diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 17c06480a856f1cea6b25968a41d6175a01c2d97..83a5d57d8aba97ec117b8cc843471084830b5469 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -31,9 +31,9 @@ jobs: conda env list pip show coverage cd $GITHUB_WORKSPACE && sh tests/retry_env.sh - cd $GITHUB_WORKSPACE && python tests/clean_coverage.py - cd $GITHUB_WORKSPACE && coverage run -m pytest tests/unittest/ --cov=magic_pdf/ --cov-report html --cov-report term-missing - cd $GITHUB_WORKSPACE && python tests/get_coverage.py + # cd $GITHUB_WORKSPACE && python tests/clean_coverage.py + # cd $GITHUB_WORKSPACE && coverage run -m pytest tests/unittest/ --cov=magic_pdf/ --cov-report html --cov-report term-missing + # cd $GITHUB_WORKSPACE && python tests/get_coverage.py cd $GITHUB_WORKSPACE && pytest -m P0 -s -v tests/test_cli/test_cli_sdk.py notify_to_feishu: diff --git a/.github/workflows/huigui.yml b/.github/workflows/huigui.yml index 8d0d55a1022f190cabcd837d39d0e610451cba01..95ceffc83375b85668612d8515326848a2ae587a 100644 --- a/.github/workflows/huigui.yml +++ b/.github/workflows/huigui.yml @@ -30,9 +30,9 @@ jobs: conda env list pip show coverage cd $GITHUB_WORKSPACE && sh tests/retry_env.sh - cd $GITHUB_WORKSPACE && python tests/clean_coverage.py - cd $GITHUB_WORKSPACE && coverage run -m pytest tests/unittest/ --cov=magic_pdf/ --cov-report html --cov-report term-missing - cd $GITHUB_WORKSPACE && python tests/get_coverage.py + # cd $GITHUB_WORKSPACE && python tests/clean_coverage.py + # cd $GITHUB_WORKSPACE && coverage run -m pytest tests/unittest/ --cov=magic_pdf/ --cov-report html --cov-report term-missing + # cd $GITHUB_WORKSPACE && python tests/get_coverage.py cd $GITHUB_WORKSPACE && pytest -s -v tests/test_cli/test_cli_sdk.py notify_to_feishu: diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 71a9e367fe6c3e26930e72da7c73f6940a7bb1c8..335d46290bda4a04c5a7336e1164728717efcd91 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -32,14 +32,14 @@ jobs: - name: Verify version.py run: | - ls -l magic_pdf/libs/version.py - cat magic_pdf/libs/version.py + ls -l mineru/version.py + cat mineru/version.py - name: Commit changes run: | git config --local user.email "moe@myhloli.com" git config --local user.name "myhloli" - git add magic_pdf/libs/version.py + git add mineru/version.py if git diff-index --quiet HEAD; then echo "No changes to commit" else @@ -71,18 +71,18 @@ jobs: - name: Verify version.py run: | - ls -l magic_pdf/libs/version.py - cat magic_pdf/libs/version.py + ls -l mineru/version.py + cat mineru/version.py - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - name: Install magic-pdf + - name: Install mineru run: | python -m pip install --upgrade pip - pip install -e .[full] + pip install -e .[all] build: needs: [ check-install ] @@ -103,10 +103,11 @@ jobs: - name: Install wheel run: | python -m pip install wheel + pip install build - name: Build wheel run: | - python setup.py bdist_wheel + python -m build --wheel - name: Upload artifact uses: actions/upload-artifact@v4 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index fc7446dfd8c83f8410d2472790c0f917bdfed2f1..0000000000000000000000000000000000000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,47 +0,0 @@ -repos: - - repo: https://github.com/PyCQA/flake8 - rev: 5.0.4 - hooks: - - id: flake8 - args: ["--max-line-length=150", "--ignore=E131,E125,W503,W504,E203"] - - repo: https://github.com/PyCQA/isort - rev: 5.11.5 - hooks: - - id: isort - - repo: https://github.com/pre-commit/mirrors-yapf - rev: v0.32.0 - hooks: - - id: yapf - args: ["--style={based_on_style: google, column_limit: 150, indent_width: 4}"] - - repo: https://github.com/codespell-project/codespell - rev: v2.2.1 - hooks: - - id: codespell - args: ['--skip', '*.json'] - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 - hooks: - - id: trailing-whitespace - - id: check-yaml - - id: end-of-file-fixer - - id: requirements-txt-fixer - - id: double-quote-string-fixer - - id: check-merge-conflict - - id: fix-encoding-pragma - args: ["--remove"] - - id: mixed-line-ending - args: ["--fix=lf"] - - repo: https://github.com/executablebooks/mdformat - rev: 0.7.9 - hooks: - - id: mdformat - args: ["--number", "--table-width", "200"] - additional_dependencies: - - mdformat-openmmlab - - mdformat_frontmatter - - linkify-it-py - - repo: https://github.com/myint/docformatter - rev: v1.3.1 - hooks: - - id: docformatter - args: ["--in-place", "--wrap-descriptions", "119"] diff --git a/.readthedocs.yaml b/.readthedocs.yaml deleted file mode 100644 index 09a7b6b14dcec50e52b2daa1a848110f14e379c3..0000000000000000000000000000000000000000 --- a/.readthedocs.yaml +++ /dev/null @@ -1,16 +0,0 @@ -version: 2 - -build: - os: ubuntu-22.04 - tools: - python: "3.10" - -formats: - - epub - -python: - install: - - requirements: next_docs/zh_cn/requirements.txt - -sphinx: - configuration: next_docs/zh_cn/conf.py diff --git a/README.md b/README.md index 09bdd782183e44b2bd8f7a4c6972516af632a7b1..cb4363b63439a1811948a59832386693e8b35393 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,17 @@ [![forks](https://img.shields.io/github/forks/opendatalab/MinerU.svg)](https://github.com/opendatalab/MinerU) [![open issues](https://img.shields.io/github/issues-raw/opendatalab/MinerU)](https://github.com/opendatalab/MinerU/issues) [![issue resolution](https://img.shields.io/github/issues-closed-raw/opendatalab/MinerU)](https://github.com/opendatalab/MinerU/issues) -[![PyPI version](https://img.shields.io/pypi/v/magic-pdf)](https://pypi.org/project/magic-pdf/) -[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/magic-pdf)](https://pypi.org/project/magic-pdf/) -[![Downloads](https://static.pepy.tech/badge/magic-pdf)](https://pepy.tech/project/magic-pdf) -[![Downloads](https://static.pepy.tech/badge/magic-pdf/month)](https://pepy.tech/project/magic-pdf) + +[![PyPI version](https://img.shields.io/pypi/v/mineru)](https://pypi.org/project/mineru/) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/mineru)](https://pypi.org/project/mineru/) +[![Downloads](https://static.pepy.tech/badge/mineru)](https://pepy.tech/project/mineru) +[![Downloads](https://static.pepy.tech/badge/mineru/month)](https://pepy.tech/project/mineru) [![OpenDataLab](https://img.shields.io/badge/Demo_on_OpenDataLab-blue?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTM0IiBoZWlnaHQ9IjEzNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMTIyLDljMCw1LTQsOS05LDlzLTktNC05LTksNC05LDktOSw5LDQsOSw5eiIgZmlsbD0idXJsKCNhKSIvPjxwYXRoIGQ9Im0xMjIsOWMwLDUtNCw5LTksOXMtOS00LTktOSw0LTksOS05LDksNCw5LDl6IiBmaWxsPSIjMDEwMTAxIi8+PHBhdGggZD0ibTkxLDE4YzAsNS00LDktOSw5cy05LTQtOS05LDQtOSw5LTksOSw0LDksOXoiIGZpbGw9InVybCgjYikiLz48cGF0aCBkPSJtOTEsMThjMCw1LTQsOS05LDlzLTktNC05LTksNC05LDktOSw5LDQsOSw5eiIgZmlsbD0iIzAxMDEwMSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJtMzksNjJjMCwxNiw4LDMwLDIwLDM4LDctNiwxMi0xNiwxMi0yNlY0OWMwLTQsMy03LDYtOGw0Ni0xMmM1LTEsMTEsMywxMSw4djMxYzAsMzctMzAsNjYtNjYsNjYtMzcsMC02Ni0zMC02Ni02NlY0NmMwLTQsMy03LDYtOGwyMC02YzUtMSwxMSwzLDExLDh2MjF6bS0yOSw2YzAsMTYsNiwzMCwxNyw0MCwzLDEsNSwxLDgsMSw1LDAsMTAtMSwxNS0zQzM3LDk1LDI5LDc5LDI5LDYyVjQybC0xOSw1djIweiIgZmlsbD0idXJsKCNjKSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJtMzksNjJjMCwxNiw4LDMwLDIwLDM4LDctNiwxMi0xNiwxMi0yNlY0OWMwLTQsMy03LDYtOGw0Ni0xMmM1LTEsMTEsMywxMSw4djMxYzAsMzctMzAsNjYtNjYsNjYtMzcsMC02Ni0zMC02Ni02NlY0NmMwLTQsMy03LDYtOGwyMC02YzUtMSwxMSwzLDExLDh2MjF6bS0yOSw2YzAsMTYsNiwzMCwxNyw0MCwzLDEsNSwxLDgsMSw1LDAsMTAtMSwxNS0zQzM3LDk1LDI5LDc5LDI5LDYyVjQybC0xOSw1djIweiIgZmlsbD0iIzAxMDEwMSIvPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iYSIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYyIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48L3N2Zz4=&labelColor=white)](https://mineru.net/OpenSourceTools/Extractor?source=github) [![HuggingFace](https://img.shields.io/badge/Demo_on_HuggingFace-yellow.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAABYCAMAAACkl9t/AAAAk1BMVEVHcEz/nQv/nQv/nQr/nQv/nQr/nQv/nQv/nQr/wRf/txT/pg7/yRr/rBD/zRz/ngv/oAz/zhz/nwv/txT/ngv/0B3+zBz/nQv/0h7/wxn/vRb/thXkuiT/rxH/pxD/ogzcqyf/nQvTlSz/czCxky7/SjifdjT/Mj3+Mj3wMj15aTnDNz+DSD9RTUBsP0FRO0Q6O0WyIxEIAAAAGHRSTlMADB8zSWF3krDDw8TJ1NbX5efv8ff9/fxKDJ9uAAAGKklEQVR42u2Z63qjOAyGC4RwCOfB2JAGqrSb2WnTw/1f3UaWcSGYNKTdf/P+mOkTrE+yJBulvfvLT2A5ruenaVHyIks33npl/6C4s/ZLAM45SOi/1FtZPyFur1OYofBX3w7d54Bxm+E8db+nDr12ttmESZ4zludJEG5S7TO72YPlKZFyE+YCYUJTBZsMiNS5Sd7NlDmKM2Eg2JQg8awbglfqgbhArjxkS7dgp2RH6hc9AMLdZYUtZN5DJr4molC8BfKrEkPKEnEVjLbgW1fLy77ZVOJagoIcLIl+IxaQZGjiX597HopF5CkaXVMDO9Pyix3AFV3kw4lQLCbHuMovz8FallbcQIJ5Ta0vks9RnolbCK84BtjKRS5uA43hYoZcOBGIG2Epbv6CvFVQ8m8loh66WNySsnN7htL58LNp+NXT8/PhXiBXPMjLSxtwp8W9f/1AngRierBkA+kk/IpUSOeKByzn8y3kAAAfh//0oXgV4roHm/kz4E2z//zRc3/lgwBzbM2mJxQEa5pqgX7d1L0htrhx7LKxOZlKbwcAWyEOWqYSI8YPtgDQVjpB5nvaHaSnBaQSD6hweDi8PosxD6/PT09YY3xQA7LTCTKfYX+QHpA0GCcqmEHvr/cyfKQTEuwgbs2kPxJEB0iNjfJcCTPyocx+A0griHSmADiC91oNGVwJ69RudYe65vJmoqfpul0lrqXadW0jFKH5BKwAeCq+Den7s+3zfRJzA61/Uj/9H/VzLKTx9jFPPdXeeP+L7WEvDLAKAIoF8bPTKT0+TM7W8ePj3Rz/Yn3kOAp2f1Kf0Weony7pn/cPydvhQYV+eFOfmOu7VB/ViPe34/EN3RFHY/yRuT8ddCtMPH/McBAT5s+vRde/gf2c/sPsjLK+m5IBQF5tO+h2tTlBGnP6693JdsvofjOPnnEHkh2TnV/X1fBl9S5zrwuwF8NFrAVJVwCAPTe8gaJlomqlp0pv4Pjn98tJ/t/fL++6unpR1YGC2n/KCoa0tTLoKiEeUPDl94nj+5/Tv3/eT5vBQ60X1S0oZr+IWRR8Ldhu7AlLjPISlJcO9vrFotky9SpzDequlwEir5beYAc0R7D9KS1DXva0jhYRDXoExPdc6yw5GShkZXe9QdO/uOvHofxjrV/TNS6iMJS+4TcSTgk9n5agJdBQbB//IfF/HpvPt3Tbi7b6I6K0R72p6ajryEJrENW2bbeVUGjfgoals4L443c7BEE4mJO2SpbRngxQrAKRudRzGQ8jVOL2qDVjjI8K1gc3TIJ5KiFZ1q+gdsARPB4NQS4AjwVSt72DSoXNyOWUrU5mQ9nRYyjp89Xo7oRI6Bga9QNT1mQ/ptaJq5T/7WcgAZywR/XlPGAUDdet3LE+qS0TI+g+aJU8MIqjo0Kx8Ly+maxLjJmjQ18rA0YCkxLQbUZP1WqdmyQGJLUm7VnQFqodmXSqmRrdVpqdzk5LvmvgtEcW8PMGdaS23EOWyDVbACZzUJPaqMbjDxpA3Qrgl0AikimGDbqmyT8P8NOYiqrldF8rX+YN7TopX4UoHuSCYY7cgX4gHwclQKl1zhx0THf+tCAUValzjI7Wg9EhptrkIcfIJjA94evOn8B2eHaVzvBrnl2ig0So6hvPaz0IGcOvTHvUIlE2+prqAxLSQxZlU2stql1NqCCLdIiIN/i1DBEHUoElM9dBravbiAnKqgpi4IBkw+utSPIoBijDXJipSVV7MpOEJUAc5Qmm3BnUN+w3hteEieYKfRZSIUcXKMVf0u5wD4EwsUNVvZOtUT7A2GkffHjByWpHqvRBYrTV72a6j8zZ6W0DTE86Hn04bmyWX3Ri9WH7ZU6Q7h+ZHo0nHUAcsQvVhXRDZHChwiyi/hnPuOsSEF6Exk3o6Y9DT1eZ+6cASXk2Y9k+6EOQMDGm6WBK10wOQJCBwren86cPPWUcRAnTVjGcU1LBgs9FURiX/e6479yZcLwCBmTxiawEwrOcleuu12t3tbLv/N4RLYIBhYexm7Fcn4OJcn0+zc+s8/VfPeddZHAGN6TT8eGczHdR/Gts1/MzDkThr23zqrVfAMFT33Nx1RJsx1k5zuWILLnG/vsH+Fv5D4NTVcp1Gzo8AAAAAElFTkSuQmCC&labelColor=white)](https://huggingface.co/spaces/opendatalab/MinerU) [![ModelScope](https://img.shields.io/badge/Demo_on_ModelScope-purple?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIzIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCiA8Zz4KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+CiAgPHBhdGggaWQ9InN2Z18xNCIgZmlsbD0iIzYyNGFmZiIgZD0ibTAsODkuODRsMjUuNjUsMGwwLDI1LjY0OTk5bC0yNS42NSwwbDAsLTI1LjY0OTk5eiIvPgogIDxwYXRoIGlkPSJzdmdfMTUiIGZpbGw9IiM2MjRhZmYiIGQ9Im05OS4xNCwxMTUuNDlsMjUuNjUsMGwwLDI1LjY1bC0yNS42NSwwbDAsLTI1LjY1eiIvPgogIDxwYXRoIGlkPSJzdmdfMTYiIGZpbGw9IiM2MjRhZmYiIGQ9Im0xNzYuMDksMTQxLjE0bC0yNS42NDk5OSwwbDAsMjIuMTlsNDcuODQsMGwwLC00Ny44NGwtMjIuMTksMGwwLDI1LjY1eiIvPgogIDxwYXRoIGlkPSJzdmdfMTciIGZpbGw9IiMzNmNmZDEiIGQ9Im0xMjQuNzksODkuODRsMjUuNjUsMGwwLDI1LjY0OTk5bC0yNS42NSwwbDAsLTI1LjY0OTk5eiIvPgogIDxwYXRoIGlkPSJzdmdfMTgiIGZpbGw9IiMzNmNmZDEiIGQ9Im0wLDY0LjE5bDI1LjY1LDBsMCwyNS42NWwtMjUuNjUsMGwwLC0yNS42NXoiLz4KICA8cGF0aCBpZD0ic3ZnXzE5IiBmaWxsPSIjNjI0YWZmIiBkPSJtMTk4LjI4LDg5Ljg0bDI1LjY0OTk5LDBsMCwyNS42NDk5OWwtMjUuNjQ5OTksMGwwLC0yNS42NDk5OXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIwIiBmaWxsPSIjMzZjZmQxIiBkPSJtMTk4LjI4LDY0LjE5bDI1LjY0OTk5LDBsMCwyNS42NWwtMjUuNjQ5OTksMGwwLC0yNS42NXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIxIiBmaWxsPSIjNjI0YWZmIiBkPSJtMTUwLjQ0LDQybDAsMjIuMTlsMjUuNjQ5OTksMGwwLDI1LjY1bDIyLjE5LDBsMCwtNDcuODRsLTQ3Ljg0LDB6Ii8+CiAgPHBhdGggaWQ9InN2Z18yMiIgZmlsbD0iIzM2Y2ZkMSIgZD0ibTczLjQ5LDg5Ljg0bDI1LjY1LDBsMCwyNS42NDk5OWwtMjUuNjUsMGwwLC0yNS42NDk5OXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIzIiBmaWxsPSIjNjI0YWZmIiBkPSJtNDcuODQsNjQuMTlsMjUuNjUsMGwwLC0yMi4xOWwtNDcuODQsMGwwLDQ3Ljg0bDIyLjE5LDBsMCwtMjUuNjV6Ii8+CiAgPHBhdGggaWQ9InN2Z18yNCIgZmlsbD0iIzYyNGFmZiIgZD0ibTQ3Ljg0LDExNS40OWwtMjIuMTksMGwwLDQ3Ljg0bDQ3Ljg0LDBsMCwtMjIuMTlsLTI1LjY1LDBsMCwtMjUuNjV6Ii8+CiA8L2c+Cjwvc3ZnPg==&labelColor=white)](https://www.modelscope.cn/studios/OpenDataLab/MinerU) + +[![HuggingFace](https://img.shields.io/badge/VLM_Demo_on_HuggingFace-yellow.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAABYCAMAAACkl9t/AAAAk1BMVEVHcEz/nQv/nQv/nQr/nQv/nQr/nQv/nQv/nQr/wRf/txT/pg7/yRr/rBD/zRz/ngv/oAz/zhz/nwv/txT/ngv/0B3+zBz/nQv/0h7/wxn/vRb/thXkuiT/rxH/pxD/ogzcqyf/nQvTlSz/czCxky7/SjifdjT/Mj3+Mj3wMj15aTnDNz+DSD9RTUBsP0FRO0Q6O0WyIxEIAAAAGHRSTlMADB8zSWF3krDDw8TJ1NbX5efv8ff9/fxKDJ9uAAAGKklEQVR42u2Z63qjOAyGC4RwCOfB2JAGqrSb2WnTw/1f3UaWcSGYNKTdf/P+mOkTrE+yJBulvfvLT2A5ruenaVHyIks33npl/6C4s/ZLAM45SOi/1FtZPyFur1OYofBX3w7d54Bxm+E8db+nDr12ttmESZ4zludJEG5S7TO72YPlKZFyE+YCYUJTBZsMiNS5Sd7NlDmKM2Eg2JQg8awbglfqgbhArjxkS7dgp2RH6hc9AMLdZYUtZN5DJr4molC8BfKrEkPKEnEVjLbgW1fLy77ZVOJagoIcLIl+IxaQZGjiX597HopF5CkaXVMDO9Pyix3AFV3kw4lQLCbHuMovz8FallbcQIJ5Ta0vks9RnolbCK84BtjKRS5uA43hYoZcOBGIG2Epbv6CvFVQ8m8loh66WNySsnN7htL58LNp+NXT8/PhXiBXPMjLSxtwp8W9f/1AngRierBkA+kk/IpUSOeKByzn8y3kAAAfh//0oXgV4roHm/kz4E2z//zRc3/lgwBzbM2mJxQEa5pqgX7d1L0htrhx7LKxOZlKbwcAWyEOWqYSI8YPtgDQVjpB5nvaHaSnBaQSD6hweDi8PosxD6/PT09YY3xQA7LTCTKfYX+QHpA0GCcqmEHvr/cyfKQTEuwgbs2kPxJEB0iNjfJcCTPyocx+A0griHSmADiC91oNGVwJ69RudYe65vJmoqfpul0lrqXadW0jFKH5BKwAeCq+Den7s+3zfRJzA61/Uj/9H/VzLKTx9jFPPdXeeP+L7WEvDLAKAIoF8bPTKT0+TM7W8ePj3Rz/Yn3kOAp2f1Kf0Weony7pn/cPydvhQYV+eFOfmOu7VB/ViPe34/EN3RFHY/yRuT8ddCtMPH/McBAT5s+vRde/gf2c/sPsjLK+m5IBQF5tO+h2tTlBGnP6693JdsvofjOPnnEHkh2TnV/X1fBl9S5zrwuwF8NFrAVJVwCAPTe8gaJlomqlp0pv4Pjn98tJ/t/fL++6unpR1YGC2n/KCoa0tTLoKiEeUPDl94nj+5/Tv3/eT5vBQ60X1S0oZr+IWRR8Ldhu7AlLjPISlJcO9vrFotky9SpzDequlwEir5beYAc0R7D9KS1DXva0jhYRDXoExPdc6yw5GShkZXe9QdO/uOvHofxjrV/TNS6iMJS+4TcSTgk9n5agJdBQbB//IfF/HpvPt3Tbi7b6I6K0R72p6ajryEJrENW2bbeVUGjfgoals4L443c7BEE4mJO2SpbRngxQrAKRudRzGQ8jVOL2qDVjjI8K1gc3TIJ5KiFZ1q+gdsARPB4NQS4AjwVSt72DSoXNyOWUrU5mQ9nRYyjp89Xo7oRI6Bga9QNT1mQ/ptaJq5T/7WcgAZywR/XlPGAUDdet3LE+qS0TI+g+aJU8MIqjo0Kx8Ly+maxLjJmjQ18rA0YCkxLQbUZP1WqdmyQGJLUm7VnQFqodmXSqmRrdVpqdzk5LvmvgtEcW8PMGdaS23EOWyDVbACZzUJPaqMbjDxpA3Qrgl0AikimGDbqmyT8P8NOYiqrldF8rX+YN7TopX4UoHuSCYY7cgX4gHwclQKl1zhx0THf+tCAUValzjI7Wg9EhptrkIcfIJjA94evOn8B2eHaVzvBrnl2ig0So6hvPaz0IGcOvTHvUIlE2+prqAxLSQxZlU2stql1NqCCLdIiIN/i1DBEHUoElM9dBravbiAnKqgpi4IBkw+utSPIoBijDXJipSVV7MpOEJUAc5Qmm3BnUN+w3hteEieYKfRZSIUcXKMVf0u5wD4EwsUNVvZOtUT7A2GkffHjByWpHqvRBYrTV72a6j8zZ6W0DTE86Hn04bmyWX3Ri9WH7ZU6Q7h+ZHo0nHUAcsQvVhXRDZHChwiyi/hnPuOsSEF6Exk3o6Y9DT1eZ+6cASXk2Y9k+6EOQMDGm6WBK10wOQJCBwren86cPPWUcRAnTVjGcU1LBgs9FURiX/e6479yZcLwCBmTxiawEwrOcleuu12t3tbLv/N4RLYIBhYexm7Fcn4OJcn0+zc+s8/VfPeddZHAGN6TT8eGczHdR/Gts1/MzDkThr23zqrVfAMFT33Nx1RJsx1k5zuWILLnG/vsH+Fv5D4NTVcp1Gzo8AAAAAElFTkSuQmCC&labelColor=white)](https://huggingface.co/spaces/opendatalab/mineru2) [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/gist/myhloli/3b3a00a4a0a61577b6c30f989092d20d/mineru_demo.ipynb) [![Paper](https://img.shields.io/badge/Paper-arXiv-green)](https://arxiv.org/abs/2409.18839) @@ -48,251 +51,344 @@ Easier to use: Just grab MinerU Desktop. No coding, no login, just a simple inte # Changelog -- 2025/05/24 1.3.12 Released - - Added support for ppocrv5 model, updated `ch_server` model to `PP-OCRv5_rec_server` and `ch_lite` model to `PP-OCRv5_rec_mobile` (model update required) - - In testing, we found that ppocrv5(server) shows some improvement for handwritten documents, but slightly lower accuracy than v4_server_doc for other document types. Therefore, the default ch model remains unchanged as `PP-OCRv4_server_rec_doc`. - - Since ppocrv5 enhances recognition capabilities for handwritten text and special characters, you can manually select ppocrv5 models for Japanese, traditional Chinese mixed scenarios and handwritten document scenarios - - You can select the appropriate model through the lang parameter `lang='ch_server'` (python api) or `--lang ch_server` (command line): - - `ch`: `PP-OCRv4_rec_server_doc` (default) (Chinese, English, Japanese, Traditional Chinese mixed/15k dictionary) - - `ch_server`: `PP-OCRv5_rec_server` (Chinese, English, Japanese, Traditional Chinese mixed + handwriting/18k dictionary) - - `ch_lite`: `PP-OCRv5_rec_mobile` (Chinese, English, Japanese, Traditional Chinese mixed + handwriting/18k dictionary) - - `ch_server_v4`: `PP-OCRv4_rec_server` (Chinese, English mixed/6k dictionary) - - `ch_lite_v4`: `PP-OCRv4_rec_mobile` (Chinese, English mixed/6k dictionary) - - Added support for handwritten documents by optimizing layout recognition of handwritten text areas - - This feature is supported by default, no additional configuration needed - - You can refer to the instructions above to manually select ppocrv5 model for better handwritten document parsing - - The demos on `huggingface` and `modelscope` have been updated to support handwriting recognition and ppocrv5 models, which you can experience online -- 2025/04/29 1.3.10 Released - - Support for custom formula delimiters can be achieved by modifying the `latex-delimiter-config` item in the `magic-pdf.json` file under the user directory. -- 2025/04/27 1.3.9 Released - - Optimized the formula parsing function to improve the success rate of formula rendering -- 2025/04/23 1.3.8 Released - - The default `ocr` model (`ch`) has been updated to `PP-OCRv4_server_rec_doc` (model update required) - - `PP-OCRv4_server_rec_doc` is trained on a mix of more Chinese document data and PP-OCR training data, enhancing recognition capabilities for some traditional Chinese characters, Japanese, and special characters. It supports over 15,000 recognizable characters, improving text recognition in documents while also boosting general text recognition. - - [Performance comparison between PP-OCRv4_server_rec_doc, PP-OCRv4_server_rec, and PP-OCRv4_mobile_rec](https://paddlepaddle.github.io/PaddleX/latest/en/module_usage/tutorials/ocr_modules/text_recognition.html#ii-supported-model-list) - - Verified results show that the `PP-OCRv4_server_rec_doc` model significantly improves accuracy in both single-language (`Chinese`, `English`, `Japanese`, `Traditional Chinese`) and mixed-language scenarios, with speed comparable to `PP-OCRv4_server_rec`, making it suitable for most use cases. - - In a small number of pure English scenarios, the `PP-OCRv4_server_rec_doc` model may encounter word concatenation issues, whereas `PP-OCRv4_server_rec` performs better in such cases. Therefore, we have retained the `PP-OCRv4_server_rec` model, which users can invoke by passing the parameter `lang='ch_server'`(python api) or `--lang ch_server`(cli). -- 2025/04/22 1.3.7 Released - - Fixed the issue where the `lang` parameter was ineffective during table parsing model initialization. - - Fixed the significant slowdown in OCR and table parsing speed in `cpu` mode. -- 2025/04/16 1.3.4 Released - - Slightly improved the speed of OCR detection by removing some unused blocks. - - Fixed page-level sorting errors caused by footnotes in certain cases. -- 2025/04/12 1.3.2 released - - Fixed the issue of incompatible dependency package versions when installing in Python 3.13 environment on Windows systems. - - Optimized memory usage during batch inference. - - Improved the parsing effect of tables rotated by 90 degrees. - - Enhanced the parsing accuracy for large tables in financial report samples. - - Fixed the occasional word concatenation issue in English text areas when OCR language is not specified.(The model needs to be updated) -- 2025/04/08 1.3.1 released, fixed some compatibility issues - - Supported Python 3.13 - - Made the final adaptation for some outdated Linux systems (e.g., CentOS 7), and no further support will be guaranteed for subsequent versions. [Installation Instructions](https://github.com/opendatalab/MinerU/issues/1004) -- 2025/04/03 1.3.0 released, in this version we made many optimizations and improvements: - - Installation and compatibility optimization - - By removing the use of `layoutlmv3` in layout, resolved compatibility issues caused by `detectron2`. - - Torch version compatibility extended to 2.2~2.6 (excluding 2.5). - - CUDA compatibility supports 11.8/12.4/12.6/12.8 (CUDA version determined by torch), resolving compatibility issues for some users with 50-series and H-series GPUs. - - Python compatible versions expanded to 3.10~3.12, solving the problem of automatic downgrade to 0.6.1 during installation in non-3.10 environments. - - Offline deployment process optimized; no internet connection required after successful deployment to download any model files. - - Performance optimization - - By supporting batch processing of multiple PDF files ([script example](demo/batch_demo.py)), improved parsing speed for small files in batches (compared to version 1.0.1, formula parsing speed increased by over 1400%, overall parsing speed increased by over 500%). - - Optimized loading and usage of the mfr model, reducing GPU memory usage and improving parsing speed (requires re-execution of the [model download process](docs/how_to_download_models_en.md) to obtain incremental updates of model files). - - Optimized GPU memory usage, requiring only a minimum of 6GB to run this project. - - Improved running speed on MPS devices. - - Parsing effect optimization - - Updated the mfr model to `unimernet(2503)`, solving the issue of lost line breaks in multi-line formulas. - - Usability Optimization - - By using `paddleocr2torch`, completely replaced the use of the `paddle` framework and `paddleocr` in the project, resolving conflicts between `paddle` and `torch`, as well as thread safety issues caused by the `paddle` framework. - - Added a real-time progress bar during the parsing process to accurately track progress, making the wait less painful. -
-2025/03/03 1.2.1 released - -
- -
-2025/02/24 1.2.0 released -

This version includes several fixes and improvements to enhance parsing efficiency and accuracy:

- -
- -
-2025/01/22 1.1.0 released -

In this version we have focused on improving parsing accuracy and efficiency:

- -
+- 2025/06/13 2.0.0 Released + - MinerU 2.0 represents a comprehensive reconstruction and upgrade from architecture to functionality, delivering a more streamlined design, enhanced performance, and more flexible user experience. + - **New Architecture**: MinerU 2.0 has been deeply restructured in code organization and interaction methods, significantly improving system usability, maintainability, and extensibility. + - **Removal of Third-party Dependency Limitations**: Completely eliminated the dependency on `pymupdf`, moving the project toward a more open and compliant open-source direction. + - **Ready-to-use, Easy Configuration**: No need to manually edit JSON configuration files; most parameters can now be set directly via command line or API. + - **Automatic Model Management**: Added automatic model download and update mechanisms, allowing users to complete model deployment without manual intervention. + - **Offline Deployment Friendly**: Provides built-in model download commands, supporting deployment requirements in completely offline environments. + - **Streamlined Code Structure**: Removed thousands of lines of redundant code, simplified class inheritance logic, significantly improving code readability and development efficiency. + - **Unified Intermediate Format Output**: Adopted standardized `middle_json` format, compatible with most secondary development scenarios based on this format, ensuring seamless ecosystem business migration. + - **New Model**: MinerU 2.0 integrates our latest small-parameter, high-performance multimodal document parsing model, achieving end-to-end high-speed, high-precision document understanding. + - **Small Model, Big Capabilities**: With parameters under 1B, yet surpassing traditional 72B-level vision-language models (VLMs) in parsing accuracy. + - **Multiple Functions in One**: A single model covers multilingual recognition, handwriting recognition, layout analysis, table parsing, formula recognition, reading order sorting, and other core tasks. + - **Ultimate Inference Speed**: Achieves peak throughput exceeding 10,000 tokens/s through `sglang` acceleration on a single NVIDIA 4090 card, easily handling large-scale document processing requirements. + - **Online Experience**: You can experience this model online on our Hugging Face demo: [![HuggingFace](https://img.shields.io/badge/VLM_Demo_on_HuggingFace-yellow.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAABYCAMAAACkl9t/AAAAk1BMVEVHcEz/nQv/nQv/nQr/nQv/nQr/nQv/nQv/nQr/wRf/txT/pg7/yRr/rBD/zRz/ngv/oAz/zhz/nwv/txT/ngv/0B3+zBz/nQv/0h7/wxn/vRb/thXkuiT/rxH/pxD/ogzcqyf/nQvTlSz/czCxky7/SjifdjT/Mj3+Mj3wMj15aTnDNz+DSD9RTUBsP0FRO0Q6O0WyIxEIAAAAGHRSTlMADB8zSWF3krDDw8TJ1NbX5efv8ff9/fxKDJ9uAAAGKklEQVR42u2Z63qjOAyGC4RwCOfB2JAGqrSb2WnTw/1f3UaWcSGYNKTdf/P+mOkTrE+yJBulvfvLT2A5ruenaVHyIks33npl/6C4s/ZLAM45SOi/1FtZPyFur1OYofBX3w7d54Bxm+E8db+nDr12ttmESZ4zludJEG5S7TO72YPlKZFyE+YCYUJTBZsMiNS5Sd7NlDmKM2Eg2JQg8awbglfqgbhArjxkS7dgp2RH6hc9AMLdZYUtZN5DJr4molC8BfKrEkPKEnEVjLbgW1fLy77ZVOJagoIcLIl+IxaQZGjiX597HopF5CkaXVMDO9Pyix3AFV3kw4lQLCbHuMovz8FallbcQIJ5Ta0vks9RnolbCK84BtjKRS5uA43hYoZcOBGIG2Epbv6CvFVQ8m8loh66WNySsnN7htL58LNp+NXT8/PhXiBXPMjLSxtwp8W9f/1AngRierBkA+kk/IpUSOeKByzn8y3kAAAfh//0oXgV4roHm/kz4E2z//zRc3/lgwBzbM2mJxQEa5pqgX7d1L0htrhx7LKxOZlKbwcAWyEOWqYSI8YPtgDQVjpB5nvaHaSnBaQSD6hweDi8PosxD6/PT09YY3xQA7LTCTKfYX+QHpA0GCcqmEHvr/cyfKQTEuwgbs2kPxJEB0iNjfJcCTPyocx+A0griHSmADiC91oNGVwJ69RudYe65vJmoqfpul0lrqXadW0jFKH5BKwAeCq+Den7s+3zfRJzA61/Uj/9H/VzLKTx9jFPPdXeeP+L7WEvDLAKAIoF8bPTKT0+TM7W8ePj3Rz/Yn3kOAp2f1Kf0Weony7pn/cPydvhQYV+eFOfmOu7VB/ViPe34/EN3RFHY/yRuT8ddCtMPH/McBAT5s+vRde/gf2c/sPsjLK+m5IBQF5tO+h2tTlBGnP6693JdsvofjOPnnEHkh2TnV/X1fBl9S5zrwuwF8NFrAVJVwCAPTe8gaJlomqlp0pv4Pjn98tJ/t/fL++6unpR1YGC2n/KCoa0tTLoKiEeUPDl94nj+5/Tv3/eT5vBQ60X1S0oZr+IWRR8Ldhu7AlLjPISlJcO9vrFotky9SpzDequlwEir5beYAc0R7D9KS1DXva0jhYRDXoExPdc6yw5GShkZXe9QdO/uOvHofxjrV/TNS6iMJS+4TcSTgk9n5agJdBQbB//IfF/HpvPt3Tbi7b6I6K0R72p6ajryEJrENW2bbeVUGjfgoals4L443c7BEE4mJO2SpbRngxQrAKRudRzGQ8jVOL2qDVjjI8K1gc3TIJ5KiFZ1q+gdsARPB4NQS4AjwVSt72DSoXNyOWUrU5mQ9nRYyjp89Xo7oRI6Bga9QNT1mQ/ptaJq5T/7WcgAZywR/XlPGAUDdet3LE+qS0TI+g+aJU8MIqjo0Kx8Ly+maxLjJmjQ18rA0YCkxLQbUZP1WqdmyQGJLUm7VnQFqodmXSqmRrdVpqdzk5LvmvgtEcW8PMGdaS23EOWyDVbACZzUJPaqMbjDxpA3Qrgl0AikimGDbqmyT8P8NOYiqrldF8rX+YN7TopX4UoHuSCYY7cgX4gHwclQKl1zhx0THf+tCAUValzjI7Wg9EhptrkIcfIJjA94evOn8B2eHaVzvBrnl2ig0So6hvPaz0IGcOvTHvUIlE2+prqAxLSQxZlU2stql1NqCCLdIiIN/i1DBEHUoElM9dBravbiAnKqgpi4IBkw+utSPIoBijDXJipSVV7MpOEJUAc5Qmm3BnUN+w3hteEieYKfRZSIUcXKMVf0u5wD4EwsUNVvZOtUT7A2GkffHjByWpHqvRBYrTV72a6j8zZ6W0DTE86Hn04bmyWX3Ri9WH7ZU6Q7h+ZHo0nHUAcsQvVhXRDZHChwiyi/hnPuOsSEF6Exk3o6Y9DT1eZ+6cASXk2Y9k+6EOQMDGm6WBK10wOQJCBwren86cPPWUcRAnTVjGcU1LBgs9FURiX/e6479yZcLwCBmTxiawEwrOcleuu12t3tbLv/N4RLYIBhYexm7Fcn4OJcn0+zc+s8/VfPeddZHAGN6TT8eGczHdR/Gts1/MzDkThr23zqrVfAMFT33Nx1RJsx1k5zuWILLnG/vsH+Fv5D4NTVcp1Gzo8AAAAAElFTkSuQmCC&labelColor=white)](https://huggingface.co/spaces/opendatalab/mineru2) + - **Incompatible Changes Notice**: To improve overall architectural rationality and long-term maintainability, this version contains some incompatible changes: + - Python package name changed from `magic-pdf` to `mineru`, and the command-line tool changed from `magic-pdf` to `mineru`. Please update your scripts and command calls accordingly. + - For modular system design and ecosystem consistency considerations, MinerU 2.0 no longer includes the LibreOffice document conversion module. If you need to process Office documents, we recommend converting them to PDF format through an independently deployed LibreOffice service before proceeding with subsequent parsing operations.
-2025/01/10 1.0.1 released -

This is our first official release, where we have introduced a completely new API interface and enhanced compatibility through extensive refactoring, as well as a brand new automatic language identification feature:

- -
- -
-2024/11/22 0.10.0 released -

Introducing hybrid OCR text extraction capabilities:

- -
- -
-2024/11/15 0.9.3 released -

Integrated RapidTable for table recognition, improving single-table parsing speed by more than 10 times, with higher accuracy and lower GPU memory usage.

-
- -
-2024/11/06 0.9.2 released -

Integrated the StructTable-InternVL2-1B model for table recognition functionality.

-
- -
-2024/10/31 0.9.0 released -

This is a major new version with extensive code refactoring, addressing numerous issues, improving performance, reducing hardware requirements, and enhancing usability:

- -
- -
-2024/09/27 Version 0.8.1 released -

Fixed some bugs, and providing a localized deployment version of the online demo and the front-end interface.

-
- -
-2024/09/09 Version 0.8.0 released -

Supporting fast deployment with Dockerfile, and launching demos on Huggingface and Modelscope.

-
- -
-2024/08/30 Version 0.7.1 released -

Add paddle tablemaster table recognition option

-
- -
-2024/08/09 Version 0.7.0b1 released -

Simplified installation process, added table recognition functionality

-
- -
-2024/08/01 Version 0.6.2b1 released -

Optimized dependency conflict issues and installation documentation

-
- -
-2024/07/05 Initial open-source release -
- - - -
-

Table of Contents

-
    -
  1. - MinerU -
      -
    • Project Introduction
    • -
    • Key Features
    • -
    • Quick Start + History Log +
      + 2025/05/24 Release 1.3.12 +
        +
      • Added support for PPOCRv5 models, updated ch_server model to PP-OCRv5_rec_server, and ch_lite model to PP-OCRv5_rec_mobile (model update required) +
          +
        • In testing, we found that PPOCRv5(server) has some improvement for handwritten documents, but has slightly lower accuracy than v4_server_doc for other document types, so the default ch model remains unchanged as PP-OCRv4_server_rec_doc.
        • +
        • Since PPOCRv5 has enhanced recognition capabilities for handwriting and special characters, you can manually choose the PPOCRv5 model for Japanese-Traditional Chinese mixed scenarios and handwritten documents
        • +
        • You can select the appropriate model through the lang parameter lang='ch_server' (Python API) or --lang ch_server (command line):
            -
          • Online Demo
          • -
          • Quick CPU Demo
          • -
          • Using GPU
          • -
          • Using NPU
          • +
          • ch: PP-OCRv4_server_rec_doc (default) (Chinese/English/Japanese/Traditional Chinese mixed/15K dictionary)
          • +
          • ch_server: PP-OCRv5_rec_server (Chinese/English/Japanese/Traditional Chinese mixed + handwriting/18K dictionary)
          • +
          • ch_lite: PP-OCRv5_rec_mobile (Chinese/English/Japanese/Traditional Chinese mixed + handwriting/18K dictionary)
          • +
          • ch_server_v4: PP-OCRv4_rec_server (Chinese/English mixed/6K dictionary)
          • +
          • ch_lite_v4: PP-OCRv4_rec_mobile (Chinese/English mixed/6K dictionary)
          -
        • -
        • Usage - -
        • + +
        +
      • +
      • Added support for handwritten documents through optimized layout recognition of handwritten text areas +
          +
        • This feature is supported by default, no additional configuration required
        • +
        • You can refer to the instructions above to manually select the PPOCRv5 model for better handwritten document parsing results
        • +
        +
      • +
      • The huggingface and modelscope demos have been updated to versions that support handwriting recognition and PPOCRv5 models, which you can experience online
      • +
      +
      + +
      + 2025/04/29 Release 1.3.10 +
        +
      • Added support for custom formula delimiters, which can be configured by modifying the latex-delimiter-config section in the magic-pdf.json file in your user directory.
      • +
      +
      + +
      + 2025/04/27 Release 1.3.9 +
        +
      • Optimized formula parsing functionality, improved formula rendering success rate
      • +
      +
      + +
      + 2025/04/23 Release 1.3.8 +
        +
      • The default ocr model (ch) has been updated to PP-OCRv4_server_rec_doc (model update required) +
          +
        • PP-OCRv4_server_rec_doc is trained on a mixture of more Chinese document data and PP-OCR training data based on PP-OCRv4_server_rec, adding recognition capabilities for some traditional Chinese characters, Japanese, and special characters. It can recognize over 15,000 characters and improves both document-specific and general text recognition abilities.
        • +
        • Performance comparison of PP-OCRv4_server_rec_doc/PP-OCRv4_server_rec/PP-OCRv4_mobile_rec
        • +
        • After verification, the PP-OCRv4_server_rec_doc model shows significant accuracy improvements in Chinese/English/Japanese/Traditional Chinese in both single language and mixed language scenarios, with comparable speed to PP-OCRv4_server_rec, making it suitable for most use cases.
        • +
        • In some pure English scenarios, PP-OCRv4_server_rec_doc may have word adhesion issues, while PP-OCRv4_server_rec performs better in these cases. Therefore, we've kept the PP-OCRv4_server_rec model, which users can access by adding the parameter lang='ch_server' (Python API) or --lang ch_server (command line).
        • +
        +
      • +
      +
      + +
      + 2025/04/22 Release 1.3.7 +
        +
      • Fixed the issue where the lang parameter was ineffective during table parsing model initialization
      • +
      • Fixed the significant speed reduction of OCR and table parsing in cpu mode
      • +
      +
      + +
      + 2025/04/16 Release 1.3.4 +
        +
      • Slightly improved OCR-det speed by removing some unnecessary blocks
      • +
      • Fixed page-internal sorting errors caused by footnotes in certain cases
      • +
      +
      + +
      + 2025/04/12 Release 1.3.2 +
        +
      • Fixed dependency version incompatibility issues when installing on Windows with Python 3.13
      • +
      • Optimized memory usage during batch inference
      • +
      • Improved parsing of tables rotated 90 degrees
      • +
      • Enhanced parsing of oversized tables in financial report samples
      • +
      • Fixed the occasional word adhesion issue in English text areas when OCR language is not specified (model update required)
      • +
      +
      + +
      + 2025/04/08 Release 1.3.1 +
        +
      • Fixed several compatibility issues +
          +
        • Added support for Python 3.13
        • +
        • Made final adaptations for outdated Linux systems (such as CentOS 7) with no guarantee of continued support in future versions, installation instructions
        • +
        +
      • +
      +
      + +
      + 2025/04/03 Release 1.3.0 +
        +
      • Installation and compatibility optimizations +
          +
        • Resolved compatibility issues caused by detectron2 by removing layoutlmv3 usage in layout
        • +
        • Extended torch version compatibility to 2.2~2.6 (excluding 2.5)
        • +
        • Added CUDA compatibility for versions 11.8/12.4/12.6/12.8 (CUDA version determined by torch), solving compatibility issues for users with 50-series and H-series GPUs
        • +
        • Extended Python compatibility to versions 3.10~3.12, fixing the issue of automatic downgrade to version 0.6.1 when installing in non-3.10 environments
        • +
        • Optimized offline deployment process, eliminating the need to download any model files after successful deployment
        • +
        +
      • +
      • Performance optimizations +
          +
        • Enhanced parsing speed for batches of small files by supporting batch processing of multiple PDF files (script example), with formula parsing speed improved by up to 1400% and overall parsing speed improved by up to 500% compared to version 1.0.1
        • +
        • Reduced memory usage and improved parsing speed by optimizing MFR model loading and usage (requires re-running the model download process to get incremental updates to model files)
        • +
        • Optimized GPU memory usage, requiring only 6GB minimum to run this project
        • +
        • Improved running speed on MPS devices
        • +
        +
      • +
      • Parsing effect optimizations +
          +
        • Updated MFR model to unimernet(2503), fixing line break loss issues in multi-line formulas
        • +
        +
      • +
      • Usability optimizations +
          +
        • Completely replaced the paddle framework and paddleocr in the project by using paddleocr2torch, resolving conflicts between paddle and torch, as well as thread safety issues caused by the paddle framework
        • +
        • Added real-time progress bar display during parsing, allowing precise tracking of parsing progress and making the waiting process more bearable
        • +
        +
      • +
      +
      +
      + 2025/03/03 1.2.1 released +
        +
      • Fixed the impact on punctuation marks during full-width to half-width conversion of letters and numbers
      • +
      • Fixed caption matching inaccuracies in certain scenarios
      • +
      • Fixed formula span loss issues in certain scenarios
      • +
      +
      + +
      + 2025/02/24 1.2.0 released +

      This version includes several fixes and improvements to enhance parsing efficiency and accuracy:

      +
        +
      • Performance Optimization +
          +
        • Increased classification speed for PDF documents in auto mode.
        • +
        +
      • +
      • Parsing Optimization +
          +
        • Improved parsing logic for documents containing watermarks, significantly enhancing the parsing results for such documents.
        • +
        • Enhanced the matching logic for multiple images/tables and captions within a single page, improving the accuracy of image-text matching in complex layouts.
        • +
        +
      • +
      • Bug Fixes +
          +
        • Fixed an issue where image/table spans were incorrectly filled into text blocks under certain conditions.
        • +
        • Resolved an issue where title blocks were empty in some cases.
      • -
      • TODO
      • -
      • Known Issues
      • -
      • FAQ
      • -
      • All Thanks To Our Contributors
      • -
      • License Information
      • -
      • Acknowledgments
      • -
      • Citation
      • -
      • Star History
      • -
      • Magic-doc
      • -
      • Magic-html
      • -
      • Links
      • -
+ +
+ +
+ 2025/01/22 1.1.0 released +

In this version we have focused on improving parsing accuracy and efficiency:

+ +
+ +
+ 2025/01/10 1.0.1 released +

This is our first official release, where we have introduced a completely new API interface and enhanced compatibility through extensive refactoring, as well as a brand new automatic language identification feature:

+ +
+ +
+ 2024/11/22 0.10.0 released +

Introducing hybrid OCR text extraction capabilities:

+ +
+ +
+ 2024/11/15 0.9.3 released +

Integrated RapidTable for table recognition, improving single-table parsing speed by more than 10 times, with higher accuracy and lower GPU memory usage.

+
+ +
+ 2024/11/06 0.9.2 released +

Integrated the StructTable-InternVL2-1B model for table recognition functionality.

+
+ +
+ 2024/10/31 0.9.0 released +

This is a major new version with extensive code refactoring, addressing numerous issues, improving performance, reducing hardware requirements, and enhancing usability:

+ +
+ +
+ 2024/09/27 Version 0.8.1 released +

Fixed some bugs, and providing a localized deployment version of the online demo and the front-end interface.

+
+ +
+ 2024/09/09 Version 0.8.0 released +

Supporting fast deployment with Dockerfile, and launching demos on Huggingface and Modelscope.

+
+ +
+ 2024/08/30 Version 0.7.1 released +

Add paddle tablemaster table recognition option

+
+ +
+ 2024/08/09 Version 0.7.0b1 released +

Simplified installation process, added table recognition functionality

+
+ +
+ 2024/08/01 Version 0.6.2b1 released +

Optimized dependency conflict issues and installation documentation

+
+ +
+ 2024/07/05 Initial open-source release +
+ + + +
+

Table of Contents

+
    +
  1. + MinerU + +
  2. +
  3. TODO
  4. +
  5. Known Issues
  6. +
  7. FAQ
  8. +
  9. All Thanks To Our Contributors
  10. +
  11. License Information
  12. +
  13. Acknowledgments
  14. +
  15. Citation
  16. +
  17. Star History
  18. +
  19. Magic-doc
  20. +
  21. Magic-html
  22. +
  23. Links
  24. +
+
# MinerU @@ -326,12 +422,9 @@ If you encounter any installation issues, please first consult the Known Issues.
There are three different ways to experience MinerU: -- [Online Demo (No Installation Required)](#online-demo) -- [Quick CPU Demo (Windows, Linux, Mac)](#quick-cpu-demo) -- Accelerate inference by using CUDA/CANN/MPS - - [Linux/Windows + CUDA](#Using-GPU) - - [Linux + CANN](#using-npu) - - [MacOS + MPS](#using-mps) +- [Online Demo](#online-demo) +- [Local Deployment](#local-deployment) + > [!WARNING] > **Pre-installation Notice—Hardware and Software Environment Support** @@ -342,182 +435,235 @@ There are three different ways to experience MinerU: > > In non-mainline environments, due to the diversity of hardware and software configurations, as well as third-party dependency compatibility issues, we cannot guarantee 100% project availability. Therefore, for users who wish to use this project in non-recommended environments, we suggest carefully reading the documentation and FAQ first. Most issues already have corresponding solutions in the FAQ. We also encourage community feedback to help us gradually expand support. - - - - +
Operating System
- - - + + + + - - - - + + + + - - + + - - + + - - + + - - - - + + + + - - - - - - - - - - - - - - - + + + +
Linux after 2019Windows 10 / 11macOS 11+Parsing Backendpipelinevlm-transformersvlm-sgslang
CPUx86_64 / arm64x86_64(unsupported ARM Windows)x86_64 / arm64Operating Systemwindows/linux/macwindows/linuxwindows(wsl2)/linux
Memory Requirements16GB or more, recommended 32GB+Memory RequirementsMinimum 16GB+, 32GB+ recommended
Storage Requirements20GB or more, with a preference for SSDDisk Space Requirements20GB+, SSD recommended
Python Version3.10~3.13Python Version3.10-3.13
Nvidia Driver Versionlatest (Proprietary Driver)latestNoneCPU Inference Support
CUDA EnvironmentRefer to the PyTorch official websiteNone
CANN Environment(NPU support)8.0+(Ascend 910b)NoneNone
GPU/MPS Hardware Support ListGPU VRAM 6GB or moreAll GPUs with Tensor Cores produced from Volta(2017) onwards.
- More than 6GB VRAM
Apple siliconGPU RequirementsTuring architecture or later, 6GB+ VRAM or Apple SiliconAmpere architecture or later, 8GB+ VRAMAmpere architecture or later, 24GB+ VRAM
-### Online Demo - -Synced with dev branch updates: +## Online Demo [![OpenDataLab](https://img.shields.io/badge/Demo_on_OpenDataLab-blue?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTM0IiBoZWlnaHQ9IjEzNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMTIyLDljMCw1LTQsOS05LDlzLTktNC05LTksNC05LDktOSw5LDQsOSw5eiIgZmlsbD0idXJsKCNhKSIvPjxwYXRoIGQ9Im0xMjIsOWMwLDUtNCw5LTksOXMtOS00LTktOSw0LTksOS05LDksNCw5LDl6IiBmaWxsPSIjMDEwMTAxIi8+PHBhdGggZD0ibTkxLDE4YzAsNS00LDktOSw5cy05LTQtOS05LDQtOSw5LTksOSw0LDksOXoiIGZpbGw9InVybCgjYikiLz48cGF0aCBkPSJtOTEsMThjMCw1LTQsOS05LDlzLTktNC05LTksNC05LDktOSw5LDQsOSw5eiIgZmlsbD0iIzAxMDEwMSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJtMzksNjJjMCwxNiw4LDMwLDIwLDM4LDctNiwxMi0xNiwxMi0yNlY0OWMwLTQsMy03LDYtOGw0Ni0xMmM1LTEsMTEsMywxMSw4djMxYzAsMzctMzAsNjYtNjYsNjYtMzcsMC02Ni0zMC02Ni02NlY0NmMwLTQsMy03LDYtOGwyMC02YzUtMSwxMSwzLDExLDh2MjF6bS0yOSw2YzAsMTYsNiwzMCwxNyw0MCwzLDEsNSwxLDgsMSw1LDAsMTAtMSwxNS0zQzM3LDk1LDI5LDc5LDI5LDYyVjQybC0xOSw1djIweiIgZmlsbD0idXJsKCNjKSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJtMzksNjJjMCwxNiw4LDMwLDIwLDM4LDctNiwxMi0xNiwxMi0yNlY0OWMwLTQsMy03LDYtOGw0Ni0xMmM1LTEsMTEsMywxMSw4djMxYzAsMzctMzAsNjYtNjYsNjYtMzcsMC02Ni0zMC02Ni02NlY0NmMwLTQsMy03LDYtOGwyMC02YzUtMSwxMSwzLDExLDh2MjF6bS0yOSw2YzAsMTYsNiwzMCwxNyw0MCwzLDEsNSwxLDgsMSw1LDAsMTAtMSwxNS0zQzM3LDk1LDI5LDc5LDI5LDYyVjQybC0xOSw1djIweiIgZmlsbD0iIzAxMDEwMSIvPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iYSIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYyIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48L3N2Zz4=&labelColor=white)](https://mineru.net/OpenSourceTools/Extractor?source=github) [![HuggingFace](https://img.shields.io/badge/Demo_on_HuggingFace-yellow.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAABYCAMAAACkl9t/AAAAk1BMVEVHcEz/nQv/nQv/nQr/nQv/nQr/nQv/nQv/nQr/wRf/txT/pg7/yRr/rBD/zRz/ngv/oAz/zhz/nwv/txT/ngv/0B3+zBz/nQv/0h7/wxn/vRb/thXkuiT/rxH/pxD/ogzcqyf/nQvTlSz/czCxky7/SjifdjT/Mj3+Mj3wMj15aTnDNz+DSD9RTUBsP0FRO0Q6O0WyIxEIAAAAGHRSTlMADB8zSWF3krDDw8TJ1NbX5efv8ff9/fxKDJ9uAAAGKklEQVR42u2Z63qjOAyGC4RwCOfB2JAGqrSb2WnTw/1f3UaWcSGYNKTdf/P+mOkTrE+yJBulvfvLT2A5ruenaVHyIks33npl/6C4s/ZLAM45SOi/1FtZPyFur1OYofBX3w7d54Bxm+E8db+nDr12ttmESZ4zludJEG5S7TO72YPlKZFyE+YCYUJTBZsMiNS5Sd7NlDmKM2Eg2JQg8awbglfqgbhArjxkS7dgp2RH6hc9AMLdZYUtZN5DJr4molC8BfKrEkPKEnEVjLbgW1fLy77ZVOJagoIcLIl+IxaQZGjiX597HopF5CkaXVMDO9Pyix3AFV3kw4lQLCbHuMovz8FallbcQIJ5Ta0vks9RnolbCK84BtjKRS5uA43hYoZcOBGIG2Epbv6CvFVQ8m8loh66WNySsnN7htL58LNp+NXT8/PhXiBXPMjLSxtwp8W9f/1AngRierBkA+kk/IpUSOeKByzn8y3kAAAfh//0oXgV4roHm/kz4E2z//zRc3/lgwBzbM2mJxQEa5pqgX7d1L0htrhx7LKxOZlKbwcAWyEOWqYSI8YPtgDQVjpB5nvaHaSnBaQSD6hweDi8PosxD6/PT09YY3xQA7LTCTKfYX+QHpA0GCcqmEHvr/cyfKQTEuwgbs2kPxJEB0iNjfJcCTPyocx+A0griHSmADiC91oNGVwJ69RudYe65vJmoqfpul0lrqXadW0jFKH5BKwAeCq+Den7s+3zfRJzA61/Uj/9H/VzLKTx9jFPPdXeeP+L7WEvDLAKAIoF8bPTKT0+TM7W8ePj3Rz/Yn3kOAp2f1Kf0Weony7pn/cPydvhQYV+eFOfmOu7VB/ViPe34/EN3RFHY/yRuT8ddCtMPH/McBAT5s+vRde/gf2c/sPsjLK+m5IBQF5tO+h2tTlBGnP6693JdsvofjOPnnEHkh2TnV/X1fBl9S5zrwuwF8NFrAVJVwCAPTe8gaJlomqlp0pv4Pjn98tJ/t/fL++6unpR1YGC2n/KCoa0tTLoKiEeUPDl94nj+5/Tv3/eT5vBQ60X1S0oZr+IWRR8Ldhu7AlLjPISlJcO9vrFotky9SpzDequlwEir5beYAc0R7D9KS1DXva0jhYRDXoExPdc6yw5GShkZXe9QdO/uOvHofxjrV/TNS6iMJS+4TcSTgk9n5agJdBQbB//IfF/HpvPt3Tbi7b6I6K0R72p6ajryEJrENW2bbeVUGjfgoals4L443c7BEE4mJO2SpbRngxQrAKRudRzGQ8jVOL2qDVjjI8K1gc3TIJ5KiFZ1q+gdsARPB4NQS4AjwVSt72DSoXNyOWUrU5mQ9nRYyjp89Xo7oRI6Bga9QNT1mQ/ptaJq5T/7WcgAZywR/XlPGAUDdet3LE+qS0TI+g+aJU8MIqjo0Kx8Ly+maxLjJmjQ18rA0YCkxLQbUZP1WqdmyQGJLUm7VnQFqodmXSqmRrdVpqdzk5LvmvgtEcW8PMGdaS23EOWyDVbACZzUJPaqMbjDxpA3Qrgl0AikimGDbqmyT8P8NOYiqrldF8rX+YN7TopX4UoHuSCYY7cgX4gHwclQKl1zhx0THf+tCAUValzjI7Wg9EhptrkIcfIJjA94evOn8B2eHaVzvBrnl2ig0So6hvPaz0IGcOvTHvUIlE2+prqAxLSQxZlU2stql1NqCCLdIiIN/i1DBEHUoElM9dBravbiAnKqgpi4IBkw+utSPIoBijDXJipSVV7MpOEJUAc5Qmm3BnUN+w3hteEieYKfRZSIUcXKMVf0u5wD4EwsUNVvZOtUT7A2GkffHjByWpHqvRBYrTV72a6j8zZ6W0DTE86Hn04bmyWX3Ri9WH7ZU6Q7h+ZHo0nHUAcsQvVhXRDZHChwiyi/hnPuOsSEF6Exk3o6Y9DT1eZ+6cASXk2Y9k+6EOQMDGm6WBK10wOQJCBwren86cPPWUcRAnTVjGcU1LBgs9FURiX/e6479yZcLwCBmTxiawEwrOcleuu12t3tbLv/N4RLYIBhYexm7Fcn4OJcn0+zc+s8/VfPeddZHAGN6TT8eGczHdR/Gts1/MzDkThr23zqrVfAMFT33Nx1RJsx1k5zuWILLnG/vsH+Fv5D4NTVcp1Gzo8AAAAAElFTkSuQmCC&labelColor=white)](https://huggingface.co/spaces/opendatalab/MinerU) [![ModelScope](https://img.shields.io/badge/Demo_on_ModelScope-purple?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIzIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCiA8Zz4KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+CiAgPHBhdGggaWQ9InN2Z18xNCIgZmlsbD0iIzYyNGFmZiIgZD0ibTAsODkuODRsMjUuNjUsMGwwLDI1LjY0OTk5bC0yNS42NSwwbDAsLTI1LjY0OTk5eiIvPgogIDxwYXRoIGlkPSJzdmdfMTUiIGZpbGw9IiM2MjRhZmYiIGQ9Im05OS4xNCwxMTUuNDlsMjUuNjUsMGwwLDI1LjY1bC0yNS42NSwwbDAsLTI1LjY1eiIvPgogIDxwYXRoIGlkPSJzdmdfMTYiIGZpbGw9IiM2MjRhZmYiIGQ9Im0xNzYuMDksMTQxLjE0bC0yNS42NDk5OSwwbDAsMjIuMTlsNDcuODQsMGwwLC00Ny44NGwtMjIuMTksMGwwLDI1LjY1eiIvPgogIDxwYXRoIGlkPSJzdmdfMTciIGZpbGw9IiMzNmNmZDEiIGQ9Im0xMjQuNzksODkuODRsMjUuNjUsMGwwLDI1LjY0OTk5bC0yNS42NSwwbDAsLTI1LjY0OTk5eiIvPgogIDxwYXRoIGlkPSJzdmdfMTgiIGZpbGw9IiMzNmNmZDEiIGQ9Im0wLDY0LjE5bDI1LjY1LDBsMCwyNS42NWwtMjUuNjUsMGwwLC0yNS42NXoiLz4KICA8cGF0aCBpZD0ic3ZnXzE5IiBmaWxsPSIjNjI0YWZmIiBkPSJtMTk4LjI4LDg5Ljg0bDI1LjY0OTk5LDBsMCwyNS42NDk5OWwtMjUuNjQ5OTksMGwwLC0yNS42NDk5OXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIwIiBmaWxsPSIjMzZjZmQxIiBkPSJtMTk4LjI4LDY0LjE5bDI1LjY0OTk5LDBsMCwyNS42NWwtMjUuNjQ5OTksMGwwLC0yNS42NXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIxIiBmaWxsPSIjNjI0YWZmIiBkPSJtMTUwLjQ0LDQybDAsMjIuMTlsMjUuNjQ5OTksMGwwLDI1LjY1bDIyLjE5LDBsMCwtNDcuODRsLTQ3Ljg0LDB6Ii8+CiAgPHBhdGggaWQ9InN2Z18yMiIgZmlsbD0iIzM2Y2ZkMSIgZD0ibTczLjQ5LDg5Ljg0bDI1LjY1LDBsMCwyNS42NDk5OWwtMjUuNjUsMGwwLC0yNS42NDk5OXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIzIiBmaWxsPSIjNjI0YWZmIiBkPSJtNDcuODQsNjQuMTlsMjUuNjUsMGwwLC0yMi4xOWwtNDcuODQsMGwwLDQ3Ljg0bDIyLjE5LDBsMCwtMjUuNjV6Ii8+CiAgPHBhdGggaWQ9InN2Z18yNCIgZmlsbD0iIzYyNGFmZiIgZD0ibTQ3Ljg0LDExNS40OWwtMjIuMTksMGwwLDQ3Ljg0bDQ3Ljg0LDBsMCwtMjIuMTlsLTI1LjY1LDBsMCwtMjUuNjV6Ii8+CiA8L2c+Cjwvc3ZnPg==&labelColor=white)](https://www.modelscope.cn/studios/OpenDataLab/MinerU) -### Quick CPU Demo +### 🚀🚀🚀VLM demo +[![HuggingFace](https://img.shields.io/badge/VLM_Demo_on_HuggingFace-yellow.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAABYCAMAAACkl9t/AAAAk1BMVEVHcEz/nQv/nQv/nQr/nQv/nQr/nQv/nQv/nQr/wRf/txT/pg7/yRr/rBD/zRz/ngv/oAz/zhz/nwv/txT/ngv/0B3+zBz/nQv/0h7/wxn/vRb/thXkuiT/rxH/pxD/ogzcqyf/nQvTlSz/czCxky7/SjifdjT/Mj3+Mj3wMj15aTnDNz+DSD9RTUBsP0FRO0Q6O0WyIxEIAAAAGHRSTlMADB8zSWF3krDDw8TJ1NbX5efv8ff9/fxKDJ9uAAAGKklEQVR42u2Z63qjOAyGC4RwCOfB2JAGqrSb2WnTw/1f3UaWcSGYNKTdf/P+mOkTrE+yJBulvfvLT2A5ruenaVHyIks33npl/6C4s/ZLAM45SOi/1FtZPyFur1OYofBX3w7d54Bxm+E8db+nDr12ttmESZ4zludJEG5S7TO72YPlKZFyE+YCYUJTBZsMiNS5Sd7NlDmKM2Eg2JQg8awbglfqgbhArjxkS7dgp2RH6hc9AMLdZYUtZN5DJr4molC8BfKrEkPKEnEVjLbgW1fLy77ZVOJagoIcLIl+IxaQZGjiX597HopF5CkaXVMDO9Pyix3AFV3kw4lQLCbHuMovz8FallbcQIJ5Ta0vks9RnolbCK84BtjKRS5uA43hYoZcOBGIG2Epbv6CvFVQ8m8loh66WNySsnN7htL58LNp+NXT8/PhXiBXPMjLSxtwp8W9f/1AngRierBkA+kk/IpUSOeKByzn8y3kAAAfh//0oXgV4roHm/kz4E2z//zRc3/lgwBzbM2mJxQEa5pqgX7d1L0htrhx7LKxOZlKbwcAWyEOWqYSI8YPtgDQVjpB5nvaHaSnBaQSD6hweDi8PosxD6/PT09YY3xQA7LTCTKfYX+QHpA0GCcqmEHvr/cyfKQTEuwgbs2kPxJEB0iNjfJcCTPyocx+A0griHSmADiC91oNGVwJ69RudYe65vJmoqfpul0lrqXadW0jFKH5BKwAeCq+Den7s+3zfRJzA61/Uj/9H/VzLKTx9jFPPdXeeP+L7WEvDLAKAIoF8bPTKT0+TM7W8ePj3Rz/Yn3kOAp2f1Kf0Weony7pn/cPydvhQYV+eFOfmOu7VB/ViPe34/EN3RFHY/yRuT8ddCtMPH/McBAT5s+vRde/gf2c/sPsjLK+m5IBQF5tO+h2tTlBGnP6693JdsvofjOPnnEHkh2TnV/X1fBl9S5zrwuwF8NFrAVJVwCAPTe8gaJlomqlp0pv4Pjn98tJ/t/fL++6unpR1YGC2n/KCoa0tTLoKiEeUPDl94nj+5/Tv3/eT5vBQ60X1S0oZr+IWRR8Ldhu7AlLjPISlJcO9vrFotky9SpzDequlwEir5beYAc0R7D9KS1DXva0jhYRDXoExPdc6yw5GShkZXe9QdO/uOvHofxjrV/TNS6iMJS+4TcSTgk9n5agJdBQbB//IfF/HpvPt3Tbi7b6I6K0R72p6ajryEJrENW2bbeVUGjfgoals4L443c7BEE4mJO2SpbRngxQrAKRudRzGQ8jVOL2qDVjjI8K1gc3TIJ5KiFZ1q+gdsARPB4NQS4AjwVSt72DSoXNyOWUrU5mQ9nRYyjp89Xo7oRI6Bga9QNT1mQ/ptaJq5T/7WcgAZywR/XlPGAUDdet3LE+qS0TI+g+aJU8MIqjo0Kx8Ly+maxLjJmjQ18rA0YCkxLQbUZP1WqdmyQGJLUm7VnQFqodmXSqmRrdVpqdzk5LvmvgtEcW8PMGdaS23EOWyDVbACZzUJPaqMbjDxpA3Qrgl0AikimGDbqmyT8P8NOYiqrldF8rX+YN7TopX4UoHuSCYY7cgX4gHwclQKl1zhx0THf+tCAUValzjI7Wg9EhptrkIcfIJjA94evOn8B2eHaVzvBrnl2ig0So6hvPaz0IGcOvTHvUIlE2+prqAxLSQxZlU2stql1NqCCLdIiIN/i1DBEHUoElM9dBravbiAnKqgpi4IBkw+utSPIoBijDXJipSVV7MpOEJUAc5Qmm3BnUN+w3hteEieYKfRZSIUcXKMVf0u5wD4EwsUNVvZOtUT7A2GkffHjByWpHqvRBYrTV72a6j8zZ6W0DTE86Hn04bmyWX3Ri9WH7ZU6Q7h+ZHo0nHUAcsQvVhXRDZHChwiyi/hnPuOsSEF6Exk3o6Y9DT1eZ+6cASXk2Y9k+6EOQMDGm6WBK10wOQJCBwren86cPPWUcRAnTVjGcU1LBgs9FURiX/e6479yZcLwCBmTxiawEwrOcleuu12t3tbLv/N4RLYIBhYexm7Fcn4OJcn0+zc+s8/VfPeddZHAGN6TT8eGczHdR/Gts1/MzDkThr23zqrVfAMFT33Nx1RJsx1k5zuWILLnG/vsH+Fv5D4NTVcp1Gzo8AAAAAElFTkSuQmCC&labelColor=white)](https://huggingface.co/spaces/opendatalab/mineru2) + +## Local Deployment + +### 1. Install MinerU + +#### 1.1 Install via pip or uv + +```bash +pip install --upgrade pip +pip install uv +uv pip install "mineru[core]>=2.0.0" +``` -#### 1. Install magic-pdf +#### 1.2 Install from source ```bash -conda create -n mineru 'python=3.12' -y -conda activate mineru -pip install -U "magic-pdf[full]" +git clone https://github.com/opendatalab/MinerU.git +cd MinerU +uv pip install -e .[core] ``` -#### 2. Download model weight files +#### 1.3 Install full version (with sglang acceleration) -Refer to [How to Download Model Files](docs/how_to_download_models_en.md) for detailed instructions. +To use **sglang acceleration for VLM model inference**, install the full version: -#### 3. Modify the Configuration File for Additional Configuration +```bash +uv pip install "mineru[all]>=2.0.0" +``` -After completing the [2. Download model weight files](#2-download-model-weight-files) step, the script will automatically generate a `magic-pdf.json` file in the user directory and configure the default model path. -You can find the `magic-pdf.json` file in your 【user directory】. +Or install from source: -> [!TIP] -> The user directory for Windows is "C:\\Users\\username", for Linux it is "/home/username", and for macOS it is "/Users/username". +```bash +uv pip install -e .[all] +``` -You can modify certain configurations in this file to enable or disable features, such as table recognition: +--- +### 2. Using MinerU -> [!NOTE] -> If the following items are not present in the JSON, please manually add the required items and remove the comment content (standard JSON does not support comments). +#### 2.1 Command Line Usage -```json -{ - // other config - "layout-config": { - "model": "doclayout_yolo" - }, - "formula-config": { - "mfd_model": "yolo_v8_mfd", - "mfr_model": "unimernet_small", - "enable": true // The formula recognition feature is enabled by default. If you need to disable it, please change the value here to "false". - }, - "table-config": { - "model": "rapid_table", - "sub_model": "slanet_plus", - "enable": true, // The table recognition feature is enabled by default. If you need to disable it, please change the value here to "false". - "max_time": 400 - } -} +##### Basic Usage + +The simplest command line invocation is: + +```bash +mineru -p -o ``` -### Using GPU +- ``: Local PDF file or directory (supports pdf/png/jpg/jpeg) +- ``: Output directory -If your device supports CUDA and meets the GPU requirements of the mainline environment, you can use GPU acceleration. Please select the appropriate guide based on your system: +##### View Help Information -- [Ubuntu 22.04 LTS + GPU](docs/README_Ubuntu_CUDA_Acceleration_en_US.md) -- [Windows 10/11 + GPU](docs/README_Windows_CUDA_Acceleration_en_US.md) -- Quick Deployment with Docker -> [!IMPORTANT] -> Docker requires a GPU with at least 6GB of VRAM, and all acceleration features are enabled by default. -> -> Before running this Docker, you can use the following command to check if your device supports CUDA acceleration on Docker. -> -> ```bash -> docker run --rm --gpus=all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi -> ``` - ```bash - wget https://github.com/opendatalab/MinerU/raw/master/docker/global/Dockerfile -O Dockerfile - docker build -t mineru:latest . - docker run -it --name mineru --gpus=all mineru:latest /bin/bash -c "echo 'source /opt/mineru_venv/bin/activate' >> ~/.bashrc && exec bash" - magic-pdf --help - ``` +Get all available parameter descriptions: -### Using NPU +```bash +mineru --help +``` -If your device has NPU acceleration hardware, you can follow the tutorial below to use NPU acceleration: +##### Parameter Details + +```text +Usage: mineru [OPTIONS] + +Options: + -v, --version Show version and exit + -p, --path PATH Input file path or directory (required) + -o, --output PATH Output directory (required) + -m, --method [auto|txt|ocr] Parsing method: auto (default), txt, ocr (pipeline backend only) + -b, --backend [pipeline|vlm-transformers|vlm-sglang-engine|vlm-sglang-client] + Parsing backend (default: pipeline) + -l, --lang [ch|ch_server|... ] Specify document language (improves OCR accuracy, pipeline backend only) + -u, --url TEXT Service address when using sglang-client + -s, --start INTEGER Starting page number (0-based) + -e, --end INTEGER Ending page number (0-based) + -f, --formula BOOLEAN Enable formula parsing (default: on, pipeline backend only) + -t, --table BOOLEAN Enable table parsing (default: on, pipeline backend only) + -d, --device TEXT Inference device (e.g., cpu/cuda/cuda:0/npu/mps, pipeline backend only) + --vram INTEGER Maximum GPU VRAM usage per process (pipeline backend only) + --source [huggingface|modelscope|local] + Model source, default: huggingface + --help Show help information +``` -[Ascend NPU Acceleration](docs/README_Ascend_NPU_Acceleration_zh_CN.md) +--- -### Using MPS +#### 2.2 Model Source Configuration -If your device uses Apple silicon chips, you can enable MPS acceleration for your tasks. +MinerU automatically downloads required models from HuggingFace on first run. If HuggingFace is inaccessible, you can switch model sources: -You can enable MPS acceleration by setting the `device-mode` parameter to `mps` in the `magic-pdf.json` configuration file. +##### Switch to ModelScope Source -```json -{ - // other config - "device-mode": "mps" -} +```bash +mineru -p -o --source modelscope +``` + +Or set environment variable: + +```bash +export MINERU_MODEL_SOURCE=modelscope +mineru -p -o +``` + +##### Using Local Models + +###### 1. Download Models Locally + +```bash +mineru-models-download --help +``` + +Or use interactive command-line tool to select models: + +```bash +mineru-models-download +``` + +After download, model paths will be displayed in current terminal and automatically written to `mineru.json` in user directory. + +###### 2. Parse Using Local Models + +```bash +mineru -p -o --source local ``` +Or enable via environment variable: -## Usage +```bash +export MINERU_MODEL_SOURCE=local +mineru -p -o +``` + +--- + +#### 2.3 Using sglang to Accelerate VLM Model Inference + +##### Start sglang-engine Mode + +```bash +mineru -p -o -b vlm-sglang-engine +``` + +##### Start sglang-server/client Mode + +1. Start Server: + +```bash +mineru-sglang-server --port 30000 +``` + +2. Use Client in another terminal: + +```bash +mineru -p -o -b vlm-sglang-client -u http://127.0.0.1:30000 +``` -### Command Line +> 💡 For more information about output files, please refer to [Output File Documentation](docs/output_file_en_us.md) -[Using MinerU via Command Line](https://mineru.readthedocs.io/en/latest/user_guide/usage/command_line.html) +--- -> [!TIP] -> For more information about the output files, please refer to the [Output File Description](docs/output_file_en_us.md). +### 3. API Usage -### API +You can also call MinerU through Python code, see example code at: +👉 [Python Usage Example](demo/demo.py) -[Using MinerU via Python API](https://mineru.readthedocs.io/en/latest/user_guide/usage/api.html) +--- +### 4. Deploy Derivative Projects -### Deploy Derived Projects +Community developers have created various extensions based on MinerU, including: -Derived projects include secondary development projects based on MinerU by project developers and community developers, -such as application interfaces based on Gradio, RAG based on llama, web demos similar to the official website, lightweight multi-GPU load balancing client/server ends, etc. -These projects may offer more features and a better user experience. -For specific deployment methods, please refer to the [Derived Project README](projects/README.md) +- Graphical interface based on Gradio +- Web API based on FastAPI +- Client/server architecture with multi-GPU load balancing, etc. +These projects typically offer better user experience and additional features. -### Development Guide +For detailed deployment instructions, please refer to: +👉 [Derivative Projects Documentation](projects/README.md) -TODO +--- # TODO @@ -556,21 +702,22 @@ TODO [LICENSE.md](LICENSE.md) -This project currently uses PyMuPDF to achieve advanced functionality. However, since it adheres to the AGPL license, it may impose restrictions on certain usage scenarios. In future iterations, we plan to explore and replace it with a more permissive PDF processing library to enhance user-friendliness and flexibility. +Currently, some models in this project are trained based on YOLO. However, since YOLO follows the AGPL license, it may impose restrictions on certain use cases. In future iterations, we plan to explore and replace these with models under more permissive licenses to enhance user-friendliness and flexibility. # Acknowledgments - [PDF-Extract-Kit](https://github.com/opendatalab/PDF-Extract-Kit) - [DocLayout-YOLO](https://github.com/opendatalab/DocLayout-YOLO) -- [StructEqTable](https://github.com/UniModal4Reasoning/StructEqTable-Deploy) +- [UniMERNet](https://github.com/opendatalab/UniMERNet) - [RapidTable](https://github.com/RapidAI/RapidTable) - [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) -- [RapidOCR](https://github.com/RapidAI/RapidOCR) - [PaddleOCR2Pytorch](https://github.com/frotms/PaddleOCR2Pytorch) -- [PyMuPDF](https://github.com/pymupdf/PyMuPDF) - [layoutreader](https://github.com/ppaanngggg/layoutreader) +- [xy-cut](https://github.com/Sanster/xy-cut) - [fast-langdetect](https://github.com/LlmKira/fast-langdetect) +- [pypdfium2](https://github.com/pypdfium2-team/pypdfium2) - [pdfminer.six](https://github.com/pdfminer/pdfminer.six) +- [pypdf](https://github.com/py-pdf/pypdf) # Citation diff --git a/README_zh-CN.md b/README_zh-CN.md index 69512ae20ff33d67233beeba345c60551c9103cf..9826aa6343ee090d6f409fa7d2cdbb61c33c58ba 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -10,14 +10,17 @@ [![forks](https://img.shields.io/github/forks/opendatalab/MinerU.svg)](https://github.com/opendatalab/MinerU) [![open issues](https://img.shields.io/github/issues-raw/opendatalab/MinerU)](https://github.com/opendatalab/MinerU/issues) [![issue resolution](https://img.shields.io/github/issues-closed-raw/opendatalab/MinerU)](https://github.com/opendatalab/MinerU/issues) -[![PyPI version](https://img.shields.io/pypi/v/magic-pdf)](https://pypi.org/project/magic-pdf/) -[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/magic-pdf)](https://pypi.org/project/magic-pdf/) -[![Downloads](https://static.pepy.tech/badge/magic-pdf)](https://pepy.tech/project/magic-pdf) -[![Downloads](https://static.pepy.tech/badge/magic-pdf/month)](https://pepy.tech/project/magic-pdf) + +[![PyPI version](https://img.shields.io/pypi/v/mineru)](https://pypi.org/project/mineru/) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/mineru)](https://pypi.org/project/mineru/) +[![Downloads](https://static.pepy.tech/badge/mineru)](https://pepy.tech/project/mineru) +[![Downloads](https://static.pepy.tech/badge/mineru/month)](https://pepy.tech/project/mineru) [![OpenDataLab](https://img.shields.io/badge/Demo_on_OpenDataLab-blue?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTM0IiBoZWlnaHQ9IjEzNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMTIyLDljMCw1LTQsOS05LDlzLTktNC05LTksNC05LDktOSw5LDQsOSw5eiIgZmlsbD0idXJsKCNhKSIvPjxwYXRoIGQ9Im0xMjIsOWMwLDUtNCw5LTksOXMtOS00LTktOSw0LTksOS05LDksNCw5LDl6IiBmaWxsPSIjMDEwMTAxIi8+PHBhdGggZD0ibTkxLDE4YzAsNS00LDktOSw5cy05LTQtOS05LDQtOSw5LTksOSw0LDksOXoiIGZpbGw9InVybCgjYikiLz48cGF0aCBkPSJtOTEsMThjMCw1LTQsOS05LDlzLTktNC05LTksNC05LDktOSw5LDQsOSw5eiIgZmlsbD0iIzAxMDEwMSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJtMzksNjJjMCwxNiw4LDMwLDIwLDM4LDctNiwxMi0xNiwxMi0yNlY0OWMwLTQsMy03LDYtOGw0Ni0xMmM1LTEsMTEsMywxMSw4djMxYzAsMzctMzAsNjYtNjYsNjYtMzcsMC02Ni0zMC02Ni02NlY0NmMwLTQsMy03LDYtOGwyMC02YzUtMSwxMSwzLDExLDh2MjF6bS0yOSw2YzAsMTYsNiwzMCwxNyw0MCwzLDEsNSwxLDgsMSw1LDAsMTAtMSwxNS0zQzM3LDk1LDI5LDc5LDI5LDYyVjQybC0xOSw1djIweiIgZmlsbD0idXJsKCNjKSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJtMzksNjJjMCwxNiw4LDMwLDIwLDM4LDctNiwxMi0xNiwxMi0yNlY0OWMwLTQsMy03LDYtOGw0Ni0xMmM1LTEsMTEsMywxMSw4djMxYzAsMzctMzAsNjYtNjYsNjYtMzcsMC02Ni0zMC02Ni02NlY0NmMwLTQsMy03LDYtOGwyMC02YzUtMSwxMSwzLDExLDh2MjF6bS0yOSw2YzAsMTYsNiwzMCwxNyw0MCwzLDEsNSwxLDgsMSw1LDAsMTAtMSwxNS0zQzM3LDk1LDI5LDc5LDI5LDYyVjQybC0xOSw1djIweiIgZmlsbD0iIzAxMDEwMSIvPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iYSIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYyIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48L3N2Zz4=&labelColor=white)](https://mineru.net/OpenSourceTools/Extractor?source=github) [![ModelScope](https://img.shields.io/badge/Demo_on_ModelScope-purple?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIzIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCiA8Zz4KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+CiAgPHBhdGggaWQ9InN2Z18xNCIgZmlsbD0iIzYyNGFmZiIgZD0ibTAsODkuODRsMjUuNjUsMGwwLDI1LjY0OTk5bC0yNS42NSwwbDAsLTI1LjY0OTk5eiIvPgogIDxwYXRoIGlkPSJzdmdfMTUiIGZpbGw9IiM2MjRhZmYiIGQ9Im05OS4xNCwxMTUuNDlsMjUuNjUsMGwwLDI1LjY1bC0yNS42NSwwbDAsLTI1LjY1eiIvPgogIDxwYXRoIGlkPSJzdmdfMTYiIGZpbGw9IiM2MjRhZmYiIGQ9Im0xNzYuMDksMTQxLjE0bC0yNS42NDk5OSwwbDAsMjIuMTlsNDcuODQsMGwwLC00Ny44NGwtMjIuMTksMGwwLDI1LjY1eiIvPgogIDxwYXRoIGlkPSJzdmdfMTciIGZpbGw9IiMzNmNmZDEiIGQ9Im0xMjQuNzksODkuODRsMjUuNjUsMGwwLDI1LjY0OTk5bC0yNS42NSwwbDAsLTI1LjY0OTk5eiIvPgogIDxwYXRoIGlkPSJzdmdfMTgiIGZpbGw9IiMzNmNmZDEiIGQ9Im0wLDY0LjE5bDI1LjY1LDBsMCwyNS42NWwtMjUuNjUsMGwwLC0yNS42NXoiLz4KICA8cGF0aCBpZD0ic3ZnXzE5IiBmaWxsPSIjNjI0YWZmIiBkPSJtMTk4LjI4LDg5Ljg0bDI1LjY0OTk5LDBsMCwyNS42NDk5OWwtMjUuNjQ5OTksMGwwLC0yNS42NDk5OXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIwIiBmaWxsPSIjMzZjZmQxIiBkPSJtMTk4LjI4LDY0LjE5bDI1LjY0OTk5LDBsMCwyNS42NWwtMjUuNjQ5OTksMGwwLC0yNS42NXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIxIiBmaWxsPSIjNjI0YWZmIiBkPSJtMTUwLjQ0LDQybDAsMjIuMTlsMjUuNjQ5OTksMGwwLDI1LjY1bDIyLjE5LDBsMCwtNDcuODRsLTQ3Ljg0LDB6Ii8+CiAgPHBhdGggaWQ9InN2Z18yMiIgZmlsbD0iIzM2Y2ZkMSIgZD0ibTczLjQ5LDg5Ljg0bDI1LjY1LDBsMCwyNS42NDk5OWwtMjUuNjUsMGwwLC0yNS42NDk5OXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIzIiBmaWxsPSIjNjI0YWZmIiBkPSJtNDcuODQsNjQuMTlsMjUuNjUsMGwwLC0yMi4xOWwtNDcuODQsMGwwLDQ3Ljg0bDIyLjE5LDBsMCwtMjUuNjV6Ii8+CiAgPHBhdGggaWQ9InN2Z18yNCIgZmlsbD0iIzYyNGFmZiIgZD0ibTQ3Ljg0LDExNS40OWwtMjIuMTksMGwwLDQ3Ljg0bDQ3Ljg0LDBsMCwtMjIuMTlsLTI1LjY1LDBsMCwtMjUuNjV6Ii8+CiA8L2c+Cjwvc3ZnPg==&labelColor=white)](https://www.modelscope.cn/studios/OpenDataLab/MinerU) [![HuggingFace](https://img.shields.io/badge/Demo_on_HuggingFace-yellow.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAABYCAMAAACkl9t/AAAAk1BMVEVHcEz/nQv/nQv/nQr/nQv/nQr/nQv/nQv/nQr/wRf/txT/pg7/yRr/rBD/zRz/ngv/oAz/zhz/nwv/txT/ngv/0B3+zBz/nQv/0h7/wxn/vRb/thXkuiT/rxH/pxD/ogzcqyf/nQvTlSz/czCxky7/SjifdjT/Mj3+Mj3wMj15aTnDNz+DSD9RTUBsP0FRO0Q6O0WyIxEIAAAAGHRSTlMADB8zSWF3krDDw8TJ1NbX5efv8ff9/fxKDJ9uAAAGKklEQVR42u2Z63qjOAyGC4RwCOfB2JAGqrSb2WnTw/1f3UaWcSGYNKTdf/P+mOkTrE+yJBulvfvLT2A5ruenaVHyIks33npl/6C4s/ZLAM45SOi/1FtZPyFur1OYofBX3w7d54Bxm+E8db+nDr12ttmESZ4zludJEG5S7TO72YPlKZFyE+YCYUJTBZsMiNS5Sd7NlDmKM2Eg2JQg8awbglfqgbhArjxkS7dgp2RH6hc9AMLdZYUtZN5DJr4molC8BfKrEkPKEnEVjLbgW1fLy77ZVOJagoIcLIl+IxaQZGjiX597HopF5CkaXVMDO9Pyix3AFV3kw4lQLCbHuMovz8FallbcQIJ5Ta0vks9RnolbCK84BtjKRS5uA43hYoZcOBGIG2Epbv6CvFVQ8m8loh66WNySsnN7htL58LNp+NXT8/PhXiBXPMjLSxtwp8W9f/1AngRierBkA+kk/IpUSOeKByzn8y3kAAAfh//0oXgV4roHm/kz4E2z//zRc3/lgwBzbM2mJxQEa5pqgX7d1L0htrhx7LKxOZlKbwcAWyEOWqYSI8YPtgDQVjpB5nvaHaSnBaQSD6hweDi8PosxD6/PT09YY3xQA7LTCTKfYX+QHpA0GCcqmEHvr/cyfKQTEuwgbs2kPxJEB0iNjfJcCTPyocx+A0griHSmADiC91oNGVwJ69RudYe65vJmoqfpul0lrqXadW0jFKH5BKwAeCq+Den7s+3zfRJzA61/Uj/9H/VzLKTx9jFPPdXeeP+L7WEvDLAKAIoF8bPTKT0+TM7W8ePj3Rz/Yn3kOAp2f1Kf0Weony7pn/cPydvhQYV+eFOfmOu7VB/ViPe34/EN3RFHY/yRuT8ddCtMPH/McBAT5s+vRde/gf2c/sPsjLK+m5IBQF5tO+h2tTlBGnP6693JdsvofjOPnnEHkh2TnV/X1fBl9S5zrwuwF8NFrAVJVwCAPTe8gaJlomqlp0pv4Pjn98tJ/t/fL++6unpR1YGC2n/KCoa0tTLoKiEeUPDl94nj+5/Tv3/eT5vBQ60X1S0oZr+IWRR8Ldhu7AlLjPISlJcO9vrFotky9SpzDequlwEir5beYAc0R7D9KS1DXva0jhYRDXoExPdc6yw5GShkZXe9QdO/uOvHofxjrV/TNS6iMJS+4TcSTgk9n5agJdBQbB//IfF/HpvPt3Tbi7b6I6K0R72p6ajryEJrENW2bbeVUGjfgoals4L443c7BEE4mJO2SpbRngxQrAKRudRzGQ8jVOL2qDVjjI8K1gc3TIJ5KiFZ1q+gdsARPB4NQS4AjwVSt72DSoXNyOWUrU5mQ9nRYyjp89Xo7oRI6Bga9QNT1mQ/ptaJq5T/7WcgAZywR/XlPGAUDdet3LE+qS0TI+g+aJU8MIqjo0Kx8Ly+maxLjJmjQ18rA0YCkxLQbUZP1WqdmyQGJLUm7VnQFqodmXSqmRrdVpqdzk5LvmvgtEcW8PMGdaS23EOWyDVbACZzUJPaqMbjDxpA3Qrgl0AikimGDbqmyT8P8NOYiqrldF8rX+YN7TopX4UoHuSCYY7cgX4gHwclQKl1zhx0THf+tCAUValzjI7Wg9EhptrkIcfIJjA94evOn8B2eHaVzvBrnl2ig0So6hvPaz0IGcOvTHvUIlE2+prqAxLSQxZlU2stql1NqCCLdIiIN/i1DBEHUoElM9dBravbiAnKqgpi4IBkw+utSPIoBijDXJipSVV7MpOEJUAc5Qmm3BnUN+w3hteEieYKfRZSIUcXKMVf0u5wD4EwsUNVvZOtUT7A2GkffHjByWpHqvRBYrTV72a6j8zZ6W0DTE86Hn04bmyWX3Ri9WH7ZU6Q7h+ZHo0nHUAcsQvVhXRDZHChwiyi/hnPuOsSEF6Exk3o6Y9DT1eZ+6cASXk2Y9k+6EOQMDGm6WBK10wOQJCBwren86cPPWUcRAnTVjGcU1LBgs9FURiX/e6479yZcLwCBmTxiawEwrOcleuu12t3tbLv/N4RLYIBhYexm7Fcn4OJcn0+zc+s8/VfPeddZHAGN6TT8eGczHdR/Gts1/MzDkThr23zqrVfAMFT33Nx1RJsx1k5zuWILLnG/vsH+Fv5D4NTVcp1Gzo8AAAAAElFTkSuQmCC&labelColor=white)](https://huggingface.co/spaces/opendatalab/MinerU) + +[![HuggingFace](https://img.shields.io/badge/VLM_Demo_on_HuggingFace-yellow.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAABYCAMAAACkl9t/AAAAk1BMVEVHcEz/nQv/nQv/nQr/nQv/nQr/nQv/nQv/nQr/wRf/txT/pg7/yRr/rBD/zRz/ngv/oAz/zhz/nwv/txT/ngv/0B3+zBz/nQv/0h7/wxn/vRb/thXkuiT/rxH/pxD/ogzcqyf/nQvTlSz/czCxky7/SjifdjT/Mj3+Mj3wMj15aTnDNz+DSD9RTUBsP0FRO0Q6O0WyIxEIAAAAGHRSTlMADB8zSWF3krDDw8TJ1NbX5efv8ff9/fxKDJ9uAAAGKklEQVR42u2Z63qjOAyGC4RwCOfB2JAGqrSb2WnTw/1f3UaWcSGYNKTdf/P+mOkTrE+yJBulvfvLT2A5ruenaVHyIks33npl/6C4s/ZLAM45SOi/1FtZPyFur1OYofBX3w7d54Bxm+E8db+nDr12ttmESZ4zludJEG5S7TO72YPlKZFyE+YCYUJTBZsMiNS5Sd7NlDmKM2Eg2JQg8awbglfqgbhArjxkS7dgp2RH6hc9AMLdZYUtZN5DJr4molC8BfKrEkPKEnEVjLbgW1fLy77ZVOJagoIcLIl+IxaQZGjiX597HopF5CkaXVMDO9Pyix3AFV3kw4lQLCbHuMovz8FallbcQIJ5Ta0vks9RnolbCK84BtjKRS5uA43hYoZcOBGIG2Epbv6CvFVQ8m8loh66WNySsnN7htL58LNp+NXT8/PhXiBXPMjLSxtwp8W9f/1AngRierBkA+kk/IpUSOeKByzn8y3kAAAfh//0oXgV4roHm/kz4E2z//zRc3/lgwBzbM2mJxQEa5pqgX7d1L0htrhx7LKxOZlKbwcAWyEOWqYSI8YPtgDQVjpB5nvaHaSnBaQSD6hweDi8PosxD6/PT09YY3xQA7LTCTKfYX+QHpA0GCcqmEHvr/cyfKQTEuwgbs2kPxJEB0iNjfJcCTPyocx+A0griHSmADiC91oNGVwJ69RudYe65vJmoqfpul0lrqXadW0jFKH5BKwAeCq+Den7s+3zfRJzA61/Uj/9H/VzLKTx9jFPPdXeeP+L7WEvDLAKAIoF8bPTKT0+TM7W8ePj3Rz/Yn3kOAp2f1Kf0Weony7pn/cPydvhQYV+eFOfmOu7VB/ViPe34/EN3RFHY/yRuT8ddCtMPH/McBAT5s+vRde/gf2c/sPsjLK+m5IBQF5tO+h2tTlBGnP6693JdsvofjOPnnEHkh2TnV/X1fBl9S5zrwuwF8NFrAVJVwCAPTe8gaJlomqlp0pv4Pjn98tJ/t/fL++6unpR1YGC2n/KCoa0tTLoKiEeUPDl94nj+5/Tv3/eT5vBQ60X1S0oZr+IWRR8Ldhu7AlLjPISlJcO9vrFotky9SpzDequlwEir5beYAc0R7D9KS1DXva0jhYRDXoExPdc6yw5GShkZXe9QdO/uOvHofxjrV/TNS6iMJS+4TcSTgk9n5agJdBQbB//IfF/HpvPt3Tbi7b6I6K0R72p6ajryEJrENW2bbeVUGjfgoals4L443c7BEE4mJO2SpbRngxQrAKRudRzGQ8jVOL2qDVjjI8K1gc3TIJ5KiFZ1q+gdsARPB4NQS4AjwVSt72DSoXNyOWUrU5mQ9nRYyjp89Xo7oRI6Bga9QNT1mQ/ptaJq5T/7WcgAZywR/XlPGAUDdet3LE+qS0TI+g+aJU8MIqjo0Kx8Ly+maxLjJmjQ18rA0YCkxLQbUZP1WqdmyQGJLUm7VnQFqodmXSqmRrdVpqdzk5LvmvgtEcW8PMGdaS23EOWyDVbACZzUJPaqMbjDxpA3Qrgl0AikimGDbqmyT8P8NOYiqrldF8rX+YN7TopX4UoHuSCYY7cgX4gHwclQKl1zhx0THf+tCAUValzjI7Wg9EhptrkIcfIJjA94evOn8B2eHaVzvBrnl2ig0So6hvPaz0IGcOvTHvUIlE2+prqAxLSQxZlU2stql1NqCCLdIiIN/i1DBEHUoElM9dBravbiAnKqgpi4IBkw+utSPIoBijDXJipSVV7MpOEJUAc5Qmm3BnUN+w3hteEieYKfRZSIUcXKMVf0u5wD4EwsUNVvZOtUT7A2GkffHjByWpHqvRBYrTV72a6j8zZ6W0DTE86Hn04bmyWX3Ri9WH7ZU6Q7h+ZHo0nHUAcsQvVhXRDZHChwiyi/hnPuOsSEF6Exk3o6Y9DT1eZ+6cASXk2Y9k+6EOQMDGm6WBK10wOQJCBwren86cPPWUcRAnTVjGcU1LBgs9FURiX/e6479yZcLwCBmTxiawEwrOcleuu12t3tbLv/N4RLYIBhYexm7Fcn4OJcn0+zc+s8/VfPeddZHAGN6TT8eGczHdR/Gts1/MzDkThr23zqrVfAMFT33Nx1RJsx1k5zuWILLnG/vsH+Fv5D4NTVcp1Gzo8AAAAAElFTkSuQmCC&labelColor=white)](https://huggingface.co/spaces/opendatalab/mineru2) [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/gist/myhloli/3b3a00a4a0a61577b6c30f989092d20d/mineru_demo.ipynb) [![Paper](https://img.shields.io/badge/Paper-arXiv-green)](https://arxiv.org/abs/2409.18839) @@ -47,241 +50,337 @@ # 更新记录 -- 2025/05/24 1.3.12 发布 - - 增加ppocrv5模型的支持,将`ch_server`模型更新为`PP-OCRv5_rec_server`,`ch_lite`模型更新为`PP-OCRv5_rec_mobile`(需更新模型) - - 在测试中,发现ppocrv5(server)对手写文档效果有一定提升,但在其余类别文档的精度略差于v4_server_doc,因此默认的ch模型保持不变,仍为`PP-OCRv4_server_rec_doc`。 - - 由于ppocrv5强化了手写场景和特殊字符的识别能力,因此您可以在日繁混合场景以及手写文档场景下手动选择使用ppocrv5模型 - - 您可通过lang参数`lang='ch_server'`(python api)或`--lang ch_server`(命令行)自行选择相应的模型: - - `ch` :`PP-OCRv4_rec_server_doc`(默认)(中英日繁混合/1.5w字典) - - `ch_server` :`PP-OCRv5_rec_server`(中英日繁混合+手写场景/1.8w字典) - - `ch_lite` :`PP-OCRv5_rec_mobile`(中英日繁混合+手写场景/1.8w字典) - - `ch_server_v4` :`PP-OCRv4_rec_server`(中英混合/6k字典) - - `ch_lite_v4` :`PP-OCRv4_rec_mobile`(中英混合/6k字典) - - 增加手写文档的支持,通过优化layout对手写文本区域的识别,现已支持手写文档的解析 - - 默认支持此功能,无需额外配置 - - 可以参考上述说明,手动选择ppocrv5模型以获得更好的手写文档解析效果 - - `huggingface`和`modelscope`的demo已更新为支持手写识别和ppocrv5模型的版本,可自行在线体验 -- 2025/04/29 1.3.10 发布 - - 支持使用自定义公式标识符,可通过修改用户目录下的`magic-pdf.json`文件中的`latex-delimiter-config`项实现。 -- 2025/04/27 1.3.9 发布 - - 优化公式解析功能,提升公式渲染的成功率 -- 2025/04/23 1.3.8 发布 - - `ocr`默认模型(`ch`)更新为`PP-OCRv4_server_rec_doc`(需更新模型) - - `PP-OCRv4_server_rec_doc`是在`PP-OCRv4_server_rec`的基础上,在更多中文文档数据和PP-OCR训练数据的混合数据训练而成,增加了部分繁体字、日文、特殊字符的识别能力,可支持识别的字符为1.5万+,除文档相关的文字识别能力提升外,也同时提升了通用文字的识别能力。 - - [PP-OCRv4_server_rec_doc/PP-OCRv4_server_rec/PP-OCRv4_mobile_rec 性能对比](https://paddlepaddle.github.io/PaddleX/latest/module_usage/tutorials/ocr_modules/text_recognition.html#_3) - - 经验证,`PP-OCRv4_server_rec_doc`模型在`中英日繁`单种语言或多种语言混合场景均有明显精度提升,且速度与`PP-OCRv4_server_rec`相当,适合绝大部分场景使用。 - - `PP-OCRv4_server_rec_doc`在小部分纯英文场景可能会发生单词粘连问题,`PP-OCRv4_server_rec`则在此场景下表现更好,因此我们保留了`PP-OCRv4_server_rec`模型,用户可通过增加参数`lang='ch_server'`(python api)或`--lang ch_server`(命令行)调用。 -- 2025/04/22 1.3.7 发布 - - 修复表格解析模型初始化时lang参数失效的问题 - - 修复在`cpu`模式下ocr和表格解析速度大幅下降的问题 -- 2025/04/16 1.3.4 发布 - - 通过移除一些无用的块,小幅提升了ocr-det的速度 - - 修复部分情况下由footnote导致的页面内排序错误 -- 2025/04/12 1.3.2 发布 - - 修复了windows系统下,在python3.13环境安装时一些依赖包版本不兼容的问题 - - 优化批量推理时的内存占用 - - 优化旋转90度表格的解析效果 - - 优化财报样本中超大表格的解析效果 - - 修复了在未指定OCR语言时,英文文本区域偶尔出现的单词黏连问题(需要更新模型) -- 2025/04/08 1.3.1 发布,修复了一些兼容问题 - - 支持python 3.13 - - 为部分过时的linux系统(如centos7)做出最后适配,并不再保证后续版本的继续支持,[安装说明](https://github.com/opendatalab/MinerU/issues/1004) -- 2025/04/03 1.3.0 发布,在这个版本我们做出了许多优化和改进: - - 安装与兼容性优化 - - 通过移除layout中`layoutlmv3`的使用,解决了由`detectron2`导致的兼容问题 - - torch版本兼容扩展到2.2~2.6(2.5除外) - - cuda兼容支持11.8/12.4/12.6/12.8(cuda版本由torch决定),解决部分用户50系显卡与H系显卡的兼容问题 - - python兼容版本扩展到3.10~3.12,解决了在非3.10环境下安装时自动降级到0.6.1的问题 - - 优化离线部署流程,部署成功后不需要联网下载任何模型文件 - - 性能优化 - - 通过支持多个pdf文件的batch处理([脚本样例](demo/batch_demo.py)),提升了批量小文件的解析速度 (与1.0.1版本相比,公式解析速度最高提升超过1400%,整体解析速度最高提升超过500%) - - 通过优化mfr模型的加载和使用,降低了显存占用并提升了解析速度(需重新执行[模型下载流程](docs/how_to_download_models_zh_cn.md)以获得模型文件的增量更新) - - 优化显存占用,最低仅需6GB即可运行本项目 - - 优化了在mps设备上的运行速度 - - 解析效果优化 - - mfr模型更新到`unimernet(2503)`,解决多行公式中换行丢失的问题 - - 易用性优化 - - 通过使用`paddleocr2torch`,完全替代`paddle`框架以及`paddleocr`在项目中的使用,解决了`paddle`和`torch`的冲突问题,和由于`paddle`框架导致的线程不安全问题 - - 解析过程增加实时进度条显示,精准把握解析进度,让等待不再痛苦 -
-2025/03/03 1.2.1 发布,修复了一些问题 -
    -
  • 修复在字母与数字的全角转半角操作时对标点符号的影响
  • -
  • 修复在某些情况下caption的匹配不准确问题
  • -
  • 修复在某些情况下的公式span丢失问题
  • -
-
+- 2025/06/13 2.0.0发布 + - MinerU 2.0 是一次从架构到功能的全面重构与升级,带来了更简洁的设计、更强的性能以及更灵活的使用体验。 + - **全新架构**:MinerU 2.0 在代码结构和交互方式上进行了深度重构,显著提升了系统的易用性、可维护性与扩展能力。 + - **去除第三方依赖限制**:彻底移除对 `pymupdf` 的依赖,推动项目向更开放、合规的开源方向迈进。 + - **开箱即用,配置便捷**:无需手动编辑 JSON 配置文件,绝大多数参数已支持命令行或 API 直接设置。 + - **模型自动管理**:新增模型自动下载与更新机制,用户无需手动干预即可完成模型部署。 + - **离线部署友好**:提供内置模型下载命令,支持完全断网环境下的部署需求。 + - **代码结构精简**:移除数千行冗余代码,简化类继承逻辑,显著提升代码可读性与开发效率。 + - **统一中间格式输出**:采用标准化的 `middle_json` 格式,兼容多数基于该格式的二次开发场景,确保生态业务无缝迁移。 + - **全新模型**:MinerU 2.0 集成了我们最新研发的小参数量、高性能多模态文档解析模型,实现端到端的高速、高精度文档理解。 + - **小模型,大能力**:模型参数不足 1B,却在解析精度上超越传统 72B 级别的视觉语言模型(VLM)。 + - **多功能合一**:单模型覆盖多语言识别、手写识别、版面分析、表格解析、公式识别、阅读顺序排序等核心任务。 + - **极致推理速度**:在单卡 NVIDIA 4090 上通过 `sglang` 加速,达到峰值吞吐量超过 10,000 token/s,轻松应对大规模文档处理需求。 + - **在线体验**:您可在我们的huggingface demo上在线体验该模型:[![HuggingFace](https://img.shields.io/badge/VLM_Demo_on_HuggingFace-yellow.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAABYCAMAAACkl9t/AAAAk1BMVEVHcEz/nQv/nQv/nQr/nQv/nQr/nQv/nQv/nQr/wRf/txT/pg7/yRr/rBD/zRz/ngv/oAz/zhz/nwv/txT/ngv/0B3+zBz/nQv/0h7/wxn/vRb/thXkuiT/rxH/pxD/ogzcqyf/nQvTlSz/czCxky7/SjifdjT/Mj3+Mj3wMj15aTnDNz+DSD9RTUBsP0FRO0Q6O0WyIxEIAAAAGHRSTlMADB8zSWF3krDDw8TJ1NbX5efv8ff9/fxKDJ9uAAAGKklEQVR42u2Z63qjOAyGC4RwCOfB2JAGqrSb2WnTw/1f3UaWcSGYNKTdf/P+mOkTrE+yJBulvfvLT2A5ruenaVHyIks33npl/6C4s/ZLAM45SOi/1FtZPyFur1OYofBX3w7d54Bxm+E8db+nDr12ttmESZ4zludJEG5S7TO72YPlKZFyE+YCYUJTBZsMiNS5Sd7NlDmKM2Eg2JQg8awbglfqgbhArjxkS7dgp2RH6hc9AMLdZYUtZN5DJr4molC8BfKrEkPKEnEVjLbgW1fLy77ZVOJagoIcLIl+IxaQZGjiX597HopF5CkaXVMDO9Pyix3AFV3kw4lQLCbHuMovz8FallbcQIJ5Ta0vks9RnolbCK84BtjKRS5uA43hYoZcOBGIG2Epbv6CvFVQ8m8loh66WNySsnN7htL58LNp+NXT8/PhXiBXPMjLSxtwp8W9f/1AngRierBkA+kk/IpUSOeKByzn8y3kAAAfh//0oXgV4roHm/kz4E2z//zRc3/lgwBzbM2mJxQEa5pqgX7d1L0htrhx7LKxOZlKbwcAWyEOWqYSI8YPtgDQVjpB5nvaHaSnBaQSD6hweDi8PosxD6/PT09YY3xQA7LTCTKfYX+QHpA0GCcqmEHvr/cyfKQTEuwgbs2kPxJEB0iNjfJcCTPyocx+A0griHSmADiC91oNGVwJ69RudYe65vJmoqfpul0lrqXadW0jFKH5BKwAeCq+Den7s+3zfRJzA61/Uj/9H/VzLKTx9jFPPdXeeP+L7WEvDLAKAIoF8bPTKT0+TM7W8ePj3Rz/Yn3kOAp2f1Kf0Weony7pn/cPydvhQYV+eFOfmOu7VB/ViPe34/EN3RFHY/yRuT8ddCtMPH/McBAT5s+vRde/gf2c/sPsjLK+m5IBQF5tO+h2tTlBGnP6693JdsvofjOPnnEHkh2TnV/X1fBl9S5zrwuwF8NFrAVJVwCAPTe8gaJlomqlp0pv4Pjn98tJ/t/fL++6unpR1YGC2n/KCoa0tTLoKiEeUPDl94nj+5/Tv3/eT5vBQ60X1S0oZr+IWRR8Ldhu7AlLjPISlJcO9vrFotky9SpzDequlwEir5beYAc0R7D9KS1DXva0jhYRDXoExPdc6yw5GShkZXe9QdO/uOvHofxjrV/TNS6iMJS+4TcSTgk9n5agJdBQbB//IfF/HpvPt3Tbi7b6I6K0R72p6ajryEJrENW2bbeVUGjfgoals4L443c7BEE4mJO2SpbRngxQrAKRudRzGQ8jVOL2qDVjjI8K1gc3TIJ5KiFZ1q+gdsARPB4NQS4AjwVSt72DSoXNyOWUrU5mQ9nRYyjp89Xo7oRI6Bga9QNT1mQ/ptaJq5T/7WcgAZywR/XlPGAUDdet3LE+qS0TI+g+aJU8MIqjo0Kx8Ly+maxLjJmjQ18rA0YCkxLQbUZP1WqdmyQGJLUm7VnQFqodmXSqmRrdVpqdzk5LvmvgtEcW8PMGdaS23EOWyDVbACZzUJPaqMbjDxpA3Qrgl0AikimGDbqmyT8P8NOYiqrldF8rX+YN7TopX4UoHuSCYY7cgX4gHwclQKl1zhx0THf+tCAUValzjI7Wg9EhptrkIcfIJjA94evOn8B2eHaVzvBrnl2ig0So6hvPaz0IGcOvTHvUIlE2+prqAxLSQxZlU2stql1NqCCLdIiIN/i1DBEHUoElM9dBravbiAnKqgpi4IBkw+utSPIoBijDXJipSVV7MpOEJUAc5Qmm3BnUN+w3hteEieYKfRZSIUcXKMVf0u5wD4EwsUNVvZOtUT7A2GkffHjByWpHqvRBYrTV72a6j8zZ6W0DTE86Hn04bmyWX3Ri9WH7ZU6Q7h+ZHo0nHUAcsQvVhXRDZHChwiyi/hnPuOsSEF6Exk3o6Y9DT1eZ+6cASXk2Y9k+6EOQMDGm6WBK10wOQJCBwren86cPPWUcRAnTVjGcU1LBgs9FURiX/e6479yZcLwCBmTxiawEwrOcleuu12t3tbLv/N4RLYIBhYexm7Fcn4OJcn0+zc+s8/VfPeddZHAGN6TT8eGczHdR/Gts1/MzDkThr23zqrVfAMFT33Nx1RJsx1k5zuWILLnG/vsH+Fv5D4NTVcp1Gzo8AAAAAElFTkSuQmCC&labelColor=white)](https://huggingface.co/spaces/opendatalab/mineru2) + - **不兼容变更说明**:为提升整体架构合理性与长期可维护性,本版本包含部分不兼容的变更: + - Python 包名从 `magic-pdf` 更改为 `mineru`,命令行工具也由 `magic-pdf` 改为 `mineru`,请同步更新脚本与调用命令。 + - 出于对系统模块化设计与生态一致性的考虑,MinerU 2.0 已不再内置 LibreOffice 文档转换模块。如需处理 Office 文档,建议通过独立部署的 LibreOffice 服务先行转换为 PDF 格式,再进行后续解析操作。 +
-2025/02/24 1.2.0 发布,这个版本我们修复了一些问题,提升了解析的效率与精度: -
    -
  • 性能优化 + 历史日志 +
    + 2025/05/24 1.3.12 发布 +
      +
    • 增加ppocrv5模型的支持,将ch_server模型更新为PP-OCRv5_rec_serverch_lite模型更新为PP-OCRv5_rec_mobile(需更新模型)
        -
      • auto模式下pdf文档的分类速度提升
      • +
      • 在测试中,发现ppocrv5(server)对手写文档效果有一定提升,但在其余类别文档的精度略差于v4_server_doc,因此默认的ch模型保持不变,仍为PP-OCRv4_server_rec_doc
      • +
      • 由于ppocrv5强化了手写场景和特殊字符的识别能力,因此您可以在日繁混合场景以及手写文档场景下手动选择使用ppocrv5模型
      • +
      • 您可通过lang参数lang='ch_server'(python api)或--lang ch_server(命令行)自行选择相应的模型: +
          +
        • chPP-OCRv4_rec_server_doc(默认)(中英日繁混合/1.5w字典)
        • +
        • ch_serverPP-OCRv5_rec_server(中英日繁混合+手写场景/1.8w字典)
        • +
        • ch_litePP-OCRv5_rec_mobile(中英日繁混合+手写场景/1.8w字典)
        • +
        • ch_server_v4PP-OCRv4_rec_server(中英混合/6k字典)
        • +
        • ch_lite_v4PP-OCRv4_rec_mobile(中英混合/6k字典)
        • +
        +
      -
    • -
    • 解析优化 +
    • +
    • 增加手写文档的支持,通过优化layout对手写文本区域的识别,现已支持手写文档的解析
        -
      • 优化对包含水印文档的解析逻辑,显著提升包含水印文档的解析效果
      • -
      • 改进了单页内多个图像/表格与caption的匹配逻辑,提升了复杂布局下图文匹配的准确性
      • +
      • 默认支持此功能,无需额外配置
      • +
      • 可以参考上述说明,手动选择ppocrv5模型以获得更好的手写文档解析效果
      -
    • -
    • 问题修复 +
    • +
    • huggingfacemodelscope的demo已更新为支持手写识别和ppocrv5模型的版本,可自行在线体验
    • +
    +
    + +
    + 2025/04/29 1.3.10 发布 +
      +
    • 支持使用自定义公式标识符,可通过修改用户目录下的magic-pdf.json文件中的latex-delimiter-config项实现。
    • +
    +
    + +
    + 2025/04/27 1.3.9 发布 +
      +
    • 优化公式解析功能,提升公式渲染的成功率
    • +
    +
    + +
    + 2025/04/23 1.3.8 发布 +
      +
    • ocr默认模型(ch)更新为PP-OCRv4_server_rec_doc(需更新模型)
        -
      • 修复在某些情况下图片/表格span被填充进textblock导致的异常
      • -
      • 修复在某些情况下标题block为空的问题
      • +
      • PP-OCRv4_server_rec_doc是在PP-OCRv4_server_rec的基础上,在更多中文文档数据和PP-OCR训练数据的混合数据训练而成,增加了部分繁体字、日文、特殊字符的识别能力,可支持识别的字符为1.5万+,除文档相关的文字识别能力提升外,也同时提升了通用文字的识别能力。
      • +
      • PP-OCRv4_server_rec_doc/PP-OCRv4_server_rec/PP-OCRv4_mobile_rec 性能对比
      • +
      • 经验证,PP-OCRv4_server_rec_doc模型在中英日繁单种语言或多种语言混合场景均有明显精度提升,且速度与PP-OCRv4_server_rec相当,适合绝大部分场景使用。
      • +
      • PP-OCRv4_server_rec_doc在小部分纯英文场景可能会发生单词粘连问题,PP-OCRv4_server_rec则在此场景下表现更好,因此我们保留了PP-OCRv4_server_rec模型,用户可通过增加参数lang='ch_server'(python api)或--lang ch_server(命令行)调用。
      -
    • -
    -
    - -
    -2025/01/22 1.1.0 发布,在这个版本我们重点提升了解析的精度与效率: -
      -
    • 模型能力升级(需重新执行 模型下载流程 以获得模型文件的增量更新) +
    • +
    +
    + +
    + 2025/04/22 1.3.7 发布 +
      +
    • 修复表格解析模型初始化时lang参数失效的问题
    • +
    • 修复在cpu模式下ocr和表格解析速度大幅下降的问题
    • +
    +
    + +
    + 2025/04/16 1.3.4 发布 +
      +
    • 通过移除一些无用的块,小幅提升了ocr-det的速度
    • +
    • 修复部分情况下由footnote导致的页面内排序错误
    • +
    +
    + +
    + 2025/04/12 1.3.2 发布 +
      +
    • 修复了windows系统下,在python3.13环境安装时一些依赖包版本不兼容的问题
    • +
    • 优化批量推理时的内存占用
    • +
    • 优化旋转90度表格的解析效果
    • +
    • 优化财报样本中超大表格的解析效果
    • +
    • 修复了在未指定OCR语言时,英文文本区域偶尔出现的单词黏连问题(需要更新模型)
    • +
    +
    + +
    + 2025/04/08 1.3.1 发布 +
      +
    • 修复了一些兼容问题
        -
      • 布局识别模型升级到最新的 `doclayout_yolo(2501)` 模型,提升了layout识别精度
      • -
      • 公式解析模型升级到最新的 `unimernet(2501)` 模型,提升了公式识别精度
      • +
      • 支持python 3.13
      • +
      • 为部分过时的linux系统(如centos7)做出最后适配,并不再保证后续版本的继续支持,安装说明
      -
    • -
    • 性能优化 +
    • +
    +
    + +
    + 2025/04/03 1.3.0 发布 +
      +
    • 安装与兼容性优化
        -
      • 在配置满足一定条件(显存16GB+)的设备上,通过优化资源占用和重构处理流水线,整体解析速度提升50%以上
      • +
      • 通过移除layout中layoutlmv3的使用,解决了由detectron2导致的兼容问题
      • +
      • torch版本兼容扩展到2.2~2.6(2.5除外)
      • +
      • cuda兼容支持11.8/12.4/12.6/12.8(cuda版本由torch决定),解决部分用户50系显卡与H系显卡的兼容问题
      • +
      • python兼容版本扩展到3.10~3.12,解决了在非3.10环境下安装时自动降级到0.6.1的问题
      • +
      • 优化离线部署流程,部署成功后不需要联网下载任何模型文件
      -
    • -
    • 解析效果优化 +
    • +
    • 性能优化
        -
      • 在线demo(mineru.net / huggingface / modelscope)上新增标题分级功能(测试版本,默认开启),支持对标题进行分级,提升文档结构化程度
      • +
      • 通过支持多个pdf文件的batch处理(脚本样例),提升了批量小文件的解析速度 (与1.0.1版本相比,公式解析速度最高提升超过1400%,整体解析速度最高提升超过500%)
      • +
      • 通过优化mfr模型的加载和使用,降低了显存占用并提升了解析速度(需重新执行模型下载流程以获得模型文件的增量更新)
      • +
      • 优化显存占用,最低仅需6GB即可运行本项目
      • +
      • 优化了在mps设备上的运行速度
      -
    • -
    -
    - -
    -2025/01/10 1.0.1 发布,这是我们的第一个正式版本,在这个版本中,我们通过大量重构带来了全新的API接口和更广泛的兼容性,以及全新的自动语言识别功能: -
      -
    • 全新API接口 +
    • +
    • 解析效果优化
        -
      • 对于数据侧API,我们引入了Dataset类,旨在提供一个强大而灵活的数据处理框架。该框架当前支持包括图像(.jpg及.png)、PDF、Word(.doc及.docx)、以及PowerPoint(.ppt及.pptx)在内的多种文档格式,确保了从简单到复杂的数据处理任务都能得到有效的支持。
      • -
      • 针对用户侧API,我们将MinerU的处理流程精心设计为一系列可组合的Stage阶段。每个Stage代表了一个特定的处理步骤,用户可以根据自身需求自由地定义新的Stage,并通过创造性地组合这些阶段来定制专属的数据处理流程。
      • +
      • mfr模型更新到unimernet(2503),解决多行公式中换行丢失的问题
      -
    • -
    • 更广泛的兼容性适配 +
    • +
    • 易用性优化
        -
      • 通过优化依赖环境和配置项,确保在ARM架构的Linux系统上能够稳定高效运行。
      • -
      • 深度适配华为昇腾NPU加速,积极响应信创要求,提供自主可控的高性能计算能力,助力人工智能应用平台的国产化应用与发展。 NPU加速教程
      • +
      • 通过使用paddleocr2torch,完全替代paddle框架以及paddleocr在项目中的使用,解决了paddletorch的冲突问题,和由于paddle框架导致的线程不安全问题
      • +
      • 解析过程增加实时进度条显示,精准把握解析进度,让等待不再痛苦
      -
    • -
    • 自动语言识别 +
    • +
    +
    + +
    + 2025/03/03 1.2.1 发布,修复了一些问题 +
      +
    • 修复在字母与数字的全角转半角操作时对标点符号的影响
    • +
    • 修复在某些情况下caption的匹配不准确问题
    • +
    • 修复在某些情况下的公式span丢失问题
    • +
    +
    + +
    + 2025/02/24 1.2.0 发布,这个版本我们修复了一些问题,提升了解析的效率与精度: +
      +
    • 性能优化 +
        +
      • auto模式下pdf文档的分类速度提升
      • +
      +
    • +
    • 解析优化 +
        +
      • 优化对包含水印文档的解析逻辑,显著提升包含水印文档的解析效果
      • +
      • 改进了单页内多个图像/表格与caption的匹配逻辑,提升了复杂布局下图文匹配的准确性
      • +
      +
    • +
    • 问题修复 +
        +
      • 修复在某些情况下图片/表格span被填充进textblock导致的异常
      • +
      • 修复在某些情况下标题block为空的问题
      • +
      +
    • +
    +
    + +
    + 2025/01/22 1.1.0 发布,在这个版本我们重点提升了解析的精度与效率: +
      +
    • 模型能力升级(需重新执行 模型下载流程 以获得模型文件的增量更新) +
        +
      • 布局识别模型升级到最新的 `doclayout_yolo(2501)` 模型,提升了layout识别精度
      • +
      • 公式解析模型升级到最新的 `unimernet(2501)` 模型,提升了公式识别精度
      • +
      +
    • +
    • 性能优化 +
        +
      • 在配置满足一定条件(显存16GB+)的设备上,通过优化资源占用和重构处理流水线,整体解析速度提升50%以上
      • +
      +
    • +
    • 解析效果优化 +
        +
      • 在线demo(mineru.net / huggingface / modelscope)上新增标题分级功能(测试版本,默认开启),支持对标题进行分级,提升文档结构化程度
      • +
      +
    • +
    +
    + +
    + 2025/01/10 1.0.1 发布,这是我们的第一个正式版本,在这个版本中,我们通过大量重构带来了全新的API接口和更广泛的兼容性,以及全新的自动语言识别功能: +
      +
    • 全新API接口 +
        +
      • 对于数据侧API,我们引入了Dataset类,旨在提供一个强大而灵活的数据处理框架。该框架当前支持包括图像(.jpg及.png)、PDF、Word(.doc及.docx)、以及PowerPoint(.ppt及.pptx)在内的多种文档格式,确保了从简单到复杂的数据处理任务都能得到有效的支持。
      • +
      • 针对用户侧API,我们将MinerU的处理流程精心设计为一系列可组合的Stage阶段。每个Stage代表了一个特定的处理步骤,用户可以根据自身需求自由地定义新的Stage,并通过创造性地组合这些阶段来定制专属的数据处理流程。
      • +
      +
    • +
    • 更广泛的兼容性适配 +
        +
      • 通过优化依赖环境和配置项,确保在ARM架构的Linux系统上能够稳定高效运行。
      • +
      • 深度适配华为昇腾NPU加速,积极响应信创要求,提供自主可控的高性能计算能力,助力人工智能应用平台的国产化应用与发展。 NPU加速教程
      • +
      +
    • +
    • 自动语言识别 +
        +
      • 通过引入全新的语言识别模型, 在文档解析中将 `lang` 配置为 `auto`,即可自动选择合适的OCR语言模型,提升扫描类文档解析的准确性。
      • +
      +
    • +
    +
    + +
    + 2024/11/22 0.10.0发布,通过引入混合OCR文本提取能力, +
      +
    • 在公式密集、span区域不规范、部分文本使用图像表现等复杂文本分布场景下获得解析效果的显著提升
    • +
    • 同时具备文本模式内容提取准确、速度更快与OCR模式span/line区域识别更准的双重优势
    • +
    +
    + +
    + 2024/11/15 0.9.3发布,为表格识别功能接入了RapidTable,单表解析速度提升10倍以上,准确率更高,显存占用更低 +
    + +
    + 2024/11/06 0.9.2发布,为表格识别功能接入了StructTable-InternVL2-1B模型 +
    + +
    + 2024/10/31 0.9.0发布,这是我们进行了大量代码重构的全新版本,解决了众多问题,提升了性能,降低了硬件需求,并提供了更丰富的易用性: +
      +
    • 重构排序模块代码,使用 layoutreader 进行阅读顺序排序,确保在各种排版下都能实现极高准确率
    • +
    • 重构段落拼接模块,在跨栏、跨页、跨图、跨表情况下均能实现良好的段落拼接效果
    • +
    • 重构列表和目录识别功能,极大提升列表块和目录块识别的准确率及对应文本段落的解析效果
    • +
    • 重构图、表与描述性文本的匹配逻辑,大幅提升 caption 和 footnote 与图表的匹配准确率,并将描述性文本的丢失率降至接近0
    • +
    • 增加 OCR 的多语言支持,支持 84 种语言的检测与识别,语言支持列表详见 OCR 语言支持列表
    • +
    • 增加显存回收逻辑及其他显存优化措施,大幅降低显存使用需求。开启除表格加速外的全部加速功能(layout/公式/OCR)的显存需求从16GB降至8GB,开启全部加速功能的显存需求从24GB降至10GB
    • +
    • 优化配置文件的功能开关,增加独立的公式检测开关,无需公式检测时可大幅提升速度和解析效果
    • +
    • 集成 PDF-Extract-Kit 1.0 +
        +
      • 加入自研的 `doclayout_yolo` 模型,在相近解析效果情况下比原方案提速10倍以上,可通过配置文件与 `layoutlmv3` 自由切换
      • +
      • 公式解析升级至 `unimernet 0.2.1`,在提升公式解析准确率的同时,大幅降低显存需求
      • +
      • 因 `PDF-Extract-Kit 1.0` 更换仓库,需要重新下载模型,步骤详见 如何下载模型
      • +
      +
    • +
    +
    + +
    + 2024/09/27 0.8.1发布,修复了一些bug,同时提供了在线demo本地化部署版本前端界面 +
    + +
    + 2024/09/09 0.8.0发布,支持Dockerfile快速部署,同时上线了huggingface、modelscope demo +
    + +
    + 2024/08/30 0.7.1发布,集成了paddle tablemaster表格识别功能 +
    + +
    + 2024/08/09 0.7.0b1发布,简化安装步骤提升易用性,加入表格识别功能 +
    + +
    + 2024/08/01 0.6.2b1发布,优化了依赖冲突问题和安装文档 +
    + +
    + 2024/07/05 首次开源 +
    + + + + +
    +

    文档目录

    +
      +
    1. + MinerU -
    2. -
+ +
  • TODO
  • +
  • Known Issues
  • +
  • FAQ
  • +
  • Contributors
  • +
  • License Information
  • +
  • Acknowledgements
  • +
  • Citation
  • +
  • Star History
  • +
  • magic-doc快速提取PPT/DOC/PDF
  • +
  • magic-html提取混合网页内容
  • +
  • Links
  • + +
    -
    -2024/11/22 0.10.0发布,通过引入混合OCR文本提取能力, -
      -
    • 在公式密集、span区域不规范、部分文本使用图像表现等复杂文本分布场景下获得解析效果的显著提升
    • -
    • 同时具备文本模式内容提取准确、速度更快与OCR模式span/line区域识别更准的双重优势
    • -
    -
    - -
    -2024/11/15 0.9.3发布,为表格识别功能接入了RapidTable,单表解析速度提升10倍以上,准确率更高,显存占用更低 -
    - -
    -2024/11/06 0.9.2发布,为表格识别功能接入了StructTable-InternVL2-1B模型 -
    - -
    -2024/10/31 0.9.0发布,这是我们进行了大量代码重构的全新版本,解决了众多问题,提升了性能,降低了硬件需求,并提供了更丰富的易用性: -
      -
    • 重构排序模块代码,使用 layoutreader 进行阅读顺序排序,确保在各种排版下都能实现极高准确率
    • -
    • 重构段落拼接模块,在跨栏、跨页、跨图、跨表情况下均能实现良好的段落拼接效果
    • -
    • 重构列表和目录识别功能,极大提升列表块和目录块识别的准确率及对应文本段落的解析效果
    • -
    • 重构图、表与描述性文本的匹配逻辑,大幅提升 caption 和 footnote 与图表的匹配准确率,并将描述性文本的丢失率降至接近0
    • -
    • 增加 OCR 的多语言支持,支持 84 种语言的检测与识别,语言支持列表详见 OCR 语言支持列表
    • -
    • 增加显存回收逻辑及其他显存优化措施,大幅降低显存使用需求。开启除表格加速外的全部加速功能(layout/公式/OCR)的显存需求从16GB降至8GB,开启全部加速功能的显存需求从24GB降至10GB
    • -
    • 优化配置文件的功能开关,增加独立的公式检测开关,无需公式检测时可大幅提升速度和解析效果
    • -
    • 集成 PDF-Extract-Kit 1.0 -
        -
      • 加入自研的 `doclayout_yolo` 模型,在相近解析效果情况下比原方案提速10倍以上,可通过配置文件与 `layoutlmv3` 自由切换
      • -
      • 公式解析升级至 `unimernet 0.2.1`,在提升公式解析准确率的同时,大幅降低显存需求
      • -
      • 因 `PDF-Extract-Kit 1.0` 更换仓库,需要重新下载模型,步骤详见 如何下载模型
      • -
      -
    • -
    -
    - -
    -2024/09/27 0.8.1发布,修复了一些bug,同时提供了在线demo本地化部署版本前端界面 -
    - -
    -2024/09/09 0.8.0发布,支持Dockerfile快速部署,同时上线了huggingface、modelscope demo -
    - -
    -2024/08/30 0.7.1发布,集成了paddle tablemaster表格识别功能 -
    - -
    -2024/08/09 0.7.0b1发布,简化安装步骤提升易用性,加入表格识别功能 -
    - -
    -2024/08/01 0.6.2b1发布,优化了依赖冲突问题和安装文档 -
    - -
    -2024/07/05 首次开源 -
    - - - - -
    -

    文档目录

    -
      -
    1. - MinerU - -
    2. -
    3. TODO
    4. -
    5. Known Issues
    6. -
    7. FAQ
    8. -
    9. Contributors
    10. -
    11. License Information
    12. -
    13. Acknowledgements
    14. -
    15. Citation
    16. -
    17. Star History
    18. -
    19. magic-doc快速提取PPT/DOC/PDF
    20. -
    21. magic-html提取混合网页内容
    22. -
    23. Links
    24. -
    -
    # MinerU @@ -312,14 +411,10 @@ https://github.com/user-attachments/assets/4bea02c9-6d54-4cd6-97ed-dff14340982c 如果遇到任何安装问题,请先查询 FAQ
    如果遇到解析效果不及预期,参考 Known Issues
    -有3种不同方式可以体验MinerU的效果: +有2种不同方式可以体验MinerU的效果: -- [在线体验(无需任何安装)](#在线体验) -- [使用CPU快速体验(Windows,Linux,Mac)](#使用cpu快速体验) -- 使用 CUDA/CANN/MPS 加速推理 - - [Linux/Windows + CUDA](#使用gpu) - - [Linux + CANN](#使用npu) - - [MacOS + MPS](#使用mps) +- [在线体验](#在线体验) +- [本地部署](#本地部署) > [!WARNING] @@ -331,184 +426,236 @@ https://github.com/user-attachments/assets/4bea02c9-6d54-4cd6-97ed-dff14340982c > > 在非主线环境中,由于硬件、软件配置的多样性,以及第三方依赖项的兼容性问题,我们无法100%保证项目的完全可用性。因此,对于希望在非推荐环境中使用本项目的用户,我们建议先仔细阅读文档以及FAQ,大多数问题已经在FAQ中有对应的解决方案,除此之外我们鼓励社区反馈问题,以便我们能够逐步扩大支持范围。 - - - - +
    操作系统
    - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - - + + + + - - - - - - - - - - - - - - - + + + +
    Linux after 2019Windows 10 / 11macOS 11+解析后端pipelinevlm-transformersvlm-sgslang
    CPUx86_64 / arm64x86_64(暂不支持ARM Windows)x86_64 / arm64操作系统windows/linux/macwindows/linuxwindows(wsl2)/linux
    内存大于等于16GB,推荐32G以上内存要求最低16G以上,推荐32G以上
    存储空间大于等于20GB,推荐使用SSD以获得最佳性能磁盘空间要求20G以上,推荐使用SSD
    python版本3.10~3.13python版本3.10-3.13
    Nvidia Driver 版本latest(专有驱动)latestNoneCPU推理支持
    CUDA环境Refer to the PyTorch official websiteNone
    CANN环境(NPU支持)8.0+(Ascend 910b)NoneNone
    GPU/MPS 硬件支持列表显存6G以上 - Volta(2017)及之后生产的全部带Tensor Core的GPU
    - 6G显存及以上
    Apple siliconGPU要求Turing及以后架构,6G显存以上或Apple SiliconAmpere及以后架构,8G显存以上Ampere及以后架构,24G显存及以上
    -### 在线体验 - -同步dev分支更新: +## 在线体验 [![OpenDataLab](https://img.shields.io/badge/Demo_on_OpenDataLab-blue?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTM0IiBoZWlnaHQ9IjEzNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMTIyLDljMCw1LTQsOS05LDlzLTktNC05LTksNC05LDktOSw5LDQsOSw5eiIgZmlsbD0idXJsKCNhKSIvPjxwYXRoIGQ9Im0xMjIsOWMwLDUtNCw5LTksOXMtOS00LTktOSw0LTksOS05LDksNCw5LDl6IiBmaWxsPSIjMDEwMTAxIi8+PHBhdGggZD0ibTkxLDE4YzAsNS00LDktOSw5cy05LTQtOS05LDQtOSw5LTksOSw0LDksOXoiIGZpbGw9InVybCgjYikiLz48cGF0aCBkPSJtOTEsMThjMCw1LTQsOS05LDlzLTktNC05LTksNC05LDktOSw5LDQsOSw5eiIgZmlsbD0iIzAxMDEwMSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJtMzksNjJjMCwxNiw4LDMwLDIwLDM4LDctNiwxMi0xNiwxMi0yNlY0OWMwLTQsMy03LDYtOGw0Ni0xMmM1LTEsMTEsMywxMSw4djMxYzAsMzctMzAsNjYtNjYsNjYtMzcsMC02Ni0zMC02Ni02NlY0NmMwLTQsMy03LDYtOGwyMC02YzUtMSwxMSwzLDExLDh2MjF6bS0yOSw2YzAsMTYsNiwzMCwxNyw0MCwzLDEsNSwxLDgsMSw1LDAsMTAtMSwxNS0zQzM3LDk1LDI5LDc5LDI5LDYyVjQybC0xOSw1djIweiIgZmlsbD0idXJsKCNjKSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJtMzksNjJjMCwxNiw4LDMwLDIwLDM4LDctNiwxMi0xNiwxMi0yNlY0OWMwLTQsMy03LDYtOGw0Ni0xMmM1LTEsMTEsMywxMSw4djMxYzAsMzctMzAsNjYtNjYsNjYtMzcsMC02Ni0zMC02Ni02NlY0NmMwLTQsMy03LDYtOGwyMC02YzUtMSwxMSwzLDExLDh2MjF6bS0yOSw2YzAsMTYsNiwzMCwxNyw0MCwzLDEsNSwxLDgsMSw1LDAsMTAtMSwxNS0zQzM3LDk1LDI5LDc5LDI5LDYyVjQybC0xOSw1djIweiIgZmlsbD0iIzAxMDEwMSIvPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iYSIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYyIgeDE9Ijg0IiB5MT0iNDEiIHgyPSI3NSIgeTI9IjEyMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMyZTJlMmUiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48L3N2Zz4=&labelColor=white)](https://mineru.net/OpenSourceTools/Extractor?source=github) [![ModelScope](https://img.shields.io/badge/Demo_on_ModelScope-purple?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIzIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCiA8Zz4KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+CiAgPHBhdGggaWQ9InN2Z18xNCIgZmlsbD0iIzYyNGFmZiIgZD0ibTAsODkuODRsMjUuNjUsMGwwLDI1LjY0OTk5bC0yNS42NSwwbDAsLTI1LjY0OTk5eiIvPgogIDxwYXRoIGlkPSJzdmdfMTUiIGZpbGw9IiM2MjRhZmYiIGQ9Im05OS4xNCwxMTUuNDlsMjUuNjUsMGwwLDI1LjY1bC0yNS42NSwwbDAsLTI1LjY1eiIvPgogIDxwYXRoIGlkPSJzdmdfMTYiIGZpbGw9IiM2MjRhZmYiIGQ9Im0xNzYuMDksMTQxLjE0bC0yNS42NDk5OSwwbDAsMjIuMTlsNDcuODQsMGwwLC00Ny44NGwtMjIuMTksMGwwLDI1LjY1eiIvPgogIDxwYXRoIGlkPSJzdmdfMTciIGZpbGw9IiMzNmNmZDEiIGQ9Im0xMjQuNzksODkuODRsMjUuNjUsMGwwLDI1LjY0OTk5bC0yNS42NSwwbDAsLTI1LjY0OTk5eiIvPgogIDxwYXRoIGlkPSJzdmdfMTgiIGZpbGw9IiMzNmNmZDEiIGQ9Im0wLDY0LjE5bDI1LjY1LDBsMCwyNS42NWwtMjUuNjUsMGwwLC0yNS42NXoiLz4KICA8cGF0aCBpZD0ic3ZnXzE5IiBmaWxsPSIjNjI0YWZmIiBkPSJtMTk4LjI4LDg5Ljg0bDI1LjY0OTk5LDBsMCwyNS42NDk5OWwtMjUuNjQ5OTksMGwwLC0yNS42NDk5OXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIwIiBmaWxsPSIjMzZjZmQxIiBkPSJtMTk4LjI4LDY0LjE5bDI1LjY0OTk5LDBsMCwyNS42NWwtMjUuNjQ5OTksMGwwLC0yNS42NXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIxIiBmaWxsPSIjNjI0YWZmIiBkPSJtMTUwLjQ0LDQybDAsMjIuMTlsMjUuNjQ5OTksMGwwLDI1LjY1bDIyLjE5LDBsMCwtNDcuODRsLTQ3Ljg0LDB6Ii8+CiAgPHBhdGggaWQ9InN2Z18yMiIgZmlsbD0iIzM2Y2ZkMSIgZD0ibTczLjQ5LDg5Ljg0bDI1LjY1LDBsMCwyNS42NDk5OWwtMjUuNjUsMGwwLC0yNS42NDk5OXoiLz4KICA8cGF0aCBpZD0ic3ZnXzIzIiBmaWxsPSIjNjI0YWZmIiBkPSJtNDcuODQsNjQuMTlsMjUuNjUsMGwwLC0yMi4xOWwtNDcuODQsMGwwLDQ3Ljg0bDIyLjE5LDBsMCwtMjUuNjV6Ii8+CiAgPHBhdGggaWQ9InN2Z18yNCIgZmlsbD0iIzYyNGFmZiIgZD0ibTQ3Ljg0LDExNS40OWwtMjIuMTksMGwwLDQ3Ljg0bDQ3Ljg0LDBsMCwtMjIuMTlsLTI1LjY1LDBsMCwtMjUuNjV6Ii8+CiA8L2c+Cjwvc3ZnPg==&labelColor=white)](https://www.modelscope.cn/studios/OpenDataLab/MinerU) [![HuggingFace](https://img.shields.io/badge/Demo_on_HuggingFace-yellow.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAABYCAMAAACkl9t/AAAAk1BMVEVHcEz/nQv/nQv/nQr/nQv/nQr/nQv/nQv/nQr/wRf/txT/pg7/yRr/rBD/zRz/ngv/oAz/zhz/nwv/txT/ngv/0B3+zBz/nQv/0h7/wxn/vRb/thXkuiT/rxH/pxD/ogzcqyf/nQvTlSz/czCxky7/SjifdjT/Mj3+Mj3wMj15aTnDNz+DSD9RTUBsP0FRO0Q6O0WyIxEIAAAAGHRSTlMADB8zSWF3krDDw8TJ1NbX5efv8ff9/fxKDJ9uAAAGKklEQVR42u2Z63qjOAyGC4RwCOfB2JAGqrSb2WnTw/1f3UaWcSGYNKTdf/P+mOkTrE+yJBulvfvLT2A5ruenaVHyIks33npl/6C4s/ZLAM45SOi/1FtZPyFur1OYofBX3w7d54Bxm+E8db+nDr12ttmESZ4zludJEG5S7TO72YPlKZFyE+YCYUJTBZsMiNS5Sd7NlDmKM2Eg2JQg8awbglfqgbhArjxkS7dgp2RH6hc9AMLdZYUtZN5DJr4molC8BfKrEkPKEnEVjLbgW1fLy77ZVOJagoIcLIl+IxaQZGjiX597HopF5CkaXVMDO9Pyix3AFV3kw4lQLCbHuMovz8FallbcQIJ5Ta0vks9RnolbCK84BtjKRS5uA43hYoZcOBGIG2Epbv6CvFVQ8m8loh66WNySsnN7htL58LNp+NXT8/PhXiBXPMjLSxtwp8W9f/1AngRierBkA+kk/IpUSOeKByzn8y3kAAAfh//0oXgV4roHm/kz4E2z//zRc3/lgwBzbM2mJxQEa5pqgX7d1L0htrhx7LKxOZlKbwcAWyEOWqYSI8YPtgDQVjpB5nvaHaSnBaQSD6hweDi8PosxD6/PT09YY3xQA7LTCTKfYX+QHpA0GCcqmEHvr/cyfKQTEuwgbs2kPxJEB0iNjfJcCTPyocx+A0griHSmADiC91oNGVwJ69RudYe65vJmoqfpul0lrqXadW0jFKH5BKwAeCq+Den7s+3zfRJzA61/Uj/9H/VzLKTx9jFPPdXeeP+L7WEvDLAKAIoF8bPTKT0+TM7W8ePj3Rz/Yn3kOAp2f1Kf0Weony7pn/cPydvhQYV+eFOfmOu7VB/ViPe34/EN3RFHY/yRuT8ddCtMPH/McBAT5s+vRde/gf2c/sPsjLK+m5IBQF5tO+h2tTlBGnP6693JdsvofjOPnnEHkh2TnV/X1fBl9S5zrwuwF8NFrAVJVwCAPTe8gaJlomqlp0pv4Pjn98tJ/t/fL++6unpR1YGC2n/KCoa0tTLoKiEeUPDl94nj+5/Tv3/eT5vBQ60X1S0oZr+IWRR8Ldhu7AlLjPISlJcO9vrFotky9SpzDequlwEir5beYAc0R7D9KS1DXva0jhYRDXoExPdc6yw5GShkZXe9QdO/uOvHofxjrV/TNS6iMJS+4TcSTgk9n5agJdBQbB//IfF/HpvPt3Tbi7b6I6K0R72p6ajryEJrENW2bbeVUGjfgoals4L443c7BEE4mJO2SpbRngxQrAKRudRzGQ8jVOL2qDVjjI8K1gc3TIJ5KiFZ1q+gdsARPB4NQS4AjwVSt72DSoXNyOWUrU5mQ9nRYyjp89Xo7oRI6Bga9QNT1mQ/ptaJq5T/7WcgAZywR/XlPGAUDdet3LE+qS0TI+g+aJU8MIqjo0Kx8Ly+maxLjJmjQ18rA0YCkxLQbUZP1WqdmyQGJLUm7VnQFqodmXSqmRrdVpqdzk5LvmvgtEcW8PMGdaS23EOWyDVbACZzUJPaqMbjDxpA3Qrgl0AikimGDbqmyT8P8NOYiqrldF8rX+YN7TopX4UoHuSCYY7cgX4gHwclQKl1zhx0THf+tCAUValzjI7Wg9EhptrkIcfIJjA94evOn8B2eHaVzvBrnl2ig0So6hvPaz0IGcOvTHvUIlE2+prqAxLSQxZlU2stql1NqCCLdIiIN/i1DBEHUoElM9dBravbiAnKqgpi4IBkw+utSPIoBijDXJipSVV7MpOEJUAc5Qmm3BnUN+w3hteEieYKfRZSIUcXKMVf0u5wD4EwsUNVvZOtUT7A2GkffHjByWpHqvRBYrTV72a6j8zZ6W0DTE86Hn04bmyWX3Ri9WH7ZU6Q7h+ZHo0nHUAcsQvVhXRDZHChwiyi/hnPuOsSEF6Exk3o6Y9DT1eZ+6cASXk2Y9k+6EOQMDGm6WBK10wOQJCBwren86cPPWUcRAnTVjGcU1LBgs9FURiX/e6479yZcLwCBmTxiawEwrOcleuu12t3tbLv/N4RLYIBhYexm7Fcn4OJcn0+zc+s8/VfPeddZHAGN6TT8eGczHdR/Gts1/MzDkThr23zqrVfAMFT33Nx1RJsx1k5zuWILLnG/vsH+Fv5D4NTVcp1Gzo8AAAAAElFTkSuQmCC&labelColor=white)](https://huggingface.co/spaces/opendatalab/MinerU) -### 使用CPU快速体验 +### 🚀🚀🚀VLM demo +[![HuggingFace](https://img.shields.io/badge/VLM_Demo_on_HuggingFace-yellow.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAABYCAMAAACkl9t/AAAAk1BMVEVHcEz/nQv/nQv/nQr/nQv/nQr/nQv/nQv/nQr/wRf/txT/pg7/yRr/rBD/zRz/ngv/oAz/zhz/nwv/txT/ngv/0B3+zBz/nQv/0h7/wxn/vRb/thXkuiT/rxH/pxD/ogzcqyf/nQvTlSz/czCxky7/SjifdjT/Mj3+Mj3wMj15aTnDNz+DSD9RTUBsP0FRO0Q6O0WyIxEIAAAAGHRSTlMADB8zSWF3krDDw8TJ1NbX5efv8ff9/fxKDJ9uAAAGKklEQVR42u2Z63qjOAyGC4RwCOfB2JAGqrSb2WnTw/1f3UaWcSGYNKTdf/P+mOkTrE+yJBulvfvLT2A5ruenaVHyIks33npl/6C4s/ZLAM45SOi/1FtZPyFur1OYofBX3w7d54Bxm+E8db+nDr12ttmESZ4zludJEG5S7TO72YPlKZFyE+YCYUJTBZsMiNS5Sd7NlDmKM2Eg2JQg8awbglfqgbhArjxkS7dgp2RH6hc9AMLdZYUtZN5DJr4molC8BfKrEkPKEnEVjLbgW1fLy77ZVOJagoIcLIl+IxaQZGjiX597HopF5CkaXVMDO9Pyix3AFV3kw4lQLCbHuMovz8FallbcQIJ5Ta0vks9RnolbCK84BtjKRS5uA43hYoZcOBGIG2Epbv6CvFVQ8m8loh66WNySsnN7htL58LNp+NXT8/PhXiBXPMjLSxtwp8W9f/1AngRierBkA+kk/IpUSOeKByzn8y3kAAAfh//0oXgV4roHm/kz4E2z//zRc3/lgwBzbM2mJxQEa5pqgX7d1L0htrhx7LKxOZlKbwcAWyEOWqYSI8YPtgDQVjpB5nvaHaSnBaQSD6hweDi8PosxD6/PT09YY3xQA7LTCTKfYX+QHpA0GCcqmEHvr/cyfKQTEuwgbs2kPxJEB0iNjfJcCTPyocx+A0griHSmADiC91oNGVwJ69RudYe65vJmoqfpul0lrqXadW0jFKH5BKwAeCq+Den7s+3zfRJzA61/Uj/9H/VzLKTx9jFPPdXeeP+L7WEvDLAKAIoF8bPTKT0+TM7W8ePj3Rz/Yn3kOAp2f1Kf0Weony7pn/cPydvhQYV+eFOfmOu7VB/ViPe34/EN3RFHY/yRuT8ddCtMPH/McBAT5s+vRde/gf2c/sPsjLK+m5IBQF5tO+h2tTlBGnP6693JdsvofjOPnnEHkh2TnV/X1fBl9S5zrwuwF8NFrAVJVwCAPTe8gaJlomqlp0pv4Pjn98tJ/t/fL++6unpR1YGC2n/KCoa0tTLoKiEeUPDl94nj+5/Tv3/eT5vBQ60X1S0oZr+IWRR8Ldhu7AlLjPISlJcO9vrFotky9SpzDequlwEir5beYAc0R7D9KS1DXva0jhYRDXoExPdc6yw5GShkZXe9QdO/uOvHofxjrV/TNS6iMJS+4TcSTgk9n5agJdBQbB//IfF/HpvPt3Tbi7b6I6K0R72p6ajryEJrENW2bbeVUGjfgoals4L443c7BEE4mJO2SpbRngxQrAKRudRzGQ8jVOL2qDVjjI8K1gc3TIJ5KiFZ1q+gdsARPB4NQS4AjwVSt72DSoXNyOWUrU5mQ9nRYyjp89Xo7oRI6Bga9QNT1mQ/ptaJq5T/7WcgAZywR/XlPGAUDdet3LE+qS0TI+g+aJU8MIqjo0Kx8Ly+maxLjJmjQ18rA0YCkxLQbUZP1WqdmyQGJLUm7VnQFqodmXSqmRrdVpqdzk5LvmvgtEcW8PMGdaS23EOWyDVbACZzUJPaqMbjDxpA3Qrgl0AikimGDbqmyT8P8NOYiqrldF8rX+YN7TopX4UoHuSCYY7cgX4gHwclQKl1zhx0THf+tCAUValzjI7Wg9EhptrkIcfIJjA94evOn8B2eHaVzvBrnl2ig0So6hvPaz0IGcOvTHvUIlE2+prqAxLSQxZlU2stql1NqCCLdIiIN/i1DBEHUoElM9dBravbiAnKqgpi4IBkw+utSPIoBijDXJipSVV7MpOEJUAc5Qmm3BnUN+w3hteEieYKfRZSIUcXKMVf0u5wD4EwsUNVvZOtUT7A2GkffHjByWpHqvRBYrTV72a6j8zZ6W0DTE86Hn04bmyWX3Ri9WH7ZU6Q7h+ZHo0nHUAcsQvVhXRDZHChwiyi/hnPuOsSEF6Exk3o6Y9DT1eZ+6cASXk2Y9k+6EOQMDGm6WBK10wOQJCBwren86cPPWUcRAnTVjGcU1LBgs9FURiX/e6479yZcLwCBmTxiawEwrOcleuu12t3tbLv/N4RLYIBhYexm7Fcn4OJcn0+zc+s8/VfPeddZHAGN6TT8eGczHdR/Gts1/MzDkThr23zqrVfAMFT33Nx1RJsx1k5zuWILLnG/vsH+Fv5D4NTVcp1Gzo8AAAAAElFTkSuQmCC&labelColor=white)](https://huggingface.co/spaces/opendatalab/mineru2) + +## 本地部署 + +### 1. 安装 MinerU -#### 1. 安装magic-pdf +#### 1.1 使用 pip 或 uv 安装 -> [!NOTE] -> 最新版本国内镜像源同步可能会有延迟,请耐心等待 +```bash +pip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple +pip install uv -i https://mirrors.aliyun.com/pypi/simple +uv pip install "mineru[core]>=2.0.0" -i https://mirrors.aliyun.com/pypi/simple +``` + +#### 1.2 源码安装 ```bash -conda create -n mineru 'python=3.12' -y -conda activate mineru -pip install -U "magic-pdf[full]" -i https://mirrors.aliyun.com/pypi/simple +git clone https://github.com/opendatalab/MinerU.git +cd MinerU +uv pip install -e .[core] -i https://mirrors.aliyun.com/pypi/simple ``` -#### 2. 下载模型权重文件 +#### 1.3 安装完整版(支持 sglang 加速) -详细参考 [如何下载模型文件](docs/how_to_download_models_zh_cn.md) +如需使用 **sglang 加速 VLM 模型推理**,请安装完整版本: -#### 3. 修改配置文件以进行额外配置 +```bash +uv pip install "mineru[all]>=2.0.0" -i https://mirrors.aliyun.com/pypi/simple +``` -完成[2. 下载模型权重文件](#2-下载模型权重文件)步骤后,脚本会自动生成用户目录下的magic-pdf.json文件,并自动配置默认模型路径。 -您可在【用户目录】下找到magic-pdf.json文件。 +或从源码安装: -> [!TIP] -> windows的用户目录为 "C:\\Users\\用户名", linux用户目录为 "/home/用户名", macOS用户目录为 "/Users/用户名" +```bash +uv pip install -e .[all] -i https://mirrors.aliyun.com/pypi/simple +``` -您可修改该文件中的部分配置实现功能的开关,如表格识别功能: +--- -> [!NOTE] ->如json内没有如下项目,请手动添加需要的项目,并删除注释内容(标准json不支持注释) +### 2. 使用 MinerU -```json -{ - // other config - "layout-config": { - "model": "doclayout_yolo" - }, - "formula-config": { - "mfd_model": "yolo_v8_mfd", - "mfr_model": "unimernet_small", - "enable": true // 公式识别功能默认是开启的,如果需要关闭请修改此处的值为"false" - }, - "table-config": { - "model": "rapid_table", - "sub_model": "slanet_plus", - "enable": true, // 表格识别功能默认是开启的,如果需要关闭请修改此处的值为"false" - "max_time": 400 - } -} +#### 2.1 命令行使用方式 + +##### 基础用法 + +最简单的命令行调用方式如下: + +```bash +mineru -p -o ``` -### 使用GPU +- ``:本地 PDF 文件或目录(支持 pdf/png/jpg/jpeg) +- ``:输出目录 -如果您的设备支持CUDA,且满足主线环境中的显卡要求,则可以使用GPU加速,请根据自己的系统选择适合的教程: +##### 查看帮助信息 -- [Ubuntu22.04LTS + GPU](docs/README_Ubuntu_CUDA_Acceleration_zh_CN.md) -- [Windows10/11 + GPU](docs/README_Windows_CUDA_Acceleration_zh_CN.md) -- 使用Docker快速部署 -> [!IMPORTANT] -> Docker 需设备gpu显存大于等于6GB,默认开启所有加速功能 -> -> 运行本docker前可以通过以下命令检测自己的设备是否支持在docker上使用CUDA加速 -> -> ```bash -> docker run --rm --gpus=all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi -> ``` - ```bash - wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/docker/china/Dockerfile -O Dockerfile - docker build -t mineru:latest . - docker run -it --name mineru --gpus=all mineru:latest /bin/bash -c "echo 'source /opt/mineru_venv/bin/activate' >> ~/.bashrc && exec bash" - magic-pdf --help - ``` -### 使用NPU - -如果您的设备存在NPU加速硬件,则可以通过以下教程使用NPU加速: - -[NPU加速教程](docs/README_Ascend_NPU_Acceleration_zh_CN.md) - -### 使用MPS -如果您的设备使用Apple silicon 芯片,您可以开启mps加速: - -您可以通过在 `magic-pdf.json` 配置文件中将 `device-mode` 参数设置为 `mps` 来启用 MPS 加速。 - -```json -{ - // other config - "device-mode": "mps" -} +获取所有可用参数说明: + +```bash +mineru --help +``` + +##### 参数详解 + +```text +Usage: mineru [OPTIONS] + +Options: + -v, --version 显示版本并退出 + -p, --path PATH 输入文件路径或目录(必填) + -o, --output PATH 输出目录(必填) + -m, --method [auto|txt|ocr] 解析方法:auto(默认)、txt、ocr(仅用于 pipeline 后端) + -b, --backend [pipeline|vlm-transformers|vlm-sglang-engine|vlm-sglang-client] + 解析后端(默认为 pipeline) + -l, --lang [ch|ch_server|... ] 指定文档语言(可提升 OCR 准确率,仅用于 pipeline 后端) + -u, --url TEXT 当使用 sglang-client 时,需指定服务地址 + -s, --start INTEGER 开始解析的页码(从 0 开始) + -e, --end INTEGER 结束解析的页码(从 0 开始) + -f, --formula BOOLEAN 是否启用公式解析(默认开启,仅 pipeline 后端) + -t, --table BOOLEAN 是否启用表格解析(默认开启,仅 pipeline 后端) + -d, --device TEXT 推理设备(如 cpu/cuda/cuda:0/npu/mps,仅 pipeline 后端) + --vram INTEGER 单进程最大 GPU 显存占用(仅 pipeline 后端) + --source [huggingface|modelscope|local] + 模型来源,默认 huggingface + --help 显示帮助信息 ``` +--- + +#### 2.2 模型源配置 + +MinerU 默认在首次运行时自动从 HuggingFace 下载所需模型。若无法访问 HuggingFace,可通过以下方式切换模型源: + +##### 切换至 ModelScope 源 + +```bash +mineru -p -o --source modelscope +``` + +或设置环境变量: + +```bash +export MINERU_MODEL_SOURCE=modelscope +mineru -p -o +``` + +##### 使用本地模型 + +###### 1. 下载模型到本地 +```bash +mineru-models-download --help +``` + +或使用交互式命令行工具选择模型下载: + +```bash +mineru-models-download +``` + +下载完成后,模型路径会在当前终端窗口输出,并自动写入用户目录下的 `mineru.json`。 + +###### 2. 使用本地模型进行解析 + +```bash +mineru -p -o --source local +``` + +或通过环境变量启用: + +```bash +export MINERU_MODEL_SOURCE=local +mineru -p -o +``` + +--- + +#### 2.3 使用 sglang 加速 VLM 模型推理 + +##### 启动 sglang-engine 模式 + +```bash +mineru -p -o -b vlm-sglang-engine +``` + +##### 启动 sglang-server/client 模式 + +1. 启动 Server: + +```bash +mineru-sglang-server --port 30000 +``` + +2. 在另一个终端中使用 Client 调用: + +```bash +mineru -p -o -b vlm-sglang-client -u http://127.0.0.1:30000 +``` -## 使用 +> 💡 更多关于输出文件的信息,请参考 [输出文件说明](docs/output_file_zh_cn.md) -### 命令行 +--- -[通过命令行使用MinerU](https://mineru.readthedocs.io/en/latest/user_guide/usage/command_line.html) +### 3. API 调用方式 -> [!TIP] -> 更多有关输出文件的信息,请参考[输出文件说明](docs/output_file_zh_cn.md) +您也可以通过 Python 代码调用 MinerU,示例代码请参考: +👉 [Python 调用示例](demo/demo.py) -### API +--- -[通过Python代码调用MinerU](https://mineru.readthedocs.io/en/latest/user_guide/usage/api.html) +### 4. 部署衍生项目 +社区开发者基于 MinerU 进行了多种二次开发,包括: -### 部署衍生项目 +- 基于 Gradio 的图形界面 +- 基于 FastAPI 的 Web API +- 多卡负载均衡的客户端/服务端架构等 -衍生项目包含项目开发者和社群开发者们基于MinerU的二次开发项目, -例如基于Gradio的应用界面、基于llama的RAG、官网同款web demo、轻量级的多卡负载均衡c/s端等, -这些项目可能会提供更多的功能和更好的用户体验。 -具体部署方式请参考 [衍生项目readme](projects/README_zh-CN.md) +这些项目通常提供更好的用户体验和更多功能。 +详细部署方式请参阅: +👉 [衍生项目说明](projects/README_zh-CN.md) -### 二次开发 +--- -TODO # TODO @@ -548,21 +695,22 @@ TODO [LICENSE.md](LICENSE.md) -本项目目前采用PyMuPDF以实现高级功能,但因其遵循AGPL协议,可能对某些使用场景构成限制。未来版本迭代中,我们计划探索并替换为许可条款更为宽松的PDF处理库,以提升用户友好度及灵活性。 +本项目目前部分模型基于YOLO训练,但因其遵循AGPL协议,可能对某些使用场景构成限制。未来版本迭代中,我们计划探索并替换为许可条款更为宽松的模型,以提升用户友好度及灵活性。 # Acknowledgments - [PDF-Extract-Kit](https://github.com/opendatalab/PDF-Extract-Kit) - [DocLayout-YOLO](https://github.com/opendatalab/DocLayout-YOLO) -- [StructEqTable](https://github.com/UniModal4Reasoning/StructEqTable-Deploy) +- [UniMERNet](https://github.com/opendatalab/UniMERNet) - [RapidTable](https://github.com/RapidAI/RapidTable) - [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) -- [RapidOCR](https://github.com/RapidAI/RapidOCR) - [PaddleOCR2Pytorch](https://github.com/frotms/PaddleOCR2Pytorch) -- [PyMuPDF](https://github.com/pymupdf/PyMuPDF) - [layoutreader](https://github.com/ppaanngggg/layoutreader) +- [xy-cut](https://github.com/Sanster/xy-cut) - [fast-langdetect](https://github.com/LlmKira/fast-langdetect) +- [pypdfium2](https://github.com/pypdfium2-team/pypdfium2) - [pdfminer.six](https://github.com/pdfminer/pdfminer.six) +- [pypdf](https://github.com/py-pdf/pypdf) # Citation diff --git a/demo/batch_demo.py b/demo/batch_demo.py deleted file mode 100644 index 7f3cf468d6496725a2121e5b129e2e18f3572e43..0000000000000000000000000000000000000000 --- a/demo/batch_demo.py +++ /dev/null @@ -1,23 +0,0 @@ -import os -from pathlib import Path -from magic_pdf.data.batch_build_dataset import batch_build_dataset -from magic_pdf.tools.common import batch_do_parse - - -def batch(pdf_dir, output_dir, method, lang): - os.makedirs(output_dir, exist_ok=True) - doc_paths = [] - for doc_path in Path(pdf_dir).glob('*'): - if doc_path.suffix == '.pdf': - doc_paths.append(doc_path) - - # build dataset with 2 workers - datasets = batch_build_dataset(doc_paths, 4, lang) - - # os.environ["MINERU_MIN_BATCH_INFERENCE_SIZE"] = "200" # every 200 pages will be parsed in one batch - batch_do_parse(output_dir, [str(doc_path.stem) for doc_path in doc_paths], datasets, method) - - -if __name__ == '__main__': - batch("pdfs", "output", "auto", "") - diff --git a/demo/demo.py b/demo/demo.py index 2a1377b64b70a7d5adfdee745c9002a03cf7699a..c4094cd405603e4a189dad4729f6a9946e0501c9 100644 --- a/demo/demo.py +++ b/demo/demo.py @@ -1,68 +1,243 @@ # Copyright (c) Opendatalab. All rights reserved. +import copy +import json import os - -from magic_pdf.data.data_reader_writer import FileBasedDataWriter, FileBasedDataReader -from magic_pdf.data.dataset import PymuDocDataset -from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze -from magic_pdf.config.enums import SupportedPdfParseMethod - -# args -__dir__ = os.path.dirname(os.path.abspath(__file__)) -pdf_file_name = os.path.join(__dir__, "pdfs", "demo1.pdf") # replace with the real pdf path -name_without_extension = os.path.basename(pdf_file_name).split('.')[0] - -# prepare env -local_image_dir = os.path.join(__dir__, "output", name_without_extension, "images") -local_md_dir = os.path.join(__dir__, "output", name_without_extension) -image_dir = str(os.path.basename(local_image_dir)) -os.makedirs(local_image_dir, exist_ok=True) - -image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter(local_md_dir) - -# read bytes -reader1 = FileBasedDataReader("") -pdf_bytes = reader1.read(pdf_file_name) # read the pdf content - -# proc -## Create Dataset Instance -ds = PymuDocDataset(pdf_bytes) - -## inference -if ds.classify() == SupportedPdfParseMethod.OCR: - infer_result = ds.apply(doc_analyze, ocr=True) - - ## pipeline - pipe_result = infer_result.pipe_ocr_mode(image_writer) - -else: - infer_result = ds.apply(doc_analyze, ocr=False) - - ## pipeline - pipe_result = infer_result.pipe_txt_mode(image_writer) - -### get model inference result -model_inference_result = infer_result.get_infer_res() - -### draw layout result on each page -pipe_result.draw_layout(os.path.join(local_md_dir, f"{name_without_extension}_layout.pdf")) - -### draw spans result on each page -pipe_result.draw_span(os.path.join(local_md_dir, f"{name_without_extension}_spans.pdf")) - -### get markdown content -md_content = pipe_result.get_markdown(image_dir) - -### dump markdown -pipe_result.dump_md(md_writer, f"{name_without_extension}.md", image_dir) - -### get content list content -content_list_content = pipe_result.get_content_list(image_dir) - -### dump content list -pipe_result.dump_content_list(md_writer, f"{name_without_extension}_content_list.json", image_dir) - -### get middle json -middle_json_content = pipe_result.get_middle_json() - -### dump middle json -pipe_result.dump_middle_json(md_writer, f'{name_without_extension}_middle.json') +from pathlib import Path + +from loguru import logger + +from mineru.cli.common import convert_pdf_bytes_to_bytes_by_pypdfium2, prepare_env, read_fn +from mineru.data.data_reader_writer import FileBasedDataWriter +from mineru.utils.draw_bbox import draw_layout_bbox, draw_span_bbox +from mineru.utils.enum_class import MakeMode +from mineru.backend.vlm.vlm_analyze import doc_analyze as vlm_doc_analyze +from mineru.backend.pipeline.pipeline_analyze import doc_analyze as pipeline_doc_analyze +from mineru.backend.pipeline.pipeline_middle_json_mkcontent import union_make as pipeline_union_make +from mineru.backend.pipeline.model_json_to_middle_json import result_to_middle_json as pipeline_result_to_middle_json +from mineru.backend.vlm.vlm_middle_json_mkcontent import union_make as vlm_union_make +from mineru.utils.models_download_utils import auto_download_and_get_model_root_path + + +def do_parse( + output_dir, # Output directory for storing parsing results + pdf_file_names: list[str], # List of PDF file names to be parsed + pdf_bytes_list: list[bytes], # List of PDF bytes to be parsed + p_lang_list: list[str], # List of languages for each PDF, default is 'ch' (Chinese) + backend="pipeline", # The backend for parsing PDF, default is 'pipeline' + parse_method="auto", # The method for parsing PDF, default is 'auto' + p_formula_enable=True, # Enable formula parsing + p_table_enable=True, # Enable table parsing + server_url=None, # Server URL for vlm-sglang-client backend + f_draw_layout_bbox=True, # Whether to draw layout bounding boxes + f_draw_span_bbox=True, # Whether to draw span bounding boxes + f_dump_md=True, # Whether to dump markdown files + f_dump_middle_json=True, # Whether to dump middle JSON files + f_dump_model_output=True, # Whether to dump model output files + f_dump_orig_pdf=True, # Whether to dump original PDF files + f_dump_content_list=True, # Whether to dump content list files + f_make_md_mode=MakeMode.MM_MD, # The mode for making markdown content, default is MM_MD + start_page_id=0, # Start page ID for parsing, default is 0 + end_page_id=None, # End page ID for parsing, default is None (parse all pages until the end of the document) +): + + if backend == "pipeline": + for idx, pdf_bytes in enumerate(pdf_bytes_list): + new_pdf_bytes = convert_pdf_bytes_to_bytes_by_pypdfium2(pdf_bytes, start_page_id, end_page_id) + pdf_bytes_list[idx] = new_pdf_bytes + + infer_results, all_image_lists, all_pdf_docs, lang_list, ocr_enabled_list = pipeline_doc_analyze(pdf_bytes_list, p_lang_list, parse_method=parse_method, formula_enable=p_formula_enable,table_enable=p_table_enable) + + for idx, model_list in enumerate(infer_results): + model_json = copy.deepcopy(model_list) + pdf_file_name = pdf_file_names[idx] + local_image_dir, local_md_dir = prepare_env(output_dir, pdf_file_name, parse_method) + image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter(local_md_dir) + + images_list = all_image_lists[idx] + pdf_doc = all_pdf_docs[idx] + _lang = lang_list[idx] + _ocr_enable = ocr_enabled_list[idx] + middle_json = pipeline_result_to_middle_json(model_list, images_list, pdf_doc, image_writer, _lang, _ocr_enable, p_formula_enable) + + pdf_info = middle_json["pdf_info"] + + pdf_bytes = pdf_bytes_list[idx] + if f_draw_layout_bbox: + draw_layout_bbox(pdf_info, pdf_bytes, local_md_dir, f"{pdf_file_name}_layout.pdf") + + if f_draw_span_bbox: + draw_span_bbox(pdf_info, pdf_bytes, local_md_dir, f"{pdf_file_name}_span.pdf") + + if f_dump_orig_pdf: + md_writer.write( + f"{pdf_file_name}_origin.pdf", + pdf_bytes, + ) + + if f_dump_md: + image_dir = str(os.path.basename(local_image_dir)) + md_content_str = pipeline_union_make(pdf_info, f_make_md_mode, image_dir) + md_writer.write_string( + f"{pdf_file_name}.md", + md_content_str, + ) + + if f_dump_content_list: + image_dir = str(os.path.basename(local_image_dir)) + content_list = pipeline_union_make(pdf_info, MakeMode.CONTENT_LIST, image_dir) + md_writer.write_string( + f"{pdf_file_name}_content_list.json", + json.dumps(content_list, ensure_ascii=False, indent=4), + ) + + if f_dump_middle_json: + md_writer.write_string( + f"{pdf_file_name}_middle.json", + json.dumps(middle_json, ensure_ascii=False, indent=4), + ) + + if f_dump_model_output: + md_writer.write_string( + f"{pdf_file_name}_model.json", + json.dumps(model_json, ensure_ascii=False, indent=4), + ) + + logger.info(f"local output dir is {local_md_dir}") + else: + if backend.startswith("vlm-"): + backend = backend[4:] + + f_draw_span_bbox = False + parse_method = "vlm" + for idx, pdf_bytes in enumerate(pdf_bytes_list): + pdf_file_name = pdf_file_names[idx] + pdf_bytes = convert_pdf_bytes_to_bytes_by_pypdfium2(pdf_bytes, start_page_id, end_page_id) + local_image_dir, local_md_dir = prepare_env(output_dir, pdf_file_name, parse_method) + image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter(local_md_dir) + middle_json, infer_result = vlm_doc_analyze(pdf_bytes, image_writer=image_writer, backend=backend, server_url=server_url) + + pdf_info = middle_json["pdf_info"] + + if f_draw_layout_bbox: + draw_layout_bbox(pdf_info, pdf_bytes, local_md_dir, f"{pdf_file_name}_layout.pdf") + + if f_draw_span_bbox: + draw_span_bbox(pdf_info, pdf_bytes, local_md_dir, f"{pdf_file_name}_span.pdf") + + if f_dump_orig_pdf: + md_writer.write( + f"{pdf_file_name}_origin.pdf", + pdf_bytes, + ) + + if f_dump_md: + image_dir = str(os.path.basename(local_image_dir)) + md_content_str = vlm_union_make(pdf_info, f_make_md_mode, image_dir) + md_writer.write_string( + f"{pdf_file_name}.md", + md_content_str, + ) + + if f_dump_content_list: + image_dir = str(os.path.basename(local_image_dir)) + content_list = vlm_union_make(pdf_info, MakeMode.CONTENT_LIST, image_dir) + md_writer.write_string( + f"{pdf_file_name}_content_list.json", + json.dumps(content_list, ensure_ascii=False, indent=4), + ) + + if f_dump_middle_json: + md_writer.write_string( + f"{pdf_file_name}_middle.json", + json.dumps(middle_json, ensure_ascii=False, indent=4), + ) + + if f_dump_model_output: + model_output = ("\n" + "-" * 50 + "\n").join(infer_result) + md_writer.write_string( + f"{pdf_file_name}_model_output.txt", + model_output, + ) + + logger.info(f"local output dir is {local_md_dir}") + + +def parse_doc( + path_list: list[Path], + output_dir, + lang="ch", + backend="pipeline", + method="auto", + server_url=None, + start_page_id=0, # Start page ID for parsing, default is 0 + end_page_id=None # End page ID for parsing, default is None (parse all pages until the end of the document) +): + """ + Parameter description: + path_list: List of document paths to be parsed, can be PDF or image files. + output_dir: Output directory for storing parsing results. + lang: Language option, default is 'ch', optional values include['ch', 'ch_server', 'ch_lite', 'en', 'korean', 'japan', 'chinese_cht', 'ta', 'te', 'ka']。 + Input the languages in the pdf (if known) to improve OCR accuracy. Optional. + Adapted only for the case where the backend is set to "pipeline" + backend: the backend for parsing pdf: + pipeline: More general. + vlm-transformers: More general. + vlm-sglang-engine: Faster(engine). + vlm-sglang-client: Faster(client). + without method specified, pipeline will be used by default. + method: the method for parsing pdf: + auto: Automatically determine the method based on the file type. + txt: Use text extraction method. + ocr: Use OCR method for image-based PDFs. + Without method specified, 'auto' will be used by default. + Adapted only for the case where the backend is set to "pipeline". + server_url: When the backend is `sglang-client`, you need to specify the server_url, for example:`http://127.0.0.1:30000` + """ + try: + file_name_list = [] + pdf_bytes_list = [] + lang_list = [] + for path in path_list: + file_name = str(Path(path).stem) + pdf_bytes = read_fn(path) + file_name_list.append(file_name) + pdf_bytes_list.append(pdf_bytes) + lang_list.append(lang) + do_parse( + output_dir=output_dir, + pdf_file_names=file_name_list, + pdf_bytes_list=pdf_bytes_list, + p_lang_list=lang_list, + backend=backend, + parse_method=method, + server_url=server_url, + start_page_id=start_page_id, + end_page_id=end_page_id + ) + except Exception as e: + logger.exception(e) + + +if __name__ == '__main__': + # args + __dir__ = os.path.dirname(os.path.abspath(__file__)) + pdf_files_dir = os.path.join(__dir__, "pdfs") + output_dir = os.path.join(__dir__, "output") + pdf_suffixes = [".pdf"] + image_suffixes = [".png", ".jpeg", ".jpg"] + + doc_path_list = [] + for doc_path in Path(pdf_files_dir).glob('*'): + if doc_path.suffix in pdf_suffixes + image_suffixes: + doc_path_list.append(doc_path) + + """如果您由于网络问题无法下载模型,可以设置环境变量MINERU_MODEL_SOURCE为modelscope使用免代理仓库下载模型""" + # os.environ['MINERU_MODEL_SOURCE'] = "modelscope" + + """Use pipeline mode if your environment does not support VLM""" + parse_doc(doc_path_list, output_dir, backend="pipeline") + + """To enable VLM mode, change the backend to 'vlm-xxx'""" + # parse_doc(doc_path_list, output_dir, backend="vlm-transformers") # more general. + # parse_doc(doc_path_list, output_dir, backend="vlm-sglang-engine") # faster(engine). + # parse_doc(doc_path_list, output_dir, backend="vlm-sglang-client", server_url="http://127.0.0.1:30000") # faster(client). \ No newline at end of file diff --git a/docker/ascend_npu/Dockerfile b/docker/ascend_npu/Dockerfile deleted file mode 100644 index d19d2b69266d38347d5d60e5ae48a73f3693526a..0000000000000000000000000000000000000000 --- a/docker/ascend_npu/Dockerfile +++ /dev/null @@ -1,51 +0,0 @@ -# Use the official Ubuntu base image -FROM swr.cn-central-221.ovaijisuan.com/mindformers/mindformers1.2_mindspore2.3:20240722 - -USER root - -# Set environment variables to non-interactive to avoid prompts during installation -ENV DEBIAN_FRONTEND=noninteractive - -# Update the package list and install necessary packages -RUN apt-get update && \ - apt-get install -y \ - software-properties-common && \ - add-apt-repository -y ppa:deadsnakes/ppa && \ - apt-get update && \ - apt-get install -y \ - python3.10 \ - python3.10-venv \ - python3.10-distutils \ - python3.10-dev \ - python3-pip \ - wget \ - git \ - libgl1 \ - libglib2.0-0 \ - && rm -rf /var/lib/apt/lists/* - -# Set Python 3.10 as the default python3 -RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1 - -# Create a virtual environment for MinerU -RUN python3 -m venv /opt/mineru_venv - -# Copy the configuration file template and install magic-pdf latest -RUN /bin/bash -c "wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/magic-pdf.template.json && \ - cp magic-pdf.template.json /root/magic-pdf.json && \ - source /opt/mineru_venv/bin/activate && \ - pip3 install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple && \ - pip3 install torch==2.3.1 torchvision==0.18.1 -i https://mirrors.aliyun.com/pypi/simple && \ - pip3 install -U magic-pdf[full] 'numpy<2' decorator attrs absl-py cloudpickle ml-dtypes tornado einops -i https://mirrors.aliyun.com/pypi/simple && \ - wget https://gitee.com/ascend/pytorch/releases/download/v6.0.rc2-pytorch2.3.1/torch_npu-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl && \ - pip3 install torch_npu-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl" - -# Download models and update the configuration file -RUN /bin/bash -c "source /opt/mineru_venv/bin/activate && \ - pip3 install modelscope -i https://mirrors.aliyun.com/pypi/simple && \ - wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models.py -O download_models.py && \ - python3 download_models.py && \ - sed -i 's|cpu|npu|g' /root/magic-pdf.json" - -# Set the entry point to activate the virtual environment and run the command line tool -ENTRYPOINT ["/bin/bash", "-c", "source /opt/mineru_venv/bin/activate && exec \"$@\"", "--"] diff --git a/docker/china/Dockerfile b/docker/china/Dockerfile index 6278cec7de6918df9ba11e594dc3c9705906edea..029917b21c6056660d579f12395f9d8f6bb718ce 100644 --- a/docker/china/Dockerfile +++ b/docker/china/Dockerfile @@ -18,37 +18,19 @@ RUN apt-get update && \ wget \ git \ libgl1 \ - libreoffice \ - fonts-noto-cjk \ - fonts-wqy-zenhei \ - fonts-wqy-microhei \ - ttf-mscorefonts-installer \ - fontconfig \ libglib2.0-0 \ - libxrender1 \ - libsm6 \ - libxext6 \ - poppler-utils \ && rm -rf /var/lib/apt/lists/* # Set Python 3.10 as the default python3 RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1 -# Create a virtual environment for MinerU -RUN python3 -m venv /opt/mineru_venv - -# Copy the configuration file template and install magic-pdf latest -RUN /bin/bash -c "wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/magic-pdf.template.json && \ - cp magic-pdf.template.json /root/magic-pdf.json && \ - source /opt/mineru_venv/bin/activate && \ - pip3 install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple && \ - pip3 install -U magic-pdf[full] -i https://mirrors.aliyun.com/pypi/simple" +# install mineru latest +RUN /bin/bash -c "pip3 install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple && \ + pip3 install uv -i https://mirrors.aliyun.com/pypi/simple && \ + uv pip install 'mineru[all]>=2.0.0' -i https://mirrors.aliyun.com/pypi/simple" # Download models and update the configuration file -RUN /bin/bash -c "pip3 install modelscope -i https://mirrors.aliyun.com/pypi/simple && \ - wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models.py -O download_models.py && \ - python3 download_models.py && \ - sed -i 's|cpu|cuda|g' /root/magic-pdf.json" +RUN /bin/bash -c "mineru-models-download -s modelscope -m all" # Set the entry point to activate the virtual environment and run the command line tool -ENTRYPOINT ["/bin/bash", "-c", "source /opt/mineru_venv/bin/activate && exec \"$@\"", "--"] +ENTRYPOINT ["/bin/bash", "-c", "export MINERU_MODEL_SOURCE=local && exec \"$@\"", "--"] \ No newline at end of file diff --git a/docker/global/Dockerfile b/docker/global/Dockerfile index c698c0bc62578599a59fe6f6cc6571cb37553100..7b0c8610078971d02075fcac12bd231da3240d14 100644 --- a/docker/global/Dockerfile +++ b/docker/global/Dockerfile @@ -18,37 +18,19 @@ RUN apt-get update && \ wget \ git \ libgl1 \ - libreoffice \ - fonts-noto-cjk \ - fonts-wqy-zenhei \ - fonts-wqy-microhei \ - ttf-mscorefonts-installer \ - fontconfig \ libglib2.0-0 \ - libxrender1 \ - libsm6 \ - libxext6 \ - poppler-utils \ && rm -rf /var/lib/apt/lists/* # Set Python 3.10 as the default python3 RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1 -# Create a virtual environment for MinerU -RUN python3 -m venv /opt/mineru_venv - -# Copy the configuration file template and install magic-pdf latest -RUN /bin/bash -c "wget https://github.com/opendatalab/MinerU/raw/master/magic-pdf.template.json && \ - cp magic-pdf.template.json /root/magic-pdf.json && \ - source /opt/mineru_venv/bin/activate && \ - pip3 install --upgrade pip && \ - pip3 install -U magic-pdf[full]" +# install mineru latest +RUN /bin/bash -c "pip3 install --upgrade pip && \ + pip3 install uv && \ + uv pip install 'mineru[all]>=2.0.0'" # Download models and update the configuration file -RUN /bin/bash -c "pip3 install huggingface_hub && \ - wget https://github.com/opendatalab/MinerU/raw/master/scripts/download_models_hf.py -O download_models.py && \ - python3 download_models.py && \ - sed -i 's|cpu|cuda|g' /root/magic-pdf.json" +RUN /bin/bash -c "mineru-models-download -s huggingface -m all" # Set the entry point to activate the virtual environment and run the command line tool -ENTRYPOINT ["/bin/bash", "-c", "source /opt/mineru_venv/bin/activate && exec \"$@\"", "--"] +ENTRYPOINT ["/bin/bash", "-c", "export MINERU_MODEL_SOURCE=local && exec \"$@\"", "--"] \ No newline at end of file diff --git a/docs/README_Ascend_NPU_Acceleration_zh_CN.md b/docs/README_Ascend_NPU_Acceleration_zh_CN.md deleted file mode 100644 index a5b4913b34d4602dd61c30c32fa650d26357ffbb..0000000000000000000000000000000000000000 --- a/docs/README_Ascend_NPU_Acceleration_zh_CN.md +++ /dev/null @@ -1,51 +0,0 @@ -# Ascend NPU 加速 - -## 简介 - -本文档介绍如何在 Ascend NPU 上使用 MinerU。本文档内容已在`华为 Atlas 800T A2`服务器上测试通过。 -``` -CPU:鲲鹏 920 aarch64 2.6GHz -NPU:Ascend 910B 64GB -OS:openEuler 22.03 (LTS-SP3)/ Ubuntu 22.04.5 LTS -CANN:8.0.RC2 -驱动版本:24.1.rc2.1 -``` -由于适配 Ascend NPU 的环境较为复杂,建议使用 Docker 容器运行 MinerU。 - -通过docker运行MinerU前需确保物理机已安装支持CANN 8.0.RC2的驱动和固件。 - - -## 构建镜像 -请保持网络状况良好,并执行以下代码构建镜像。 -```bash -wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/docker/ascend_npu/Dockerfile -O Dockerfile -docker build -t mineru_npu:latest . -``` -如果构建过程中未发生报错则说明镜像构建成功。 - - -## 运行容器 - -```bash -docker run -it -u root --name mineru-npu --privileged=true \ - --ipc=host \ - --network=host \ - --device=/dev/davinci0 \ - --device=/dev/davinci1 \ - --device=/dev/davinci2 \ - --device=/dev/davinci3 \ - --device=/dev/davinci4 \ - --device=/dev/davinci5 \ - --device=/dev/davinci6 \ - --device=/dev/davinci7 \ - --device=/dev/davinci_manager \ - --device=/dev/devmm_svm \ - --device=/dev/hisi_hdc \ - -v /var/log/npu/:/usr/slog \ - -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \ - -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ - mineru_npu:latest \ - /bin/bash -c "echo 'source /opt/mineru_venv/bin/activate' >> ~/.bashrc && exec bash" - -magic-pdf --help -``` diff --git a/docs/README_Ubuntu_CUDA_Acceleration_en_US.md b/docs/README_Ubuntu_CUDA_Acceleration_en_US.md deleted file mode 100644 index 3d2a32642196bd628318b439694408adbf4a3820..0000000000000000000000000000000000000000 --- a/docs/README_Ubuntu_CUDA_Acceleration_en_US.md +++ /dev/null @@ -1,111 +0,0 @@ -# Ubuntu 22.04 LTS - -### 1. Check if NVIDIA Drivers Are Installed - -```sh -nvidia-smi -``` - -If you see information similar to the following, it means that the NVIDIA drivers are already installed, and you can skip Step 2. - -> [!NOTE] -> Notice:`CUDA Version` should be >= 12.4, If the displayed version number is less than 12.4, please upgrade the driver. - -```plaintext -+---------------------------------------------------------------------------------------+ -| NVIDIA-SMI 570.133.07 Driver Version: 572.83 CUDA Version: 12.8 | -|-----------------------------------------+----------------------+----------------------+ -| GPU Name TCC/WDDM | Bus-Id Disp.A | Volatile Uncorr. ECC | -| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | -| | | MIG M. | -|=========================================+======================+======================| -| 0 NVIDIA GeForce RTX 3060 Ti WDDM | 00000000:01:00.0 On | N/A | -| 0% 51C P8 12W / 200W | 1489MiB / 8192MiB | 5% Default | -| | | N/A | -+-----------------------------------------+----------------------+----------------------+ -``` - -### 2. Install the Driver - -If no driver is installed, use the following command: - -```sh -sudo apt-get update -sudo apt-get install nvidia-driver-570-server -``` - -Install the proprietary driver and restart your computer after installation. - -```sh -reboot -``` - -### 3. Install Anaconda - -If Anaconda is already installed, skip this step. - -```sh -wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh -bash Anaconda3-2024.06-1-Linux-x86_64.sh -``` - -In the final step, enter `yes`, close the terminal, and reopen it. - -### 4. Create an Environment Using Conda - -```bash -conda create -n mineru 'python=3.12' -y -conda activate mineru -``` - -### 5. Install Applications - -```sh -pip install -U magic-pdf[full] -``` -> [!TIP] -> After installation, you can check the version of `magic-pdf` using the following command: -> -> ```sh -> magic-pdf --version -> ``` - - -### 6. Download Models - - -Refer to detailed instructions on [how to download model files](how_to_download_models_en.md). - - -## 7. Understand the Location of the Configuration File - -After completing the [6. Download Models](#6-download-models) step, the script will automatically generate a `magic-pdf.json` file in the user directory and configure the default model path. -You can find the `magic-pdf.json` file in your user directory. - -> [!TIP] -> The user directory for Linux is "/home/username". - - -### 8. First Run - -Download a sample file from the repository and test it. - -```sh -wget https://github.com/opendatalab/MinerU/raw/master/demo/pdfs/small_ocr.pdf -magic-pdf -p small_ocr.pdf -o ./output -``` - -### 9. Test CUDA Acceleration - -If your graphics card has at least **6GB** of VRAM, follow these steps to test CUDA acceleration: - -1. Modify the value of `"device-mode"` in the `magic-pdf.json` configuration file located in your home directory. - ```json - { - "device-mode": "cuda" - } - ``` -2. Test CUDA acceleration with the following command: - ```sh - magic-pdf -p small_ocr.pdf -o ./output - ``` \ No newline at end of file diff --git a/docs/README_Ubuntu_CUDA_Acceleration_zh_CN.md b/docs/README_Ubuntu_CUDA_Acceleration_zh_CN.md deleted file mode 100644 index ced8aa5c5f6579678f784f8d881f19f36b2da258..0000000000000000000000000000000000000000 --- a/docs/README_Ubuntu_CUDA_Acceleration_zh_CN.md +++ /dev/null @@ -1,115 +0,0 @@ -# Ubuntu 22.04 LTS - -## 1. 检测是否已安装nvidia驱动 - -```bash -nvidia-smi -``` - -如果看到类似如下的信息,说明已经安装了nvidia驱动,可以跳过步骤2 - -> [!NOTE] -> `CUDA Version` 显示的版本号应 >= 12.4,如显示的版本号小于12.4,请升级驱动 - -```plaintext -+---------------------------------------------------------------------------------------+ -| NVIDIA-SMI 570.133.07 Driver Version: 572.83 CUDA Version: 12.8 | -|-----------------------------------------+----------------------+----------------------+ -| GPU Name TCC/WDDM | Bus-Id Disp.A | Volatile Uncorr. ECC | -| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | -| | | MIG M. | -|=========================================+======================+======================| -| 0 NVIDIA GeForce RTX 3060 Ti WDDM | 00000000:01:00.0 On | N/A | -| 0% 51C P8 12W / 200W | 1489MiB / 8192MiB | 5% Default | -| | | N/A | -+-----------------------------------------+----------------------+----------------------+ -``` - -## 2. 安装驱动 - -如没有驱动,则通过如下命令 - -```bash -sudo apt-get update -sudo apt-get install nvidia-driver-570-server -``` - -安装专有驱动,安装完成后,重启电脑 - -```bash -reboot -``` - -## 3. 安装anacoda - -如果已安装conda,可以跳过本步骤 - -```bash -wget -U NoSuchBrowser/1.0 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2024.06-1-Linux-x86_64.sh -bash Anaconda3-2024.06-1-Linux-x86_64.sh -``` - -最后一步输入yes,关闭终端重新打开 - -## 4. 使用conda 创建环境 - -```bash -conda create -n mineru 'python=3.12' -y -conda activate mineru -``` - -## 5. 安装应用 - -```bash -pip install -U magic-pdf[full] -i https://mirrors.aliyun.com/pypi/simple -``` - -> [!TIP] -> 下载完成后,您可以通过以下命令检查`magic-pdf`的版本: -> -> ```bash -> magic-pdf --version -> ``` - - -## 6. 下载模型 - - -详细参考 [如何下载模型文件](how_to_download_models_zh_cn.md) - -## 7. 了解配置文件存放的位置 - -完成[6.下载模型](#6-下载模型)步骤后,脚本会自动生成用户目录下的magic-pdf.json文件,并自动配置默认模型路径。 -您可在【用户目录】下找到magic-pdf.json文件。 - -> [!TIP] -> linux用户目录为 "/home/用户名" - -## 8. 第一次运行 - -从仓库中下载样本文件,并测试 - -```bash -wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/demo/pdfs/small_ocr.pdf -magic-pdf -p small_ocr.pdf -o ./output -``` - -## 9. 测试CUDA加速 - -如果您的显卡显存大于等于 **6GB** ,可以进行以下流程,测试CUDA解析加速效果 - -**1.修改【用户目录】中配置文件magic-pdf.json中"device-mode"的值** - -```json -{ - "device-mode":"cuda" -} -``` - -**2.运行以下命令测试cuda加速效果** - -```bash -magic-pdf -p small_ocr.pdf -o ./output -``` -> [!TIP] -> CUDA加速是否生效可以根据log中输出的各个阶段cost耗时来简单判断,通常情况下,使用cuda加速会比cpu更快。 diff --git a/docs/README_Windows_CUDA_Acceleration_en_US.md b/docs/README_Windows_CUDA_Acceleration_en_US.md deleted file mode 100644 index 28efb304ac8bbbbaeeed3ec84e2afd284bd16ed0..0000000000000000000000000000000000000000 --- a/docs/README_Windows_CUDA_Acceleration_en_US.md +++ /dev/null @@ -1,83 +0,0 @@ -# Windows 10/11 - -### 1. Install CUDA and cuDNN - -You need to install a CUDA version that is compatible with torch's requirements. For details, please refer to the [official PyTorch website](https://pytorch.org/get-started/locally/). - -- CUDA 11.8 https://developer.nvidia.com/cuda-11-8-0-download-archive -- CUDA 12.4 https://developer.nvidia.com/cuda-12-4-0-download-archive -- CUDA 12.6 https://developer.nvidia.com/cuda-12-6-0-download-archive -- CUDA 12.8 https://developer.nvidia.com/cuda-12-8-0-download-archive - -### 2. Install Anaconda - -If Anaconda is already installed, you can skip this step. - -Download link: https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Windows-x86_64.exe - -### 3. Create an Environment Using Conda - -```bash -conda create -n mineru 'python=3.12' -y -conda activate mineru -``` - -### 4. Install Applications - -``` -pip install -U magic-pdf[full] -``` - -> [!IMPORTANT] -> After installation, you can check the version of `magic-pdf` using the following command: -> -> ```bash -> magic-pdf --version -> ``` - - -### 5. Download Models - -Refer to detailed instructions on [how to download model files](how_to_download_models_en.md). - -### 6. Understand the Location of the Configuration File - -After completing the [5. Download Models](#5-download-models) step, the script will automatically generate a `magic-pdf.json` file in the user directory and configure the default model path. -You can find the `magic-pdf.json` file in your 【user directory】 . - -> [!TIP] -> The user directory for Windows is "C:/Users/username". - -### 7. First Run - -Download a sample file from the repository and test it. - -```powershell - wget https://github.com/opendatalab/MinerU/raw/master/demo/pdfs/small_ocr.pdf -O small_ocr.pdf - magic-pdf -p small_ocr.pdf -o ./output -``` - -### 8. Test CUDA Acceleration - -If your graphics card has at least 6GB of VRAM, follow these steps to test CUDA-accelerated parsing performance. - -1. **Overwrite the installation of torch and torchvision** supporting CUDA.(Please select the appropriate index-url based on your CUDA version. For more details, refer to the [PyTorch official website](https://pytorch.org/get-started/locally/).) - - ``` - pip install --force-reinstall torch torchvision --index-url https://download.pytorch.org/whl/cu124 - ``` - -2. **Modify the value of `"device-mode"`** in the `magic-pdf.json` configuration file located in your user directory. - - ```json - { - "device-mode": "cuda" - } - ``` - - -3. **Run the following command to test CUDA acceleration**: - - ``` - magic-pdf -p small_ocr.pdf -o ./output - ``` \ No newline at end of file diff --git a/docs/README_Windows_CUDA_Acceleration_zh_CN.md b/docs/README_Windows_CUDA_Acceleration_zh_CN.md deleted file mode 100644 index 87a189b744d31cfe2039cbf09eb74c67ccf52a5e..0000000000000000000000000000000000000000 --- a/docs/README_Windows_CUDA_Acceleration_zh_CN.md +++ /dev/null @@ -1,86 +0,0 @@ -# Windows10/11 - -## 1. 安装cuda环境 - -需要安装符合torch要求的cuda版本,具体可参考[torch官网](https://pytorch.org/get-started/locally/) - -- CUDA 11.8 https://developer.nvidia.com/cuda-11-8-0-download-archive -- CUDA 12.4 https://developer.nvidia.com/cuda-12-4-0-download-archive -- CUDA 12.6 https://developer.nvidia.com/cuda-12-6-0-download-archive -- CUDA 12.8 https://developer.nvidia.com/cuda-12-8-0-download-archive - -## 2. 安装anaconda - -如果已安装conda,可以跳过本步骤 - -下载链接: -https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2024.06-1-Windows-x86_64.exe - -## 3. 使用conda 创建环境 - -```bash -conda create -n mineru 'python=3.12' -y -conda activate mineru -``` - -## 4. 安装应用 - -```bash -pip install -U magic-pdf[full] -i https://mirrors.aliyun.com/pypi/simple -``` - -> [!IMPORTANT] -> 下载完成后,您可以通过以下命令检查magic-pdf的版本 -> -> ```bash -> magic-pdf --version -> ``` - - -## 5. 下载模型 - -详细参考 [如何下载模型文件](how_to_download_models_zh_cn.md) - -## 6. 了解配置文件存放的位置 - -完成[5.下载模型](#5-下载模型)步骤后,脚本会自动生成用户目录下的magic-pdf.json文件,并自动配置默认模型路径。 -您可在【用户目录】下找到magic-pdf.json文件。 - -> [!TIP] -> windows用户目录为 "C:/Users/用户名" - -## 7. 第一次运行 - -从仓库中下载样本文件,并测试 - -```powershell - wget https://github.com/opendatalab/MinerU/raw/master/demo/pdfs/small_ocr.pdf -O small_ocr.pdf - magic-pdf -p small_ocr.pdf -o ./output -``` - -## 8. 测试CUDA加速 - -如果您的显卡显存大于等于 **6GB** ,可以进行以下流程,测试CUDA解析加速效果 - -**1.覆盖安装支持cuda的torch和torchvision**(请根据cuda版本选择合适的index-url,具体可参考[torch官网](https://pytorch.org/get-started/locally/)) - -```bash -pip install --force-reinstall torch torchvision --index-url https://download.pytorch.org/whl/cu124 -``` - -**2.修改【用户目录】中配置文件magic-pdf.json中"device-mode"的值** - -```json -{ - "device-mode":"cuda" -} -``` - -**3.运行以下命令测试cuda加速效果** - -```bash -magic-pdf -p small_ocr.pdf -o ./output -``` - -> [!TIP] -> CUDA加速是否生效可以根据log中输出的各个阶段的耗时来简单判断,通常情况下,cuda加速后运行速度比cpu更快。 diff --git a/docs/how_to_download_models_en.md b/docs/how_to_download_models_en.md deleted file mode 100644 index 1852558a2a903ac908c1dd495f59d1b1b9ac3f86..0000000000000000000000000000000000000000 --- a/docs/how_to_download_models_en.md +++ /dev/null @@ -1,23 +0,0 @@ -Model downloads are divided into initial downloads and updates to the model directory. Please refer to the corresponding documentation for instructions on how to proceed. - - -# Initial download of model files - -### Download the Model from Hugging Face - -Use a Python Script to Download Model Files from Hugging Face -```bash -pip install huggingface_hub -wget https://github.com/opendatalab/MinerU/raw/master/scripts/download_models_hf.py -O download_models_hf.py -python download_models_hf.py -``` -The Python script will automatically download the model files and configure the model directory in the configuration file. - -The configuration file can be found in the user directory, with the filename `magic-pdf.json`. - - -# How to update models previously downloaded - -## 1. Models downloaded via Hugging Face or Model Scope - -If you previously downloaded models via Hugging Face or Model Scope, you can rerun the Python script used for the initial download. This will automatically update the model directory to the latest version. diff --git a/docs/how_to_download_models_zh_cn.md b/docs/how_to_download_models_zh_cn.md deleted file mode 100644 index ec254bfa452222ac9b9d4749557fdad1cce59c2f..0000000000000000000000000000000000000000 --- a/docs/how_to_download_models_zh_cn.md +++ /dev/null @@ -1,37 +0,0 @@ -模型下载分为首次下载和更新模型目录,请参考对应的文档内容进行操作 - -# 首次下载模型文件 - -模型文件可以从 Hugging Face 或 Model Scope 下载,由于网络原因,国内用户访问HF可能会失败,请使用 ModelScope。 - -
    - 方法一:从 Hugging Face 下载模型 -

    使用python脚本 从Hugging Face下载模型文件

    -
    pip install huggingface_hub
    -wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models_hf.py -O download_models_hf.py
    -python download_models_hf.py
    -

    python脚本会自动下载模型文件并配置好配置文件中的模型目录

    -
    - -## 方法二:从 ModelScope 下载模型 - -### 使用python脚本 从ModelScope下载模型文件 - -```bash -pip install modelscope -wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models.py -O download_models.py -python download_models.py -``` -python脚本会自动下载模型文件并配置好配置文件中的模型目录 - -配置文件可以在用户目录中找到,文件名为`magic-pdf.json` - -> [!TIP] -> windows的用户目录为 "C:\\Users\\用户名", linux用户目录为 "/home/用户名", macOS用户目录为 "/Users/用户名" - - -# 此前下载过模型,如何更新 - -## 1. 通过 Hugging Face 或 Model Scope 下载过模型 - -如此前通过 HuggingFace 或 Model Scope 下载过模型,可以重复执行此前的模型下载python脚本,将会自动将模型目录更新到最新版本。 diff --git a/magic-pdf.template.json b/magic-pdf.template.json deleted file mode 100644 index a80b8bf44c0e8e4bd7530a541dbfc637867ac971..0000000000000000000000000000000000000000 --- a/magic-pdf.template.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "bucket_info":{ - "bucket-name-1":["ak", "sk", "endpoint"], - "bucket-name-2":["ak", "sk", "endpoint"] - }, - "models-dir":"/tmp/models", - "layoutreader-model-dir":"/tmp/layoutreader", - "device-mode":"cpu", - "layout-config": { - "model": "doclayout_yolo" - }, - "formula-config": { - "mfd_model": "yolo_v8_mfd", - "mfr_model": "unimernet_small", - "enable": true - }, - "table-config": { - "model": "rapid_table", - "sub_model": "slanet_plus", - "enable": true, - "max_time": 400 - }, - "latex-delimiter-config": { - "display": { - "left": "$$", - "right": "$$" - }, - "inline": { - "left": "$", - "right": "$" - } - }, - "llm-aided-config": { - "formula_aided": { - "api_key": "your_api_key", - "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", - "model": "qwen2.5-7b-instruct", - "enable": false - }, - "text_aided": { - "api_key": "your_api_key", - "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", - "model": "qwen2.5-7b-instruct", - "enable": false - }, - "title_aided": { - "api_key": "your_api_key", - "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", - "model": "qwen2.5-32b-instruct", - "enable": false - } - }, - "config_version": "1.2.1" -} \ No newline at end of file diff --git a/magic_pdf/config/constants.py b/magic_pdf/config/constants.py deleted file mode 100644 index b18d630bbd1144816c4e0102c7f5ad53bc6d6194..0000000000000000000000000000000000000000 --- a/magic_pdf/config/constants.py +++ /dev/null @@ -1,60 +0,0 @@ -"""span维度自定义字段.""" -# span是否是跨页合并的 -CROSS_PAGE = 'cross_page' - -""" -block维度自定义字段 -""" -# block中lines是否被删除 -LINES_DELETED = 'lines_deleted' - -# table recognition max time default value -TABLE_MAX_TIME_VALUE = 400 - -# pp_table_result_max_length -TABLE_MAX_LEN = 480 - -# table master structure dict -TABLE_MASTER_DICT = 'table_master_structure_dict.txt' - -# table master dir -TABLE_MASTER_DIR = 'table_structure_tablemaster_infer/' - -# pp detect model dir -DETECT_MODEL_DIR = 'ch_PP-OCRv4_det_infer' - -# pp rec model dir -REC_MODEL_DIR = 'ch_PP-OCRv4_rec_infer' - -# pp rec char dict path -REC_CHAR_DICT = 'ppocr_keys_v1.txt' - -# pp rec copy rec directory -PP_REC_DIRECTORY = '.paddleocr/whl/rec/ch/ch_PP-OCRv4_rec_infer' - -# pp rec copy det directory -PP_DET_DIRECTORY = '.paddleocr/whl/det/ch/ch_PP-OCRv4_det_infer' - - -class MODEL_NAME: - # pp table structure algorithm - TABLE_MASTER = 'tablemaster' - # struct eqtable - STRUCT_EQTABLE = 'struct_eqtable' - - DocLayout_YOLO = 'doclayout_yolo' - - LAYOUTLMv3 = 'layoutlmv3' - - YOLO_V8_MFD = 'yolo_v8_mfd' - - UniMerNet_v2_Small = 'unimernet_small' - - RAPID_TABLE = 'rapid_table' - - YOLO_V11_LangDetect = 'yolo_v11n_langdetect' - - -PARSE_TYPE_TXT = 'txt' -PARSE_TYPE_OCR = 'ocr' - diff --git a/magic_pdf/config/drop_reason.py b/magic_pdf/config/drop_reason.py deleted file mode 100644 index d75d5676b81481c987f6c4d4948aaa82e9a4c86f..0000000000000000000000000000000000000000 --- a/magic_pdf/config/drop_reason.py +++ /dev/null @@ -1,35 +0,0 @@ -class DropReason: - TEXT_BLCOK_HOR_OVERLAP = 'text_block_horizontal_overlap' # 文字块有水平互相覆盖,导致无法准确定位文字顺序 - USEFUL_BLOCK_HOR_OVERLAP = ( - 'useful_block_horizontal_overlap' # 需保留的block水平覆盖 - ) - COMPLICATED_LAYOUT = 'complicated_layout' # 复杂的布局,暂时不支持 - TOO_MANY_LAYOUT_COLUMNS = 'too_many_layout_columns' # 目前不支持分栏超过2列的 - COLOR_BACKGROUND_TEXT_BOX = 'color_background_text_box' # 含有带色块的PDF,色块会改变阅读顺序,目前不支持带底色文字块的PDF。 - HIGH_COMPUTATIONAL_lOAD_BY_IMGS = ( - 'high_computational_load_by_imgs' # 含特殊图片,计算量太大,从而丢弃 - ) - HIGH_COMPUTATIONAL_lOAD_BY_SVGS = ( - 'high_computational_load_by_svgs' # 特殊的SVG图,计算量太大,从而丢弃 - ) - HIGH_COMPUTATIONAL_lOAD_BY_TOTAL_PAGES = 'high_computational_load_by_total_pages' # 计算量超过负荷,当前方法下计算量消耗过大 - MISS_DOC_LAYOUT_RESULT = 'missing doc_layout_result' # 版面分析失败 - Exception = '_exception' # 解析中发生异常 - ENCRYPTED = 'encrypted' # PDF是加密的 - EMPTY_PDF = 'total_page=0' # PDF页面总数为0 - NOT_IS_TEXT_PDF = 'not_is_text_pdf' # 不是文字版PDF,无法直接解析 - DENSE_SINGLE_LINE_BLOCK = 'dense_single_line_block' # 无法清晰的分段 - TITLE_DETECTION_FAILED = 'title_detection_failed' # 探测标题失败 - TITLE_LEVEL_FAILED = ( - 'title_level_failed' # 分析标题级别失败(例如一级、二级、三级标题) - ) - PARA_SPLIT_FAILED = 'para_split_failed' # 识别段落失败 - PARA_MERGE_FAILED = 'para_merge_failed' # 段落合并失败 - NOT_ALLOW_LANGUAGE = 'not_allow_language' # 不支持的语种 - SPECIAL_PDF = 'special_pdf' - PSEUDO_SINGLE_COLUMN = 'pseudo_single_column' # 无法精确判断文字分栏 - CAN_NOT_DETECT_PAGE_LAYOUT = 'can_not_detect_page_layout' # 无法分析页面的版面 - NEGATIVE_BBOX_AREA = 'negative_bbox_area' # 缩放导致 bbox 面积为负 - OVERLAP_BLOCKS_CAN_NOT_SEPARATION = ( - 'overlap_blocks_can_t_separation' # 无法分离重叠的block - ) diff --git a/magic_pdf/config/drop_tag.py b/magic_pdf/config/drop_tag.py deleted file mode 100644 index 51a2bc99378ddb1182a3c87de4e3623f00f93807..0000000000000000000000000000000000000000 --- a/magic_pdf/config/drop_tag.py +++ /dev/null @@ -1,19 +0,0 @@ - -COLOR_BG_HEADER_TXT_BLOCK = 'color_background_header_txt_block' -PAGE_NO = 'page-no' # 页码 -CONTENT_IN_FOOT_OR_HEADER = 'in-foot-header-area' # 页眉页脚内的文本 -VERTICAL_TEXT = 'vertical-text' # 垂直文本 -ROTATE_TEXT = 'rotate-text' # 旋转文本 -EMPTY_SIDE_BLOCK = 'empty-side-block' # 边缘上的空白没有任何内容的block -ON_IMAGE_TEXT = 'on-image-text' # 文本在图片上 -ON_TABLE_TEXT = 'on-table-text' # 文本在表格上 - - -class DropTag: - PAGE_NUMBER = 'page_no' - HEADER = 'header' - FOOTER = 'footer' - FOOTNOTE = 'footnote' - NOT_IN_LAYOUT = 'not_in_layout' - SPAN_OVERLAP = 'span_overlap' - BLOCK_OVERLAP = 'block_overlap' diff --git a/magic_pdf/config/enums.py b/magic_pdf/config/enums.py deleted file mode 100644 index 6f3e91a3227e6cb6678af0fc578a833a3d2439e3..0000000000000000000000000000000000000000 --- a/magic_pdf/config/enums.py +++ /dev/null @@ -1,7 +0,0 @@ - -import enum - - -class SupportedPdfParseMethod(enum.Enum): - OCR = 'ocr' - TXT = 'txt' diff --git a/magic_pdf/config/make_content_config.py b/magic_pdf/config/make_content_config.py deleted file mode 100644 index abcd74a4b860f163deb484ad33797c638034fb08..0000000000000000000000000000000000000000 --- a/magic_pdf/config/make_content_config.py +++ /dev/null @@ -1,11 +0,0 @@ -class MakeMode: - MM_MD = 'mm_markdown' - NLP_MD = 'nlp_markdown' - STANDARD_FORMAT = 'standard_format' - - -class DropMode: - WHOLE_PDF = 'whole_pdf' - SINGLE_PAGE = 'single_page' - NONE = 'none' - NONE_WITH_REASON = 'none_with_reason' diff --git a/magic_pdf/config/model_block_type.py b/magic_pdf/config/model_block_type.py deleted file mode 100644 index 4ad739ac51c08071626d8badd17f43b0eb90a66c..0000000000000000000000000000000000000000 --- a/magic_pdf/config/model_block_type.py +++ /dev/null @@ -1,10 +0,0 @@ -from enum import Enum - - -class ModelBlockTypeEnum(Enum): - TITLE = 0 - PLAIN_TEXT = 1 - ABANDON = 2 - ISOLATE_FORMULA = 8 - EMBEDDING = 13 - ISOLATED = 14 diff --git a/magic_pdf/config/ocr_content_type.py b/magic_pdf/config/ocr_content_type.py deleted file mode 100644 index 30d88cfdedbf28d3552a92e1549b839bea195f5b..0000000000000000000000000000000000000000 --- a/magic_pdf/config/ocr_content_type.py +++ /dev/null @@ -1,40 +0,0 @@ -class ContentType: - Image = 'image' - Table = 'table' - Text = 'text' - InlineEquation = 'inline_equation' - InterlineEquation = 'interline_equation' - - -class BlockType: - Image = 'image' - ImageBody = 'image_body' - ImageCaption = 'image_caption' - ImageFootnote = 'image_footnote' - Table = 'table' - TableBody = 'table_body' - TableCaption = 'table_caption' - TableFootnote = 'table_footnote' - Text = 'text' - Title = 'title' - InterlineEquation = 'interline_equation' - Footnote = 'footnote' - Discarded = 'discarded' - List = 'list' - Index = 'index' - - -class CategoryId: - Title = 0 - Text = 1 - Abandon = 2 - ImageBody = 3 - ImageCaption = 4 - TableBody = 5 - TableCaption = 6 - TableFootnote = 7 - InterlineEquation_Layout = 8 - InlineEquation = 13 - InterlineEquation_YOLO = 14 - OcrText = 15 - ImageFootnote = 101 diff --git a/magic_pdf/data/batch_build_dataset.py b/magic_pdf/data/batch_build_dataset.py deleted file mode 100644 index 52d33485f1c9a624b31e16029526f0ac653a165f..0000000000000000000000000000000000000000 --- a/magic_pdf/data/batch_build_dataset.py +++ /dev/null @@ -1,167 +0,0 @@ -import concurrent.futures - -import fitz - -from magic_pdf.data.dataset import PymuDocDataset -from magic_pdf.data.utils import fitz_doc_to_image # PyMuPDF - - -def partition_array_greedy(arr, k): - """Partition an array into k parts using a simple greedy approach. - - Parameters: - ----------- - arr : list - The input array of integers - k : int - Number of partitions to create - - Returns: - -------- - partitions : list of lists - The k partitions of the array - """ - # Handle edge cases - if k <= 0: - raise ValueError('k must be a positive integer') - if k > len(arr): - k = len(arr) # Adjust k if it's too large - if k == 1: - return [list(range(len(arr)))] - if k == len(arr): - return [[i] for i in range(len(arr))] - - # Sort the array in descending order - sorted_indices = sorted(range(len(arr)), key=lambda i: arr[i][1], reverse=True) - - # Initialize k empty partitions - partitions = [[] for _ in range(k)] - partition_sums = [0] * k - - # Assign each element to the partition with the smallest current sum - for idx in sorted_indices: - # Find the partition with the smallest sum - min_sum_idx = partition_sums.index(min(partition_sums)) - - # Add the element to this partition - partitions[min_sum_idx].append(idx) # Store the original index - partition_sums[min_sum_idx] += arr[idx][1] - - return partitions - - -def process_pdf_batch(pdf_jobs, idx): - """Process a batch of PDF pages using multiple threads. - - Parameters: - ----------- - pdf_jobs : list of tuples - List of (pdf_path, page_num) tuples - output_dir : str or None - Directory to save images to - num_threads : int - Number of threads to use - **kwargs : - Additional arguments for process_pdf_page - - Returns: - -------- - images : list - List of processed images - """ - images = [] - - for pdf_path, _ in pdf_jobs: - doc = fitz.open(pdf_path) - tmp = [] - for page_num in range(len(doc)): - page = doc[page_num] - tmp.append(fitz_doc_to_image(page)) - images.append(tmp) - return (idx, images) - - -def batch_build_dataset(pdf_paths, k, lang=None): - """Process multiple PDFs by partitioning them into k balanced parts and - processing each part in parallel. - - Parameters: - ----------- - pdf_paths : list - List of paths to PDF files - k : int - Number of partitions to create - output_dir : str or None - Directory to save images to - threads_per_worker : int - Number of threads to use per worker - **kwargs : - Additional arguments for process_pdf_page - - Returns: - -------- - all_images : list - List of all processed images - """ - - results = [] - for pdf_path in pdf_paths: - with open(pdf_path, 'rb') as f: - pdf_bytes = f.read() - dataset = PymuDocDataset(pdf_bytes, lang=lang) - results.append(dataset) - return results - - - # - # # Get page counts for each PDF - # pdf_info = [] - # total_pages = 0 - # - # for pdf_path in pdf_paths: - # try: - # doc = fitz.open(pdf_path) - # num_pages = len(doc) - # pdf_info.append((pdf_path, num_pages)) - # total_pages += num_pages - # doc.close() - # except Exception as e: - # print(f'Error opening {pdf_path}: {e}') - # - # # Partition the jobs based on page countEach job has 1 page - # partitions = partition_array_greedy(pdf_info, k) - # - # # Process each partition in parallel - # all_images_h = {} - # - # with concurrent.futures.ProcessPoolExecutor(max_workers=k) as executor: - # # Submit one task per partition - # futures = [] - # for sn, partition in enumerate(partitions): - # # Get the jobs for this partition - # partition_jobs = [pdf_info[idx] for idx in partition] - # - # # Submit the task - # future = executor.submit( - # process_pdf_batch, - # partition_jobs, - # sn - # ) - # futures.append(future) - # # Process results as they complete - # for i, future in enumerate(concurrent.futures.as_completed(futures)): - # try: - # idx, images = future.result() - # all_images_h[idx] = images - # except Exception as e: - # print(f'Error processing partition: {e}') - # results = [None] * len(pdf_paths) - # for i in range(len(partitions)): - # partition = partitions[i] - # for j in range(len(partition)): - # with open(pdf_info[partition[j]][0], 'rb') as f: - # pdf_bytes = f.read() - # dataset = PymuDocDataset(pdf_bytes, lang=lang) - # dataset.set_images(all_images_h[i][j]) - # results[partition[j]] = dataset - # return results \ No newline at end of file diff --git a/magic_pdf/data/data_reader_writer/__init__.py b/magic_pdf/data/data_reader_writer/__init__.py deleted file mode 100644 index f8f8234739e4cc756b56dbd4cb502893481a7a09..0000000000000000000000000000000000000000 --- a/magic_pdf/data/data_reader_writer/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from magic_pdf.data.data_reader_writer.filebase import \ - FileBasedDataReader # noqa: F401 -from magic_pdf.data.data_reader_writer.filebase import \ - FileBasedDataWriter # noqa: F401 -from magic_pdf.data.data_reader_writer.multi_bucket_s3 import \ - MultiBucketS3DataReader # noqa: F401 -from magic_pdf.data.data_reader_writer.multi_bucket_s3 import \ - MultiBucketS3DataWriter # noqa: F401 -from magic_pdf.data.data_reader_writer.s3 import S3DataReader # noqa: F401 -from magic_pdf.data.data_reader_writer.s3 import S3DataWriter # noqa: F401 -from magic_pdf.data.data_reader_writer.base import DataReader # noqa: F401 -from magic_pdf.data.data_reader_writer.base import DataWriter # noqa: F401 \ No newline at end of file diff --git a/magic_pdf/data/dataset.py b/magic_pdf/data/dataset.py deleted file mode 100644 index fb626e12cbfb7845fff1fed30dbbfdf650d507ea..0000000000000000000000000000000000000000 --- a/magic_pdf/data/dataset.py +++ /dev/null @@ -1,408 +0,0 @@ -import os -from abc import ABC, abstractmethod -from typing import Callable, Iterator - -import fitz -from loguru import logger - -from magic_pdf.config.enums import SupportedPdfParseMethod -from magic_pdf.data.schemas import PageInfo -from magic_pdf.data.utils import fitz_doc_to_image -from magic_pdf.filter import classify - - -class PageableData(ABC): - @abstractmethod - def get_image(self) -> dict: - """Transform data to image.""" - pass - - @abstractmethod - def get_doc(self) -> fitz.Page: - """Get the pymudoc page.""" - pass - - @abstractmethod - def get_page_info(self) -> PageInfo: - """Get the page info of the page. - - Returns: - PageInfo: the page info of this page - """ - pass - - @abstractmethod - def draw_rect(self, rect_coords, color, fill, fill_opacity, width, overlay): - """draw rectangle. - - Args: - rect_coords (list[float]): four elements array contain the top-left and bottom-right coordinates, [x0, y0, x1, y1] - color (list[float] | None): three element tuple which describe the RGB of the board line, None means no board line - fill (list[float] | None): fill the board with RGB, None means will not fill with color - fill_opacity (float): opacity of the fill, range from [0, 1] - width (float): the width of board - overlay (bool): fill the color in foreground or background. True means fill in background. - """ - pass - - @abstractmethod - def insert_text(self, coord, content, fontsize, color): - """insert text. - - Args: - coord (list[float]): four elements array contain the top-left and bottom-right coordinates, [x0, y0, x1, y1] - content (str): the text content - fontsize (int): font size of the text - color (list[float] | None): three element tuple which describe the RGB of the board line, None will use the default font color! - """ - pass - - -class Dataset(ABC): - @abstractmethod - def __len__(self) -> int: - """The length of the dataset.""" - pass - - @abstractmethod - def __iter__(self) -> Iterator[PageableData]: - """Yield the page data.""" - pass - - @abstractmethod - def supported_methods(self) -> list[SupportedPdfParseMethod]: - """The methods that this dataset support. - - Returns: - list[SupportedPdfParseMethod]: The supported methods, Valid methods are: OCR, TXT - """ - pass - - @abstractmethod - def data_bits(self) -> bytes: - """The bits used to create this dataset.""" - pass - - @abstractmethod - def get_page(self, page_id: int) -> PageableData: - """Get the page indexed by page_id. - - Args: - page_id (int): the index of the page - - Returns: - PageableData: the page doc object - """ - pass - - @abstractmethod - def dump_to_file(self, file_path: str): - """Dump the file. - - Args: - file_path (str): the file path - """ - pass - - @abstractmethod - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(self, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - pass - - @abstractmethod - def classify(self) -> SupportedPdfParseMethod: - """classify the dataset. - - Returns: - SupportedPdfParseMethod: _description_ - """ - pass - - @abstractmethod - def clone(self): - """clone this dataset.""" - pass - - -class PymuDocDataset(Dataset): - def __init__(self, bits: bytes, lang=None): - """Initialize the dataset, which wraps the pymudoc documents. - - Args: - bits (bytes): the bytes of the pdf - """ - self._raw_fitz = fitz.open('pdf', bits) - self._records = [Doc(v) for v in self._raw_fitz] - self._data_bits = bits - self._raw_data = bits - self._classify_result = None - - if lang == '': - self._lang = None - elif lang == 'auto': - from magic_pdf.model.sub_modules.language_detection.utils import \ - auto_detect_lang - self._lang = auto_detect_lang(self._data_bits) - logger.info(f'lang: {lang}, detect_lang: {self._lang}') - else: - self._lang = lang - logger.info(f'lang: {lang}') - - def __len__(self) -> int: - """The page number of the pdf.""" - return len(self._records) - - def __iter__(self) -> Iterator[PageableData]: - """Yield the page doc object.""" - return iter(self._records) - - def supported_methods(self) -> list[SupportedPdfParseMethod]: - """The method supported by this dataset. - - Returns: - list[SupportedPdfParseMethod]: the supported methods - """ - return [SupportedPdfParseMethod.OCR, SupportedPdfParseMethod.TXT] - - def data_bits(self) -> bytes: - """The pdf bits used to create this dataset.""" - return self._data_bits - - def get_page(self, page_id: int) -> PageableData: - """The page doc object. - - Args: - page_id (int): the page doc index - - Returns: - PageableData: the page doc object - """ - return self._records[page_id] - - def dump_to_file(self, file_path: str): - """Dump the file. - - Args: - file_path (str): the file path - """ - - dir_name = os.path.dirname(file_path) - if dir_name not in ('', '.', '..'): - os.makedirs(dir_name, exist_ok=True) - self._raw_fitz.save(file_path) - - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(dataset, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - if 'lang' in kwargs and self._lang is not None: - kwargs['lang'] = self._lang - return proc(self, *args, **kwargs) - - def classify(self) -> SupportedPdfParseMethod: - """classify the dataset. - - Returns: - SupportedPdfParseMethod: _description_ - """ - if self._classify_result is None: - self._classify_result = classify(self._data_bits) - return self._classify_result - - def clone(self): - """clone this dataset.""" - return PymuDocDataset(self._raw_data) - - def set_images(self, images): - for i in range(len(self._records)): - self._records[i].set_image(images[i]) - -class ImageDataset(Dataset): - def __init__(self, bits: bytes, lang=None): - """Initialize the dataset, which wraps the pymudoc documents. - - Args: - bits (bytes): the bytes of the photo which will be converted to pdf first. then converted to pymudoc. - """ - pdf_bytes = fitz.open(stream=bits).convert_to_pdf() - self._raw_fitz = fitz.open('pdf', pdf_bytes) - self._records = [Doc(v) for v in self._raw_fitz] - self._raw_data = bits - self._data_bits = pdf_bytes - - if lang == '': - self._lang = None - elif lang == 'auto': - from magic_pdf.model.sub_modules.language_detection.utils import \ - auto_detect_lang - self._lang = auto_detect_lang(self._data_bits) - logger.info(f'lang: {lang}, detect_lang: {self._lang}') - else: - self._lang = lang - logger.info(f'lang: {lang}') - - def __len__(self) -> int: - """The length of the dataset.""" - return len(self._records) - - def __iter__(self) -> Iterator[PageableData]: - """Yield the page object.""" - return iter(self._records) - - def supported_methods(self): - """The method supported by this dataset. - - Returns: - list[SupportedPdfParseMethod]: the supported methods - """ - return [SupportedPdfParseMethod.OCR] - - def data_bits(self) -> bytes: - """The pdf bits used to create this dataset.""" - return self._data_bits - - def get_page(self, page_id: int) -> PageableData: - """The page doc object. - - Args: - page_id (int): the page doc index - - Returns: - PageableData: the page doc object - """ - return self._records[page_id] - - def dump_to_file(self, file_path: str): - """Dump the file. - - Args: - file_path (str): the file path - """ - dir_name = os.path.dirname(file_path) - if dir_name not in ('', '.', '..'): - os.makedirs(dir_name, exist_ok=True) - self._raw_fitz.save(file_path) - - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(dataset, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - return proc(self, *args, **kwargs) - - def classify(self) -> SupportedPdfParseMethod: - """classify the dataset. - - Returns: - SupportedPdfParseMethod: _description_ - """ - return SupportedPdfParseMethod.OCR - - def clone(self): - """clone this dataset.""" - return ImageDataset(self._raw_data) - - def set_images(self, images): - for i in range(len(self._records)): - self._records[i].set_image(images[i]) - -class Doc(PageableData): - """Initialized with pymudoc object.""" - - def __init__(self, doc: fitz.Page): - self._doc = doc - self._img = None - - def get_image(self): - """Return the image info. - - Returns: - dict: { - img: np.ndarray, - width: int, - height: int - } - """ - if self._img is None: - self._img = fitz_doc_to_image(self._doc) - return self._img - - def set_image(self, img): - """ - Args: - img (np.ndarray): the image - """ - if self._img is None: - self._img = img - - def get_doc(self) -> fitz.Page: - """Get the pymudoc object. - - Returns: - fitz.Page: the pymudoc object - """ - return self._doc - - def get_page_info(self) -> PageInfo: - """Get the page info of the page. - - Returns: - PageInfo: the page info of this page - """ - page_w = self._doc.rect.width - page_h = self._doc.rect.height - return PageInfo(w=page_w, h=page_h) - - def __getattr__(self, name): - if hasattr(self._doc, name): - return getattr(self._doc, name) - - def draw_rect(self, rect_coords, color, fill, fill_opacity, width, overlay): - """draw rectangle. - - Args: - rect_coords (list[float]): four elements array contain the top-left and bottom-right coordinates, [x0, y0, x1, y1] - color (list[float] | None): three element tuple which describe the RGB of the board line, None means no board line - fill (list[float] | None): fill the board with RGB, None means will not fill with color - fill_opacity (float): opacity of the fill, range from [0, 1] - width (float): the width of board - overlay (bool): fill the color in foreground or background. True means fill in background. - """ - self._doc.draw_rect( - rect_coords, - color=color, - fill=fill, - fill_opacity=fill_opacity, - width=width, - overlay=overlay, - ) - - def insert_text(self, coord, content, fontsize, color): - """insert text. - - Args: - coord (list[float]): four elements array contain the top-left and bottom-right coordinates, [x0, y0, x1, y1] - content (str): the text content - fontsize (int): font size of the text - color (list[float] | None): three element tuple which describe the RGB of the board line, None will use the default font color! - """ - self._doc.insert_text(coord, content, fontsize=fontsize, color=color) \ No newline at end of file diff --git a/magic_pdf/data/io/__init__.py b/magic_pdf/data/io/__init__.py deleted file mode 100644 index badf1df07551df611dc955710743f26bf5f60595..0000000000000000000000000000000000000000 --- a/magic_pdf/data/io/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ - -from magic_pdf.data.io.base import IOReader, IOWriter # noqa: F401 -from magic_pdf.data.io.http import HttpReader, HttpWriter # noqa: F401 -from magic_pdf.data.io.s3 import S3Reader, S3Writer # noqa: F401 - -__all__ = ['IOReader', 'IOWriter', 'HttpReader', 'HttpWriter', 'S3Reader', 'S3Writer'] \ No newline at end of file diff --git a/magic_pdf/data/read_api.py b/magic_pdf/data/read_api.py deleted file mode 100644 index 9e52af6d8976910975b987529871b0acbae239bb..0000000000000000000000000000000000000000 --- a/magic_pdf/data/read_api.py +++ /dev/null @@ -1,142 +0,0 @@ -import json -import os -import tempfile -import shutil -from pathlib import Path - -from magic_pdf.config.exceptions import EmptyData, InvalidParams -from magic_pdf.data.data_reader_writer import (FileBasedDataReader, - MultiBucketS3DataReader) -from magic_pdf.data.dataset import ImageDataset, PymuDocDataset -from magic_pdf.utils.office_to_pdf import convert_file_to_pdf, ConvertToPdfError - -def read_jsonl( - s3_path_or_local: str, s3_client: MultiBucketS3DataReader | None = None -) -> list[PymuDocDataset]: - """Read the jsonl file and return the list of PymuDocDataset. - - Args: - s3_path_or_local (str): local file or s3 path - s3_client (MultiBucketS3DataReader | None, optional): s3 client that support multiple bucket. Defaults to None. - - Raises: - InvalidParams: if s3_path_or_local is s3 path but s3_client is not provided. - EmptyData: if no pdf file location is provided in some line of jsonl file. - InvalidParams: if the file location is s3 path but s3_client is not provided - - Returns: - list[PymuDocDataset]: each line in the jsonl file will be converted to a PymuDocDataset - """ - bits_arr = [] - if s3_path_or_local.startswith('s3://'): - if s3_client is None: - raise InvalidParams('s3_client is required when s3_path is provided') - jsonl_bits = s3_client.read(s3_path_or_local) - else: - jsonl_bits = FileBasedDataReader('').read(s3_path_or_local) - jsonl_d = [ - json.loads(line) for line in jsonl_bits.decode().split('\n') if line.strip() - ] - for d in jsonl_d: - pdf_path = d.get('file_location', '') or d.get('path', '') - if len(pdf_path) == 0: - raise EmptyData('pdf file location is empty') - if pdf_path.startswith('s3://'): - if s3_client is None: - raise InvalidParams('s3_client is required when s3_path is provided') - bits_arr.append(s3_client.read(pdf_path)) - else: - bits_arr.append(FileBasedDataReader('').read(pdf_path)) - return [PymuDocDataset(bits) for bits in bits_arr] - - -def read_local_pdfs(path: str) -> list[PymuDocDataset]: - """Read pdf from path or directory. - - Args: - path (str): pdf file path or directory that contains pdf files - - Returns: - list[PymuDocDataset]: each pdf file will converted to a PymuDocDataset - """ - if os.path.isdir(path): - reader = FileBasedDataReader() - ret = [] - for root, _, files in os.walk(path): - for file in files: - suffix = file.split('.') - if suffix[-1] == 'pdf': - ret.append( PymuDocDataset(reader.read(os.path.join(root, file)))) - return ret - else: - reader = FileBasedDataReader() - bits = reader.read(path) - return [PymuDocDataset(bits)] - -def read_local_office(path: str) -> list[PymuDocDataset]: - """Read ms-office file (ppt, pptx, doc, docx) from path or directory. - - Args: - path (str): ms-office file or directory that contains ms-office files - - Returns: - list[PymuDocDataset]: each ms-office file will converted to a PymuDocDataset - - Raises: - ConvertToPdfError: Failed to convert ms-office file to pdf via libreoffice - FileNotFoundError: File not Found - Exception: Unknown Exception raised - """ - suffixes = ['.ppt', '.pptx', '.doc', '.docx'] - fns = [] - ret = [] - if os.path.isdir(path): - for root, _, files in os.walk(path): - for file in files: - suffix = Path(file).suffix - if suffix in suffixes: - fns.append((os.path.join(root, file))) - else: - fns.append(path) - - reader = FileBasedDataReader() - temp_dir = tempfile.mkdtemp() - for fn in fns: - try: - convert_file_to_pdf(fn, temp_dir) - except ConvertToPdfError as e: - raise e - except FileNotFoundError as e: - raise e - except Exception as e: - raise e - fn_path = Path(fn) - pdf_fn = f"{temp_dir}/{fn_path.stem}.pdf" - ret.append(PymuDocDataset(reader.read(pdf_fn))) - shutil.rmtree(temp_dir) - return ret - -def read_local_images(path: str, suffixes: list[str]=['.png', '.jpg', '.jpeg']) -> list[ImageDataset]: - """Read images from path or directory. - - Args: - path (str): image file path or directory that contains image files - suffixes (list[str]): the suffixes of the image files used to filter the files. Example: ['.jpg', '.png'] - - Returns: - list[ImageDataset]: each image file will converted to a ImageDataset - """ - if os.path.isdir(path): - imgs_bits = [] - s_suffixes = set(suffixes) - reader = FileBasedDataReader() - for root, _, files in os.walk(path): - for file in files: - suffix = Path(file).suffix - if suffix in s_suffixes: - imgs_bits.append(reader.read(os.path.join(root, file))) - return [ImageDataset(bits) for bits in imgs_bits] - else: - reader = FileBasedDataReader() - bits = reader.read(path) - return [ImageDataset(bits)] diff --git a/magic_pdf/data/utils.py b/magic_pdf/data/utils.py deleted file mode 100644 index 849fa780939ddba531029500b158280658af8ea3..0000000000000000000000000000000000000000 --- a/magic_pdf/data/utils.py +++ /dev/null @@ -1,166 +0,0 @@ - -import multiprocessing as mp -import threading -from concurrent.futures import (ProcessPoolExecutor, ThreadPoolExecutor, - as_completed) - -import fitz -import numpy as np -from loguru import logger - - - -def fitz_doc_to_image(page, dpi=200) -> dict: - """Convert fitz.Document to image, Then convert the image to numpy array. - - Args: - page (_type_): pymudoc page - dpi (int, optional): reset the dpi of dpi. Defaults to 200. - - Returns: - dict: {'img': numpy array, 'width': width, 'height': height } - """ - mat = fitz.Matrix(dpi / 72, dpi / 72) - pm = page.get_pixmap(matrix=mat, alpha=False) - - # If the width or height exceeds 4500 after scaling, do not scale further. - if pm.width > 4500 or pm.height > 4500: - pm = page.get_pixmap(matrix=fitz.Matrix(1, 1), alpha=False) - - # Convert pixmap samples directly to numpy array - img = np.frombuffer(pm.samples, dtype=np.uint8).reshape(pm.height, pm.width, 3) - - img_dict = {'img': img, 'width': pm.width, 'height': pm.height} - - return img_dict - -def load_images_from_pdf(pdf_bytes: bytes, dpi=200, start_page_id=0, end_page_id=None) -> list: - images = [] - with fitz.open('pdf', pdf_bytes) as doc: - pdf_page_num = doc.page_count - end_page_id = ( - end_page_id - if end_page_id is not None and end_page_id >= 0 - else pdf_page_num - 1 - ) - if end_page_id > pdf_page_num - 1: - logger.warning('end_page_id is out of range, use images length') - end_page_id = pdf_page_num - 1 - - for index in range(0, doc.page_count): - if start_page_id <= index <= end_page_id: - page = doc[index] - mat = fitz.Matrix(dpi / 72, dpi / 72) - pm = page.get_pixmap(matrix=mat, alpha=False) - - # If the width or height exceeds 4500 after scaling, do not scale further. - if pm.width > 4500 or pm.height > 4500: - pm = page.get_pixmap(matrix=fitz.Matrix(1, 1), alpha=False) - - # Convert pixmap samples directly to numpy array - img = np.frombuffer(pm.samples, dtype=np.uint8).reshape(pm.height, pm.width, 3) - - img_dict = {'img': img, 'width': pm.width, 'height': pm.height} - else: - img_dict = {'img': [], 'width': 0, 'height': 0} - - images.append(img_dict) - return images - - -def convert_page(bytes_page): - pdfs = fitz.open('pdf', bytes_page) - page = pdfs[0] - return fitz_doc_to_image(page) - -def parallel_process_pdf_safe(pages, num_workers=None, **kwargs): - """Process PDF pages in parallel with serialization-safe approach.""" - if num_workers is None: - num_workers = mp.cpu_count() - - - # Process the extracted page data in parallel - with ProcessPoolExecutor(max_workers=num_workers) as executor: - # Process the page data - results = list( - executor.map(convert_page, pages) - ) - - return results - - -def threaded_process_pdf(pdf_path, num_threads=4, **kwargs): - """Process all pages of a PDF using multiple threads. - - Parameters: - ----------- - pdf_path : str - Path to the PDF file - num_threads : int - Number of threads to use - **kwargs : - Additional arguments for fitz_doc_to_image - - Returns: - -------- - images : list - List of processed images, in page order - """ - # Open the PDF - doc = fitz.open(pdf_path) - num_pages = len(doc) - - # Create a list to store results in the correct order - results = [None] * num_pages - - # Create a thread pool - with ThreadPoolExecutor(max_workers=num_threads) as executor: - # Submit all tasks - futures = {} - for page_num in range(num_pages): - page = doc[page_num] - future = executor.submit(fitz_doc_to_image, page, **kwargs) - futures[future] = page_num - # Process results as they complete with progress bar - for future in as_completed(futures): - page_num = futures[future] - try: - results[page_num] = future.result() - except Exception as e: - print(f'Error processing page {page_num}: {e}') - results[page_num] = None - - # Close the document - doc.close() - -if __name__ == '__main__': - pdf = fitz.open('/tmp/[MS-DOC].pdf') - - - pdf_page = [fitz.open() for i in range(pdf.page_count)] - [pdf_page[i].insert_pdf(pdf, from_page=i, to_page=i) for i in range(pdf.page_count)] - - pdf_page = [v.tobytes() for v in pdf_page] - results = parallel_process_pdf_safe(pdf_page, num_workers=16) - - # threaded_process_pdf('/tmp/[MS-DOC].pdf', num_threads=16) - - """ benchmark results of multi-threaded processing (fitz page to image) - total page nums: 578 - thread nums, time cost - 1 7.351 sec - 2 6.334 sec - 4 5.968 sec - 8 6.728 sec - 16 8.085 sec - """ - - """ benchmark results of multi-processor processing (fitz page to image) - total page nums: 578 - processor nums, time cost - 1 17.170 sec - 2 10.170 sec - 4 7.841 sec - 8 7.900 sec - 16 7.984 sec - """ diff --git a/magic_pdf/filter/__init__.py b/magic_pdf/filter/__init__.py deleted file mode 100644 index 280156358b1417c1526ade41302a7f21b09863e0..0000000000000000000000000000000000000000 --- a/magic_pdf/filter/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ - -from magic_pdf.config.drop_reason import DropReason -from magic_pdf.config.enums import SupportedPdfParseMethod -from magic_pdf.filter.pdf_classify_by_type import classify as do_classify -from magic_pdf.filter.pdf_meta_scan import pdf_meta_scan - - -def classify(pdf_bytes: bytes) -> SupportedPdfParseMethod: - """根据pdf的元数据,判断是文本pdf,还是ocr pdf.""" - pdf_meta = pdf_meta_scan(pdf_bytes) - if pdf_meta.get('_need_drop', False): # 如果返回了需要丢弃的标志,则抛出异常 - raise Exception(f"pdf meta_scan need_drop,reason is {pdf_meta['_drop_reason']}") - else: - is_encrypted = pdf_meta['is_encrypted'] - is_needs_password = pdf_meta['is_needs_password'] - if is_encrypted or is_needs_password: # 加密的,需要密码的,没有页面的,都不处理 - raise Exception(f'pdf meta_scan need_drop,reason is {DropReason.ENCRYPTED}') - else: - is_text_pdf, results = do_classify( - pdf_meta['total_page'], - pdf_meta['page_width_pts'], - pdf_meta['page_height_pts'], - pdf_meta['image_info_per_page'], - pdf_meta['text_len_per_page'], - pdf_meta['imgs_per_page'], - # pdf_meta['text_layout_per_page'], - pdf_meta['invalid_chars'], - ) - if is_text_pdf: - return SupportedPdfParseMethod.TXT - else: - return SupportedPdfParseMethod.OCR diff --git a/magic_pdf/filter/pdf_classify_by_type.py b/magic_pdf/filter/pdf_classify_by_type.py deleted file mode 100644 index 50665737287c2d1798924c3aa30980ce280a3c7d..0000000000000000000000000000000000000000 --- a/magic_pdf/filter/pdf_classify_by_type.py +++ /dev/null @@ -1,395 +0,0 @@ -""" -根据利用meta_scan得到的结果,对pdf是否为文字版进行分类。 -定义标准: -一、什么pdf会是文字pdf,只要满足以下任意一条 - 1. 随机抽取N页,如果有任何一页文字数目大于100 - 2. 只要存在一个页面,图片的数量为0 -二、什么是扫描版pdf,只要满足以下任意一条 - 1. ~~80%页面上的最大图大小一样并且面积超过页面面积0.6~~ - 2. 大部分页面上文字的长度都是相等的。 - -""" -import json -import sys -from collections import Counter - -import click -import numpy as np -from loguru import logger - -from magic_pdf.libs.commons import mymax, get_top_percent_list -from magic_pdf.filter.pdf_meta_scan import scan_max_page, junk_limit_min - -TEXT_LEN_THRESHOLD = 100 -AVG_TEXT_LEN_THRESHOLD = 100 -TEXT_LEN_SAMPLE_RATIO = 0.1 # 抽取0.1的页面进行文字长度统计 - - -# 一个拼接图片的方案,将某些特殊扫描版本的拆图拼成一张整图 -def merge_images(image_list, page_width, page_height, max_offset=5, max_gap=2): - # 先通过set去除所有bbox重叠的图片数据 - image_list_result = [] - for page_images in image_list: - page_result = [] - dedup = set() - for img in page_images: - x0, y0, x1, y1, img_bojid = img - if (x0, y0, x1, y1) in dedup: # 这里面会出现一些重复的bbox,无需重复出现,需要去掉 - continue - else: - dedup.add((x0, y0, x1, y1)) - page_result.append([x0, y0, x1, y1, img_bojid]) - image_list_result.append(page_result) - - # 接下来,将同一页可拼接的图片进行合并 - merged_images = [] - for page_images in image_list_result: - if not page_images: - continue - - # 先将同一页的图片从上到下,从左到右进行排序 - page_images.sort(key=lambda img: (img[1], img[0])) - - merged = [page_images[0]] - - for img in page_images[1:]: - x0, y0, x1, y1, imgid = img - - last_img = merged[-1] - last_x0, last_y0, last_x1, last_y1, last_imgid = last_img - - # 单张图片宽或者高覆盖页面宽高的9成以上是拼图的一个前置条件 - full_width = abs(x1 - x0) >= page_width * 0.9 - full_height = abs(y1 - y0) >= page_height * 0.9 - - # 如果宽达标,检测是否能竖着拼 - if full_width: - # 竖着拼需要满足两个前提,左右边界各偏移不能超过 max_offset,第一张图的下边界和第二张图的上边界偏移不能超过 max_gap - close1 = (last_x0 - max_offset) <= x0 <= (last_x0 + max_offset) and (last_x1 - max_offset) <= x1 <= ( - last_x1 + max_offset) and (last_y1 - max_gap) <= y0 <= (last_y1 + max_gap) - - # 如果高达标,检测是否可以横着拼 - if full_height: - # 横着拼需要满足两个前提,上下边界各偏移不能超过 max_offset,第一张图的右边界和第二张图的左边界偏移不能超过 max_gap - close2 = (last_y0 - max_offset) <= y0 <= (last_y0 + max_offset) and (last_y1 - max_offset) <= y1 <= ( - last_y1 + max_offset) and (last_x1 - max_gap) <= x0 <= (last_x1 + max_gap) - - # Check if the image can be merged with the last image - if (full_width and close1) or (full_height and close2): - # Merge the image with the last image - merged[-1] = [min(x0, last_x0), min(y0, last_y0), - max(x1, last_x1), max(y1, last_y1), imgid] - else: - # Add the image as a new image - merged.append(img) - - merged_images.append(merged) - - return merged_images - - -def classify_by_area(total_page: int, page_width, page_height, img_sz_list, text_len_list: list): - """ - 80%页面上的最大图大小一样并且面积超过页面面积0.6则返回False,否则返回True - :param pdf_path: - :param total_page: - :param page_width: - :param page_height: - :param img_sz_list: - :return: - """ - # # 只要有一页没有图片,那么就是文字pdf。但是同时还需要满足一个条件就是这个页面上同时不能有文字。发现过一些扫描版pdf,上面有一些空白页面,既没有图片也没有文字。 - # if any([len(img_sz) == 0 for img_sz in img_sz_list]): # 含有不含图片的页面 - # # 现在找到这些页面的index - # empty_page_index = [i for i, img_sz in enumerate(img_sz_list) if len(img_sz) == 0] - # # 然后检查这些页面上是否有文字 - # text_len_at_page_idx = [text_len for i, text_len in enumerate(text_len_list) if i in empty_page_index and text_len > 0] - # if len(text_len_at_page_idx) > TEXT_LEN_THRESHOLD: # 没有图片,但是有文字,说明可能是个文字版,如果没有文字则无法判断,留给下一步,现在要求这页文字量超过一定阈值 - # return True - - # 通过objid去掉重复出现10次以上的图片,这些图片是隐藏的透明图层,其特点是id都一样 - # 先对每个id出现的次数做个统计 - objid_cnt = Counter([objid for page_img_sz in img_sz_list for _, _, _, _, objid in page_img_sz]) - # 再去掉出现次数大于10的 - if total_page >= scan_max_page: # 新的meta_scan只扫描前 scan_max_page 页,页数大于 scan_max_page 当total_page为 scan_max_page - total_page = scan_max_page - - repeat_threshold = 2 # 把bad_image的阈值设为2 - # repeat_threshold = min(2, total_page) # 当total_page为1时,repeat_threshold为1,会产生误判导致所有img变成bad_img - bad_image_objid = set([objid for objid, cnt in objid_cnt.items() if cnt >= repeat_threshold]) - # bad_image_page_idx = [i for i, page_img_sz in enumerate(img_sz_list) if any([objid in bad_image_objid for _, _, _, _, objid in page_img_sz])] - # text_len_at_bad_image_page_idx = [text_len for i, text_len in enumerate(text_len_list) if i in bad_image_page_idx and text_len > 0] - - # 特殊情况,一个文字版pdf,每页覆盖一个超大的透明图片,超大的定义是图片占整页面积的90%以上 - # fake_image_ids = [objid for objid in bad_image_objid if - # any([abs((x1 - x0) * (y1 - y0) / page_width * page_height) > 0.9 for images in img_sz_list for - # x0, y0, x1, y1, _ in images])] # 原来的代码,any里面恒为true了,原因??? - # fake_image_ids = [objid for objid in bad_image_objid for images in img_sz_list for x0, y0, x1, y1, img_id in images - # if img_id == objid and abs((x1 - x0) * (y1 - y0)) / (page_width * page_height) > 0.9] - - # if len(fake_image_ids) > 0 and any([l > TEXT_LEN_THRESHOLD for l in text_len_at_bad_image_page_idx]): # 这些透明图片所在的页面上有文字大于阈值 - # return True - - img_sz_list = [[img_sz for img_sz in page_img_sz if img_sz[-1] not in bad_image_objid] for page_img_sz in - img_sz_list] # 过滤掉重复出现的图片 - - # 有的扫描版会把一页图片拆成很多张,需要先把图拼起来再计算 - img_sz_list = merge_images(img_sz_list, page_width, page_height) - - # 计算每个页面上最大的图的面积,然后计算这个面积占页面面积的比例 - max_image_area_per_page = [mymax([(x1 - x0) * (y1 - y0) for x0, y0, x1, y1, _ in page_img_sz]) for page_img_sz in - img_sz_list] - page_area = page_width * page_height - max_image_area_per_page = [area / page_area for area in max_image_area_per_page] - max_image_area_per_page = [area for area in max_image_area_per_page if area > 0.5] - - if len(max_image_area_per_page) >= 0.5 * total_page: # 阈值从0.8改到0.5,适配3页里面有两页和两页里面有一页的情况 - # 这里条件成立的前提是把反复出现的图片去掉了。这些图片是隐藏的透明图层,其特点是id都一样 - return False - else: - return True - - -def classify_by_text_len(text_len_list: list, total_page: int): - """ - 随机抽取10%的页面,如果少于5个页面,那么就取全部页面。 - 查看页面上的文字长度,如果有任何一个页面的文字长度大于TEXT_LEN_THRESHOLD,那么就是文字pdf - :param total_page: - :param text_len_list: - :return: - """ - select_page_cnt = int(total_page * TEXT_LEN_SAMPLE_RATIO) # 选取10%的页面 - if select_page_cnt < 5: - select_page_cnt = total_page - - # # 排除头尾各10页 - # if total_page > 20: # 如果总页数大于20 - # page_range = list(range(10, total_page - 10)) # 从第11页到倒数第11页 - # else: - # page_range = list(range(total_page)) # 否则选择所有页面 - # page_num = np.random.choice(page_range, min(select_page_cnt, len(page_range)), replace=False) - # 排除前后10页对只有21,22页的pdf很尴尬,如果选出来的中间那一两页恰好没字容易误判,有了avg_words规则,这个规则可以忽略 - page_num = np.random.choice(total_page, select_page_cnt, replace=False) - text_len_lst = [text_len_list[i] for i in page_num] - is_text_pdf = any([text_len > TEXT_LEN_THRESHOLD for text_len in text_len_lst]) - return is_text_pdf - - -def classify_by_avg_words(text_len_list: list): - """ - 补充规则,如果平均每页字数少于 AVG_TEXT_LEN_THRESHOLD,就不是文字pdf - 主要是各种图集 - :param text_len_list: - :return: - """ - sum_words = sum(text_len_list) - count_of_numbers = len(text_len_list) - if count_of_numbers == 0: - is_text_pdf = False - else: - avg_words = round(sum_words / count_of_numbers) - if avg_words > AVG_TEXT_LEN_THRESHOLD: - is_text_pdf = True - else: - is_text_pdf = False - - return is_text_pdf - - -def classify_by_img_num(img_sz_list: list, img_num_list: list): - """ - 补充规则,有一种扫描版本的PDF,每一页都会放所有的扫描页进去,在 metascan 时会被去重, - 这种pdf的 metasca 扫描结果的特点是 img_sz_list 内全是空元素,img_num_list中每一页的数量都很大且相同 - :param img_sz_list: - :param img_num_list: - :return: - """ - # 计算img_sz_list中非空元素的个数 - count_img_sz_list_not_none = sum(1 for item in img_sz_list if item) - # 获取前80%的元素 - top_eighty_percent = get_top_percent_list(img_num_list, 0.8) - # img_sz_list中非空元素的个数小于1,前80%的元素都相等,且最大值大于等于junk_limit_min - if count_img_sz_list_not_none <= 1 and len(set(top_eighty_percent)) == 1 and max(img_num_list) >= junk_limit_min: - - #拿max和min的值,用来判断list内的值是否全都相等 - # min_imgs = min(img_num_list) - # max_imgs = max(img_num_list) - # - # if count_img_sz_list_not_none == 0 and max_imgs == min_imgs and max_imgs >= junk_limit_min: - return False # 如果满足这个条件,一定不是文字版pdf - else: - return True # 不满足这三个条件,可能是文字版pdf,通过其他规则判断 - - -def classify_by_text_layout(text_layout_per_page: list): - """ - 判断文本布局是否以竖排为主。 - - Args: - text_layout_per_page (list): 文本布局列表,列表中的每个元素表示一页的文本布局, - 值为'vertical'表示竖排,值为'horizontal'表示横排。 - - Returns: - bool: 若文本布局以竖排为主,则返回False;否则返回True。 - """ - # 统计text_layout_per_page中竖排的个数 - count_vertical = sum(1 for item in text_layout_per_page if item == 'vertical') - # 统计text_layout_per_page中横排的个数 - count_horizontal = sum(1 for item in text_layout_per_page if item == 'horizontal') - # 计算text_layout_per_page中竖排的占比 - known_layout_cnt = count_vertical + count_horizontal - if known_layout_cnt != 0: - ratio = count_vertical / known_layout_cnt - if ratio >= 0.5: # 阈值设为0.5,适配3页里面有2页和两页里有一页的情况 - return False # 文本布局以竖排为主,认为不是文字版pdf - else: - return True # 文本布局以横排为主,认为是文字版pdf - else: - return False # 文本布局未知,默认认为不是文字版pdf - - -def classify_by_img_narrow_strips(page_width, page_height, img_sz_list): - """ - 判断一页是否由细长条组成,有两个条件: - 1. 图片的宽或高达到页面宽或高的90%,且长边需要是窄边长度的数倍以上 - 2. 整个页面所有的图片有80%以上满足条件1 - - Args: - page_width (float): 页面宽度 - page_height (float): 页面高度 - img_sz_list (list): 图片尺寸列表,每个元素为一个元组,表示图片的矩形区域和尺寸,形如(x0, y0, x1, y1, size),其中(x0, y0)为矩形区域的左上角坐标,(x1, y1)为矩形区域的右下角坐标,size为图片的尺寸 - - Returns: - bool: 如果满足条件的页面的比例小于0.5,返回True,否则返回False - """ - - def is_narrow_strip(img): - x0, y0, x1, y1, _ = img - width, height = x1 - x0, y1 - y0 - return any([ - # 图片宽度大于等于页面宽度的90%,且宽度大于等于高度4倍 - width >= page_width * 0.9 and width >= height * 4, - # 图片高度大于等于页面高度的90%,且高度大于等于宽度4倍 - height >= page_height * 0.9 and height >= width * 4, - ]) - - # 初始化满足条件的页面数量 - narrow_strip_pages_count = 0 - - # 遍历所有页面 - for page_img_list in img_sz_list: - # 忽略空页面 - if not page_img_list: - continue - - # 计算页面中的图片总数 - total_images = len(page_img_list) - - # 计算页面中细长条图片的数量 - narrow_strip_images_count = 0 - for img in page_img_list: - if is_narrow_strip(img): - narrow_strip_images_count += 1 - # 如果细长条图片的数量少于5,跳过 - if narrow_strip_images_count < 5: - continue - else: - # 如果细长条图片的比例大于或等于0.8,增加满足条件的页面数量 - if narrow_strip_images_count / total_images >= 0.8: - narrow_strip_pages_count += 1 - - # 计算满足条件的页面的比例 - narrow_strip_pages_ratio = narrow_strip_pages_count / len(img_sz_list) - - return narrow_strip_pages_ratio < 0.5 - - -def classify(total_page: int, page_width, page_height, img_sz_list: list, text_len_list: list, img_num_list: list, - # text_layout_list: list, - invalid_chars: bool): - """ - 这里的图片和页面长度单位是pts - :param total_page: - :param text_len_list: - :param page_width: - :param page_height: - :param img_sz_list: - :param pdf_path: - :return: - """ - results = { - 'by_image_area': classify_by_area(total_page, page_width, page_height, img_sz_list, text_len_list), - 'by_text_len': classify_by_text_len(text_len_list, total_page), - 'by_avg_words': classify_by_avg_words(text_len_list), - 'by_img_num': classify_by_img_num(img_sz_list, img_num_list), - # 'by_text_layout': classify_by_text_layout(text_layout_list), - 'by_img_narrow_strips': classify_by_img_narrow_strips(page_width, page_height, img_sz_list), - 'by_invalid_chars': invalid_chars, - } - - if all(results.values()): - return True, results - elif not any(results.values()): - return False, results - else: - logger.warning( - f"OCR needed based on classification result, by_image_area: {results['by_image_area']}," - f" by_text: {results['by_text_len']}, by_avg_words: {results['by_avg_words']}, by_img_num: {results['by_img_num']}," - # f" by_text_layout: {results['by_text_layout']}," - f" by_img_narrow_strips: {results['by_img_narrow_strips']}," - f" by_invalid_chars: {results['by_invalid_chars']}", - file=sys.stderr) # 利用这种情况可以快速找出来哪些pdf比较特殊,针对性修正分类算法 - return False, results - - -@click.command() -@click.option("--json-file", type=str, help="pdf信息") -def main(json_file): - if json_file is None: - print("json_file is None", file=sys.stderr) - exit(0) - try: - with open(json_file, "r") as f: - for l in f: - if l.strip() == "": - continue - o = json.loads(l) - total_page = o["total_page"] - page_width = o["page_width_pts"] - page_height = o["page_height_pts"] - img_sz_list = o["image_info_per_page"] - text_len_list = o['text_len_per_page'] - text_layout_list = o['text_layout_per_page'] - pdf_path = o['pdf_path'] - is_encrypted = o['is_encrypted'] - is_needs_password = o['is_needs_password'] - if is_encrypted or total_page == 0 or is_needs_password: # 加密的,需要密码的,没有页面的,都不处理 - continue - tag = classify(total_page, page_width, page_height, img_sz_list, text_len_list, text_layout_list) - o['is_text_pdf'] = tag - print(json.dumps(o, ensure_ascii=False)) - except Exception as e: - print("ERROR: ", e, file=sys.stderr) - - -if __name__ == "__main__": - main() - # false = False - # true = True - # null = None - # o = {"pdf_path":"s3://llm-raw-snew/llm-raw-the-eye/raw/World%20Tracker%20Library/worldtracker.org/media/library/Science/Computer%20Science/Shreiner%20-%20OpenGL%20Programming%20Guide%206e%20%5BThe%20Redbook%5D%20%28AW%2C%202008%29.pdf","is_needs_password":false,"is_encrypted":false,"total_page":978,"page_width_pts":368,"page_height_pts":513,"image_info_per_page":[[[0,0,368,513,10037]],[[0,0,368,513,4]],[[0,0,368,513,7]],[[0,0,368,513,10]],[[0,0,368,513,13]],[[0,0,368,513,16]],[[0,0,368,513,19]],[[0,0,368,513,22]],[[0,0,368,513,25]],[[0,0,368,513,28]],[[0,0,368,513,31]],[[0,0,368,513,34]],[[0,0,368,513,37]],[[0,0,368,513,40]],[[0,0,368,513,43]],[[0,0,368,513,46]],[[0,0,368,513,49]],[[0,0,368,513,52]],[[0,0,368,513,55]],[[0,0,368,513,58]],[[0,0,368,513,61]],[[0,0,368,513,64]],[[0,0,368,513,67]],[[0,0,368,513,70]],[[0,0,368,513,73]],[[0,0,368,516,76]],[[0,0,368,516,79]],[[0,0,368,513,82]],[[0,0,368,513,85]],[[0,0,368,513,88]],[[0,0,368,513,91]],[[0,0,368,513,94]],[[0,0,368,513,97]],[[0,0,368,513,100]],[[0,0,368,513,103]],[[0,0,368,513,106]],[[0,0,368,513,109]],[[0,0,368,513,112]],[[0,0,368,513,115]],[[0,0,368,513,118]],[[0,0,368,513,121]],[[0,0,368,513,124]],[[0,0,368,513,127]],[[0,0,368,513,130]],[[0,0,368,513,133]],[[0,0,368,513,136]],[[0,0,368,513,139]],[[0,0,368,513,142]],[[0,0,368,513,145]],[[0,0,368,513,148]],[[0,0,368,513,151]],[[0,0,368,513,154]],[[0,0,368,513,157]],[[0,0,368,513,160]],[[0,0,368,513,163]],[[0,0,368,513,166]],[[0,0,368,513,169]],[[0,0,368,513,172]],[[0,0,368,513,175]],[[0,0,368,513,178]],[[0,0,368,513,181]],[[0,0,368,513,184]],[[0,0,368,513,187]],[[0,0,368,513,190]],[[0,0,368,513,193]],[[0,0,368,513,196]],[[0,0,368,513,199]],[[0,0,368,513,202]],[[0,0,368,513,205]],[[0,0,368,513,208]],[[0,0,368,513,211]],[[0,0,368,513,214]],[[0,0,368,513,217]],[[0,0,368,513,220]],[[0,0,368,513,223]],[[0,0,368,513,226]],[[0,0,368,513,229]],[[0,0,368,513,232]],[[0,0,368,513,235]],[[0,0,368,513,238]],[[0,0,368,513,241]],[[0,0,368,513,244]],[[0,0,368,513,247]],[[0,0,368,513,250]],[[0,0,368,513,253]],[[0,0,368,513,256]],[[0,0,368,513,259]],[[0,0,368,513,262]],[[0,0,368,513,265]],[[0,0,368,513,268]],[[0,0,368,513,271]],[[0,0,368,513,274]],[[0,0,368,513,277]],[[0,0,368,513,280]],[[0,0,368,513,283]],[[0,0,368,513,286]],[[0,0,368,513,289]],[[0,0,368,513,292]],[[0,0,368,513,295]],[[0,0,368,513,298]],[[0,0,368,513,301]],[[0,0,368,513,304]],[[0,0,368,513,307]],[[0,0,368,513,310]],[[0,0,368,513,313]],[[0,0,368,513,316]],[[0,0,368,513,319]],[[0,0,368,513,322]],[[0,0,368,513,325]],[[0,0,368,513,328]],[[0,0,368,513,331]],[[0,0,368,513,334]],[[0,0,368,513,337]],[[0,0,368,513,340]],[[0,0,368,513,343]],[[0,0,368,513,346]],[[0,0,368,513,349]],[[0,0,368,513,352]],[[0,0,368,513,355]],[[0,0,368,513,358]],[[0,0,368,513,361]],[[0,0,368,513,364]],[[0,0,368,513,367]],[[0,0,368,513,370]],[[0,0,368,513,373]],[[0,0,368,513,376]],[[0,0,368,513,379]],[[0,0,368,513,382]],[[0,0,368,513,385]],[[0,0,368,513,388]],[[0,0,368,513,391]],[[0,0,368,513,394]],[[0,0,368,513,397]],[[0,0,368,513,400]],[[0,0,368,513,403]],[[0,0,368,513,406]],[[0,0,368,513,409]],[[0,0,368,513,412]],[[0,0,368,513,415]],[[0,0,368,513,418]],[[0,0,368,513,421]],[[0,0,368,513,424]],[[0,0,368,513,427]],[[0,0,368,513,430]],[[0,0,368,513,433]],[[0,0,368,513,436]],[[0,0,368,513,439]],[[0,0,368,513,442]],[[0,0,368,513,445]],[[0,0,368,513,448]],[[0,0,368,513,451]],[[0,0,368,513,454]],[[0,0,368,513,457]],[[0,0,368,513,460]],[[0,0,368,513,463]],[[0,0,368,513,466]],[[0,0,368,513,469]],[[0,0,368,513,472]],[[0,0,368,513,475]],[[0,0,368,513,478]],[[0,0,368,513,481]],[[0,0,368,513,484]],[[0,0,368,513,487]],[[0,0,368,513,490]],[[0,0,368,513,493]],[[0,0,368,513,496]],[[0,0,368,513,499]],[[0,0,368,513,502]],[[0,0,368,513,505]],[[0,0,368,513,508]],[[0,0,368,513,511]],[[0,0,368,513,514]],[[0,0,368,513,517]],[[0,0,368,513,520]],[[0,0,368,513,523]],[[0,0,368,513,526]],[[0,0,368,513,529]],[[0,0,368,513,532]],[[0,0,368,513,535]],[[0,0,368,513,538]],[[0,0,368,513,541]],[[0,0,368,513,544]],[[0,0,368,513,547]],[[0,0,368,513,550]],[[0,0,368,513,553]],[[0,0,368,513,556]],[[0,0,368,513,559]],[[0,0,368,513,562]],[[0,0,368,513,565]],[[0,0,368,513,568]],[[0,0,368,513,571]],[[0,0,368,513,574]],[[0,0,368,513,577]],[[0,0,368,513,580]],[[0,0,368,513,583]],[[0,0,368,513,586]],[[0,0,368,513,589]],[[0,0,368,513,592]],[[0,0,368,513,595]],[[0,0,368,513,598]],[[0,0,368,513,601]],[[0,0,368,513,604]],[[0,0,368,513,607]],[[0,0,368,513,610]],[[0,0,368,513,613]],[[0,0,368,513,616]],[[0,0,368,513,619]],[[0,0,368,513,622]],[[0,0,368,513,625]],[[0,0,368,513,628]],[[0,0,368,513,631]],[[0,0,368,513,634]],[[0,0,368,513,637]],[[0,0,368,513,640]],[[0,0,368,513,643]],[[0,0,368,513,646]],[[0,0,368,513,649]],[[0,0,368,513,652]],[[0,0,368,513,655]],[[0,0,368,513,658]],[[0,0,368,513,661]],[[0,0,368,513,664]],[[0,0,368,513,667]],[[0,0,368,513,670]],[[0,0,368,513,673]],[[0,0,368,513,676]],[[0,0,368,513,679]],[[0,0,368,513,682]],[[0,0,368,513,685]],[[0,0,368,513,688]],[[0,0,368,513,691]],[[0,0,368,513,694]],[[0,0,368,513,697]],[[0,0,368,513,700]],[[0,0,368,513,703]],[[0,0,368,513,706]],[[0,0,368,513,709]],[[0,0,368,513,712]],[[0,0,368,513,715]],[[0,0,368,513,718]],[[0,0,368,513,721]],[[0,0,368,513,724]],[[0,0,368,513,727]],[[0,0,368,513,730]],[[0,0,368,513,733]],[[0,0,368,513,736]],[[0,0,368,513,739]],[[0,0,368,513,742]],[[0,0,368,513,745]],[[0,0,368,513,748]],[[0,0,368,513,751]],[[0,0,368,513,754]],[[0,0,368,513,757]],[[0,0,368,513,760]],[[0,0,368,513,763]],[[0,0,368,513,766]],[[0,0,368,513,769]],[[0,0,368,513,772]],[[0,0,368,513,775]],[[0,0,368,513,778]],[[0,0,368,513,781]],[[0,0,368,513,784]],[[0,0,368,513,787]],[[0,0,368,513,790]],[[0,0,368,513,793]],[[0,0,368,513,796]],[[0,0,368,513,799]],[[0,0,368,513,802]],[[0,0,368,513,805]],[[0,0,368,513,808]],[[0,0,368,513,811]],[[0,0,368,513,814]],[[0,0,368,513,817]],[[0,0,368,513,820]],[[0,0,368,513,823]],[[0,0,368,513,826]],[[0,0,368,513,829]],[[0,0,368,513,832]],[[0,0,368,513,835]],[[0,0,368,513,838]],[[0,0,368,513,841]],[[0,0,368,513,844]],[[0,0,368,513,847]],[[0,0,368,513,850]],[[0,0,368,513,853]],[[0,0,368,513,856]],[[0,0,368,513,859]],[[0,0,368,513,862]],[[0,0,368,513,865]],[[0,0,368,513,868]],[[0,0,368,513,871]],[[0,0,368,513,874]],[[0,0,368,513,877]],[[0,0,368,513,880]],[[0,0,368,513,883]],[[0,0,368,513,886]],[[0,0,368,513,889]],[[0,0,368,513,892]],[[0,0,368,513,895]],[[0,0,368,513,898]],[[0,0,368,513,901]],[[0,0,368,513,904]],[[0,0,368,513,907]],[[0,0,368,513,910]],[[0,0,368,513,913]],[[0,0,368,513,916]],[[0,0,368,513,919]],[[0,0,368,513,922]],[[0,0,368,513,925]],[[0,0,368,513,928]],[[0,0,368,513,931]],[[0,0,368,513,934]],[[0,0,368,513,937]],[[0,0,368,513,940]],[[0,0,368,513,943]],[[0,0,368,513,946]],[[0,0,368,513,949]],[[0,0,368,513,952]],[[0,0,368,513,955]],[[0,0,368,513,958]],[[0,0,368,513,961]],[[0,0,368,513,964]],[[0,0,368,513,967]],[[0,0,368,513,970]],[[0,0,368,513,973]],[[0,0,368,513,976]],[[0,0,368,513,979]],[[0,0,368,513,982]],[[0,0,368,513,985]],[[0,0,368,513,988]],[[0,0,368,513,991]],[[0,0,368,513,994]],[[0,0,368,513,997]],[[0,0,368,513,1000]],[[0,0,368,513,1003]],[[0,0,368,513,1006]],[[0,0,368,513,1009]],[[0,0,368,513,1012]],[[0,0,368,513,1015]],[[0,0,368,513,1018]],[[0,0,368,513,2797]],[[0,0,368,513,2798]],[[0,0,368,513,2799]],[[0,0,368,513,2800]],[[0,0,368,513,2801]],[[0,0,368,513,2802]],[[0,0,368,513,2803]],[[0,0,368,513,2804]],[[0,0,368,513,2805]],[[0,0,368,513,2806]],[[0,0,368,513,2807]],[[0,0,368,513,2808]],[[0,0,368,513,2809]],[[0,0,368,513,2810]],[[0,0,368,513,2811]],[[0,0,368,513,2812]],[[0,0,368,513,2813]],[[0,0,368,513,2814]],[[0,0,368,513,2815]],[[0,0,368,513,2816]],[[0,0,368,513,2817]],[[0,0,368,513,2818]],[[0,0,368,513,2819]],[[0,0,368,513,2820]],[[0,0,368,513,2821]],[[0,0,368,513,2822]],[[0,0,368,513,2823]],[[0,0,368,513,2824]],[[0,0,368,513,2825]],[[0,0,368,513,2826]],[[0,0,368,513,2827]],[[0,0,368,513,2828]],[[0,0,368,513,2829]],[[0,0,368,513,2830]],[[0,0,368,513,2831]],[[0,0,368,513,2832]],[[0,0,368,513,2833]],[[0,0,368,513,2834]],[[0,0,368,513,2835]],[[0,0,368,513,2836]],[[0,0,368,513,2837]],[[0,0,368,513,2838]],[[0,0,368,513,2839]],[[0,0,368,513,2840]],[[0,0,368,513,2841]],[[0,0,368,513,2842]],[[0,0,368,513,2843]],[[0,0,368,513,2844]],[[0,0,368,513,2845]],[[0,0,368,513,2846]],[[0,0,368,513,2847]],[[0,0,368,513,2848]],[[0,0,368,513,2849]],[[0,0,368,513,2850]],[[0,0,368,513,2851]],[[0,0,368,513,2852]],[[0,0,368,513,2853]],[[0,0,368,513,2854]],[[0,0,368,513,2855]],[[0,0,368,513,2856]],[[0,0,368,513,2857]],[[0,0,368,513,2858]],[[0,0,368,513,2859]],[[0,0,368,513,2860]],[[0,0,368,513,2861]],[[0,0,368,513,2862]],[[0,0,368,513,2863]],[[0,0,368,513,2864]],[[0,0,368,513,2797]],[[0,0,368,513,2798]],[[0,0,368,513,2799]],[[0,0,368,513,2800]],[[0,0,368,513,2801]],[[0,0,368,513,2802]],[[0,0,368,513,2803]],[[0,0,368,513,2804]],[[0,0,368,513,2805]],[[0,0,368,513,2806]],[[0,0,368,513,2807]],[[0,0,368,513,2808]],[[0,0,368,513,2809]],[[0,0,368,513,2810]],[[0,0,368,513,2811]],[[0,0,368,513,2812]],[[0,0,368,513,2813]],[[0,0,368,513,2814]],[[0,0,368,513,2815]],[[0,0,368,513,2816]],[[0,0,368,513,2817]],[[0,0,368,513,2818]],[[0,0,368,513,2819]],[[0,0,368,513,2820]],[[0,0,368,513,2821]],[[0,0,368,513,2822]],[[0,0,368,513,2823]],[[0,0,368,513,2824]],[[0,0,368,513,2825]],[[0,0,368,513,2826]],[[0,0,368,513,2827]],[[0,0,368,513,2828]],[[0,0,368,513,2829]],[[0,0,368,513,2830]],[[0,0,368,513,2831]],[[0,0,368,513,2832]],[[0,0,368,513,2833]],[[0,0,368,513,2834]],[[0,0,368,513,2835]],[[0,0,368,513,2836]],[[0,0,368,513,2837]],[[0,0,368,513,2838]],[[0,0,368,513,2839]],[[0,0,368,513,2840]],[[0,0,368,513,2841]],[[0,0,368,513,2842]],[[0,0,368,513,2843]],[[0,0,368,513,2844]],[[0,0,368,513,2845]],[[0,0,368,513,2846]],[[0,0,368,513,2847]],[[0,0,368,513,2848]],[[0,0,368,513,2849]],[[0,0,368,513,2850]],[[0,0,368,513,2851]],[[0,0,368,513,2852]],[[0,0,368,513,2853]],[[0,0,368,513,2854]],[[0,0,368,513,2855]],[[0,0,368,513,2856]],[[0,0,368,513,2857]],[[0,0,368,513,2858]],[[0,0,368,513,2859]],[[0,0,368,513,2860]],[[0,0,368,513,2861]],[[0,0,368,513,2862]],[[0,0,368,513,2863]],[[0,0,368,513,2864]],[[0,0,368,513,1293]],[[0,0,368,513,1296]],[[0,0,368,513,1299]],[[0,0,368,513,1302]],[[0,0,368,513,1305]],[[0,0,368,513,1308]],[[0,0,368,513,1311]],[[0,0,368,513,1314]],[[0,0,368,513,1317]],[[0,0,368,513,1320]],[[0,0,368,513,1323]],[[0,0,368,513,1326]],[[0,0,368,513,1329]],[[0,0,368,513,1332]],[[0,0,368,513,1335]],[[0,0,368,513,1338]],[[0,0,368,513,1341]],[[0,0,368,513,1344]],[[0,0,368,513,1347]],[[0,0,368,513,1350]],[[0,0,368,513,1353]],[[0,0,368,513,1356]],[[0,0,368,513,1359]],[[0,0,368,513,1362]],[[0,0,368,513,1365]],[[0,0,368,513,1368]],[[0,0,368,513,1371]],[[0,0,368,513,1374]],[[0,0,368,513,1377]],[[0,0,368,513,1380]],[[0,0,368,513,1383]],[[0,0,368,513,1386]],[[0,0,368,513,1389]],[[0,0,368,513,1392]],[[0,0,368,513,1395]],[[0,0,368,513,1398]],[[0,0,368,513,1401]],[[0,0,368,513,1404]],[[0,0,368,513,1407]],[[0,0,368,513,1410]],[[0,0,368,513,1413]],[[0,0,368,513,1416]],[[0,0,368,513,1419]],[[0,0,368,513,1422]],[[0,0,368,513,1425]],[[0,0,368,513,1428]],[[0,0,368,513,1431]],[[0,0,368,513,1434]],[[0,0,368,513,1437]],[[0,0,368,513,1440]],[[0,0,368,513,1443]],[[0,0,368,513,1446]],[[0,0,368,513,1449]],[[0,0,368,513,1452]],[[0,0,368,513,1455]],[[0,0,368,513,1458]],[[0,0,368,513,1461]],[[0,0,368,513,1464]],[[0,0,368,513,1467]],[[0,0,368,513,1470]],[[0,0,368,513,1473]],[[0,0,368,513,1476]],[[0,0,368,513,1479]],[[0,0,368,513,1482]],[[0,0,368,513,1485]],[[0,0,368,513,1488]],[[0,0,368,513,1491]],[[0,0,368,513,1494]],[[0,0,368,513,1497]],[[0,0,368,513,1500]],[[0,0,368,513,1503]],[[0,0,368,513,1506]],[[0,0,368,513,1509]],[[0,0,368,513,1512]],[[0,0,368,513,1515]],[[0,0,368,513,1518]],[[0,0,368,513,1521]],[[0,0,368,513,1524]],[[0,0,368,513,1527]],[[0,0,368,513,1530]],[[0,0,368,513,1533]],[[0,0,368,513,1536]],[[0,0,368,513,1539]],[[0,0,368,513,1542]],[[0,0,368,513,1545]],[[0,0,368,513,1548]],[[0,0,368,513,1551]],[[0,0,368,513,1554]],[[0,0,368,513,1557]],[[0,0,368,513,1560]],[[0,0,368,513,1563]],[[0,0,368,513,1566]],[[0,0,368,513,1569]],[[0,0,368,513,1572]],[[0,0,368,513,1575]],[[0,0,368,513,1578]],[[0,0,368,513,1581]],[[0,0,368,513,1584]],[[0,0,368,513,1587]],[[0,0,368,513,1590]],[[0,0,368,513,1593]],[[0,0,368,513,1596]],[[0,0,368,513,1599]],[[0,0,368,513,1602]],[[0,0,368,513,1605]],[[0,0,368,513,1608]],[[0,0,368,513,1611]],[[0,0,368,513,1614]],[[0,0,368,513,1617]],[[0,0,368,513,1620]],[[0,0,368,513,1623]],[[0,0,368,513,1626]],[[0,0,368,513,1629]],[[0,0,368,513,1632]],[[0,0,368,513,1635]],[[0,0,368,513,1638]],[[0,0,368,513,1641]],[[0,0,368,513,1644]],[[0,0,368,513,1647]],[[0,0,368,513,1650]],[[0,0,368,513,1653]],[[0,0,368,513,1656]],[[0,0,368,513,1659]],[[0,0,368,513,1662]],[[0,0,368,513,1665]],[[0,0,368,513,1668]],[[0,0,368,513,1671]],[[0,0,368,513,1674]],[[0,0,368,513,1677]],[[0,0,368,513,1680]],[[0,0,368,513,1683]],[[0,0,368,513,1686]],[[0,0,368,513,1689]],[[0,0,368,513,1692]],[[0,0,368,513,1695]],[[0,0,368,513,1698]],[[0,0,368,513,1701]],[[0,0,368,513,1704]],[[0,0,368,513,1707]],[[0,0,368,513,1710]],[[0,0,368,513,1713]],[[0,0,368,513,1716]],[[0,0,368,513,1719]],[[0,0,368,513,1722]],[[0,0,368,513,1725]],[[0,0,368,513,1728]],[[0,0,368,513,1731]],[[0,0,368,513,1734]],[[0,0,368,513,1737]],[[0,0,368,513,1740]],[[0,0,368,513,1743]],[[0,0,368,513,1746]],[[0,0,368,513,1749]],[[0,0,368,513,1752]],[[0,0,368,513,1755]],[[0,0,368,513,1758]],[[0,0,368,513,1761]],[[0,0,368,513,1764]],[[0,0,368,513,1767]],[[0,0,368,513,1770]],[[0,0,368,513,1773]],[[0,0,368,513,1776]],[[0,0,368,513,1779]],[[0,0,368,513,1782]],[[0,0,368,513,1785]],[[0,0,368,513,1788]],[[0,0,368,513,1791]],[[0,0,368,513,1794]],[[0,0,368,513,1797]],[[0,0,368,513,1800]],[[0,0,368,513,1803]],[[0,0,368,513,1806]],[[0,0,368,513,1809]],[[0,0,368,513,1812]],[[0,0,368,513,1815]],[[0,0,368,513,1818]],[[0,0,368,513,1821]],[[0,0,368,513,1824]],[[0,0,368,513,1827]],[[0,0,368,513,1830]],[[0,0,368,513,1833]],[[0,0,368,513,1836]],[[0,0,368,513,1839]],[[0,0,368,513,1842]],[[0,0,368,513,1845]],[[0,0,368,513,1848]],[[0,0,368,513,1851]],[[0,0,368,513,1854]],[[0,0,368,513,1857]],[[0,0,368,513,1860]],[[0,0,368,513,1863]],[[0,0,368,513,1866]],[[0,0,368,513,1869]],[[0,0,368,513,1872]],[[0,0,368,513,1875]],[[0,0,368,513,1878]],[[0,0,368,513,1881]],[[0,0,368,513,1884]],[[0,0,368,513,1887]],[[0,0,368,513,1890]],[[0,0,368,513,1893]],[[0,0,368,513,1896]],[[0,0,368,513,1899]],[[0,0,368,513,1902]],[[0,0,368,513,1905]],[[0,0,368,513,1908]],[[0,0,368,513,1911]],[[0,0,368,513,1914]],[[0,0,368,513,1917]],[[0,0,368,513,1920]],[[0,0,368,513,1923]],[[0,0,368,513,1926]],[[0,0,368,513,1929]],[[0,0,368,513,1932]],[[0,0,368,513,1935]],[[0,0,368,513,1938]],[[0,0,368,513,1941]],[[0,0,368,513,1944]],[[0,0,368,513,1947]],[[0,0,368,513,1950]],[[0,0,368,513,1953]],[[0,0,368,513,1956]],[[0,0,368,513,1959]],[[0,0,368,513,1962]],[[0,0,368,513,1965]],[[0,0,368,513,1968]],[[0,0,368,513,1971]],[[0,0,368,513,1974]],[[0,0,368,513,1977]],[[0,0,368,513,1980]],[[0,0,368,513,1983]],[[0,0,368,513,1986]],[[0,0,368,513,1989]],[[0,0,368,513,1992]],[[0,0,368,513,1995]],[[0,0,368,513,1998]],[[0,0,368,513,2001]],[[0,0,368,513,2004]],[[0,0,368,513,2007]],[[0,0,368,513,2010]],[[0,0,368,513,2013]],[[0,0,368,513,2016]],[[0,0,368,513,2019]],[[0,0,368,513,2022]],[[0,0,368,513,2025]],[[0,0,368,513,2028]],[[0,0,368,513,2031]],[[0,0,368,513,2034]],[[0,0,368,513,2037]],[[0,0,368,513,2040]],[[0,0,368,513,2043]],[[0,0,368,513,2046]],[[0,0,368,513,2049]],[[0,0,368,513,2052]],[[0,0,368,513,2055]],[[0,0,368,513,2058]],[[0,0,368,513,2061]],[[0,0,368,513,2064]],[[0,0,368,513,2067]],[[0,0,368,513,2070]],[[0,0,368,513,2073]],[[0,0,368,513,2076]],[[0,0,368,513,2079]],[[0,0,368,513,2082]],[[0,0,368,513,2085]],[[0,0,368,513,2088]],[[0,0,368,513,2091]],[[0,0,368,513,2094]],[[0,0,368,513,2097]],[[0,0,368,513,2100]],[[0,0,368,513,2103]],[[0,0,368,513,2106]],[[0,0,368,513,2109]],[[0,0,368,513,2112]],[[0,0,368,513,2115]],[[0,0,368,513,2118]],[[0,0,368,513,2121]],[[0,0,368,513,2124]],[[0,0,368,513,2127]],[[0,0,368,513,2130]],[[0,0,368,513,2133]],[[0,0,368,513,2136]],[[0,0,368,513,2139]],[[0,0,368,513,2142]],[[0,0,368,513,2145]],[[0,0,368,513,2148]],[[0,0,368,513,2151]],[[0,0,368,513,2154]],[[0,0,368,513,2157]],[[0,0,368,513,2160]],[[0,0,368,513,2163]],[[0,0,368,513,2166]],[[0,0,368,513,2169]],[[0,0,368,513,2172]],[[0,0,368,513,2175]],[[0,0,368,513,2178]],[[0,0,368,513,2181]],[[0,0,368,513,2184]],[[0,0,368,513,2187]],[[0,0,368,513,2190]],[[0,0,368,513,2193]],[[0,0,368,513,2196]],[[0,0,368,513,2199]],[[0,0,368,513,2202]],[[0,0,368,513,2205]],[[0,0,368,513,2208]],[[0,0,368,513,2211]],[[0,0,368,513,2214]],[[0,0,368,513,2217]],[[0,0,368,513,2220]],[[0,0,368,513,2223]],[[0,0,368,513,2226]],[[0,0,368,513,2229]],[[0,0,368,513,2232]],[[0,0,368,513,2235]],[[0,0,368,513,2238]],[[0,0,368,513,2241]],[[0,0,368,513,2244]],[[0,0,368,513,2247]],[[0,0,368,513,2250]],[[0,0,368,513,2253]],[[0,0,368,513,2256]],[[0,0,368,513,2259]],[[0,0,368,513,2262]],[[0,0,368,513,2265]],[[0,0,368,513,2268]],[[0,0,368,513,2271]],[[0,0,368,513,2274]],[[0,0,368,513,2277]],[[0,0,368,513,2280]],[[0,0,368,513,2283]],[[0,0,368,513,2286]],[[0,0,368,513,2289]],[[0,0,368,513,2292]],[[0,0,368,513,2295]],[[0,0,368,513,2298]],[[0,0,368,513,2301]],[[0,0,368,513,2304]],[[0,0,368,513,2307]],[[0,0,368,513,2310]],[[0,0,368,513,2313]],[[0,0,368,513,2316]],[[0,0,368,513,2319]],[[0,0,368,513,2322]],[[0,0,368,513,2325]],[[0,0,368,513,2328]],[[0,0,368,513,2331]],[[0,0,368,513,2334]],[[0,0,368,513,2337]],[[0,0,368,513,2340]],[[0,0,368,513,2343]],[[0,0,368,513,2346]],[[0,0,368,513,2349]],[[0,0,368,513,2352]],[[0,0,368,513,2355]],[[0,0,368,513,2358]],[[0,0,368,513,2361]],[[0,0,368,513,2364]],[[0,0,368,513,2367]],[[0,0,368,513,2370]],[[0,0,368,513,2373]],[[0,0,368,513,2376]],[[0,0,368,513,2379]],[[0,0,368,513,2382]],[[0,0,368,513,2385]],[[0,0,368,513,2388]],[[0,0,368,513,2391]],[[0,0,368,513,2394]],[[0,0,368,513,2397]],[[0,0,368,513,2400]],[[0,0,368,513,2403]],[[0,0,368,513,2406]],[[0,0,368,513,2409]],[[0,0,368,513,2412]],[[0,0,368,513,2415]],[[0,0,368,513,2418]],[[0,0,368,513,2421]],[[0,0,368,513,2424]],[[0,0,368,513,2427]],[[0,0,368,513,2430]],[[0,0,368,513,2433]],[[0,0,368,513,2436]],[[0,0,368,513,2439]],[[0,0,368,513,2442]],[[0,0,368,513,2445]],[[0,0,368,513,2448]],[[0,0,368,513,2451]],[[0,0,368,513,2454]],[[0,0,368,513,2457]],[[0,0,368,513,2460]],[[0,0,368,513,2463]],[[0,0,368,513,2466]],[[0,0,368,513,2469]],[[0,0,368,513,2472]],[[0,0,368,513,2475]],[[0,0,368,513,2478]],[[0,0,368,513,2481]],[[0,0,368,513,2484]],[[0,0,368,513,2487]],[[0,0,368,513,2490]],[[0,0,368,513,2493]],[[0,0,368,513,2496]],[[0,0,368,513,2499]],[[0,0,368,513,2502]],[[0,0,368,513,2505]],[[0,0,368,513,2508]],[[0,0,368,513,2511]],[[0,0,368,513,2514]],[[0,0,368,513,2517]],[[0,0,368,513,2520]],[[0,0,368,513,2523]],[[0,0,368,513,2526]],[[0,0,368,513,2529]],[[0,0,368,513,2532]],[[0,0,368,513,2535]],[[0,0,368,513,2538]],[[0,0,368,513,2541]],[[0,0,368,513,2544]],[[0,0,368,513,2547]],[[0,0,368,513,2550]],[[0,0,368,513,2553]],[[0,0,368,513,2556]],[[0,0,368,513,2559]],[[0,0,368,513,2562]],[[0,0,368,513,2565]],[[0,0,368,513,2568]],[[0,0,368,513,2571]],[[0,0,368,513,2574]],[[0,0,368,513,2577]],[[0,0,368,513,2580]],[[0,0,368,513,2583]],[[0,0,368,513,2586]],[[0,0,368,513,2589]],[[0,0,368,513,2592]],[[0,0,368,513,2595]],[[0,0,368,513,2598]],[[0,0,368,513,2601]],[[0,0,368,513,2604]],[[0,0,368,513,2607]],[[0,0,368,513,2610]],[[0,0,368,513,2613]],[[0,0,368,513,2616]],[[0,0,368,513,2619]],[[0,0,368,513,2622]],[[0,0,368,513,2625]],[[0,0,368,513,2628]],[[0,0,368,513,2631]],[[0,0,368,513,2634]],[[0,0,368,513,2637]],[[0,0,368,513,2640]],[[0,0,368,513,2643]],[[0,0,368,513,2646]],[[0,0,368,513,2649]],[[0,0,368,513,2652]],[[0,0,368,513,2655]],[[0,0,368,513,2658]],[[0,0,368,513,2661]],[[0,0,368,513,2664]],[[0,0,368,513,2667]],[[0,0,368,513,2670]],[[0,0,368,513,2673]],[[0,0,368,513,2676]],[[0,0,368,513,2679]],[[0,0,368,513,2682]],[[0,0,368,513,2685]],[[0,0,368,513,2688]],[[0,0,368,513,2691]],[[0,0,368,513,2694]],[[0,0,368,513,2697]],[[0,0,368,513,2700]],[[0,0,368,513,2703]],[[0,0,368,513,2706]],[[0,0,368,513,2709]],[[0,0,368,513,2712]],[[0,0,368,513,2715]],[[0,0,368,513,2718]],[[0,0,368,513,2721]],[[0,0,368,513,2724]],[[0,0,368,513,2727]],[[0,0,368,513,2730]],[[0,0,368,513,2733]],[[0,0,368,513,2736]],[[0,0,368,513,2739]],[[0,0,368,513,2742]],[[0,0,368,513,2745]],[[0,0,368,513,2748]],[[0,0,368,513,2751]],[[0,0,368,513,2754]],[[0,0,368,513,2757]],[[0,0,368,513,2760]],[[0,0,368,513,2763]],[[0,0,368,513,2766]],[[0,0,368,513,2769]],[[0,0,368,513,2772]],[[0,0,368,513,2775]],[[0,0,368,513,2778]],[[0,0,368,513,2781]],[[0,0,368,513,2784]],[[0,0,368,513,2787]],[[0,0,368,513,2790]],[[0,0,368,513,2793]],[[0,0,368,513,2796]]],"text_len_per_page":[53,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54],"metadata":{"format":"PDF 1.6","title":"","author":"","subject":"","keywords":"","creator":"Adobe Acrobat 7.0","producer":"Adobe Acrobat 7.0 Image Conversion Plug-in","creationDate":"D:20080404141457+01'00'","modDate":"D:20080404144821+01'00'","trapped":"","encryption":null}} - # o = json.loads(json.dumps(o)) - # total_page = o["total_page"] - # page_width = o["page_width_pts"] - # page_height = o["page_height_pts"] - # img_sz_list = o["image_info_per_page"] - # text_len_list = o['text_len_per_page'] - # pdf_path = o['pdf_path'] - # is_encrypted = o['is_encrypted'] - # is_needs_password = o['is_needs_password'] - # if is_encrypted or total_page == 0 or is_needs_password: # 加密的,需要密码的,没有页面的,都不处理 - # print("加密的") - # exit(0) - # tag = classify(pdf_path, total_page, page_width, page_height, img_sz_list, text_len_list) - # o['is_text_pdf'] = tag - # print(json.dumps(o, ensure_ascii=False)) diff --git a/magic_pdf/filter/pdf_meta_scan.py b/magic_pdf/filter/pdf_meta_scan.py deleted file mode 100644 index 67e56315057299b4888bc4058f057d857c0b3dc8..0000000000000000000000000000000000000000 --- a/magic_pdf/filter/pdf_meta_scan.py +++ /dev/null @@ -1,397 +0,0 @@ -"""输入: s3路径,每行一个 输出: pdf文件元信息,包括每一页上的所有图片的长宽高,bbox位置.""" - -from collections import Counter - -import fitz -from loguru import logger - -from magic_pdf.config.drop_reason import DropReason -from magic_pdf.libs.commons import get_top_percent_list, mymax -from magic_pdf.libs.language import detect_lang -from magic_pdf.libs.pdf_check import detect_invalid_chars_by_pymupdf, detect_invalid_chars - -scan_max_page = 50 -junk_limit_min = 10 - - -def calculate_max_image_area_per_page(result: list, page_width_pts, page_height_pts): - max_image_area_per_page = [ - mymax([(x1 - x0) * (y1 - y0) for x0, y0, x1, y1, _ in page_img_sz]) - for page_img_sz in result - ] - page_area = int(page_width_pts) * int(page_height_pts) - max_image_area_per_page = [area / page_area for area in max_image_area_per_page] - max_image_area_per_page = [area for area in max_image_area_per_page if area > 0.6] - return max_image_area_per_page - - -def process_image(page, junk_img_bojids=[]): - page_result = [] # 存每个页面里的多张图四元组信息 - items = page.get_images() - dedup = set() - for img in items: - # 这里返回的是图片在page上的实际展示的大小。返回一个数组,每个元素第一部分是 - img_bojid = img[ - 0 - ] # 在pdf文件中是全局唯一的,如果这个图反复出现在pdf里那么就可能是垃圾信息,例如水印、页眉页脚等 - if img_bojid in junk_img_bojids: # 如果是垃圾图像,就跳过 - continue - recs = page.get_image_rects(img, transform=True) - if recs: - rec = recs[0][0] - x0, y0, x1, y1 = map(int, rec) - width = x1 - x0 - height = y1 - y0 - if ( - x0, - y0, - x1, - y1, - img_bojid, - ) in dedup: # 这里面会出现一些重复的bbox,无需重复出现,需要去掉 - continue - if not all( - [width, height] - ): # 长和宽任何一个都不能是0,否则这个图片不可见,没有实际意义 - continue - dedup.add((x0, y0, x1, y1, img_bojid)) - page_result.append([x0, y0, x1, y1, img_bojid]) - return page_result - - -def get_image_info(doc: fitz.Document, page_width_pts, page_height_pts) -> list: - """返回每个页面里的图片的四元组,每个页面多个图片。 - - :param doc: - :return: - """ - # 使用 Counter 计数 img_bojid 的出现次数 - img_bojid_counter = Counter(img[0] for page in doc for img in page.get_images()) - # 找出出现次数超过 len(doc) 半数的 img_bojid - - junk_limit = max(len(doc) * 0.5, junk_limit_min) # 对一些页数比较少的进行豁免 - - junk_img_bojids = [ - img_bojid - for img_bojid, count in img_bojid_counter.items() - if count >= junk_limit - ] - - # todo 加个判断,用前十页就行,这些垃圾图片需要满足两个条件,不止出现的次数要足够多,而且图片占书页面积的比例要足够大,且图与图大小都差不多 - # 有两种扫描版,一种文字版,这里可能会有误判 - # 扫描版1:每页都有所有扫描页图片,特点是图占比大,每页展示1张 - # 扫描版2,每页存储的扫描页图片数量递增,特点是图占比大,每页展示1张,需要清空junklist跑前50页图片信息用于分类判断 - # 文 字版1.每页存储所有图片,特点是图片占页面比例不大,每页展示可能为0也可能不止1张 这种pdf需要拿前10页抽样检测img大小和个数,如果符合需要清空junklist - imgs_len_list = [len(page.get_images()) for page in doc] - - special_limit_pages = 10 - - # 统一用前十页结果做判断 - result = [] - break_loop = False - for i, page in enumerate(doc): - if break_loop: - break - if i >= special_limit_pages: - break - page_result = process_image( - page - ) # 这里不传junk_img_bojids,拿前十页所有图片信息用于后续分析 - result.append(page_result) - for item in result: - if not any( - item - ): # 如果任何一页没有图片,说明是个文字版,需要判断是否为特殊文字版 - if ( - max(imgs_len_list) == min(imgs_len_list) - and max(imgs_len_list) >= junk_limit_min - ): # 如果是特殊文字版,就把junklist置空并break - junk_img_bojids = [] - else: # 不是特殊文字版,是个普通文字版,但是存在垃圾图片,不置空junklist - pass - break_loop = True - break - if not break_loop: - # 获取前80%的元素 - top_eighty_percent = get_top_percent_list(imgs_len_list, 0.8) - # 检查前80%的元素是否都相等 - if len(set(top_eighty_percent)) == 1 and max(imgs_len_list) >= junk_limit_min: - # # 如果前10页跑完都有图,根据每页图片数量是否相等判断是否需要清除junklist - # if max(imgs_len_list) == min(imgs_len_list) and max(imgs_len_list) >= junk_limit_min: - - # 前10页都有图,且每页数量一致,需要检测图片大小占页面的比例判断是否需要清除junklist - max_image_area_per_page = calculate_max_image_area_per_page( - result, page_width_pts, page_height_pts - ) - if ( - len(max_image_area_per_page) < 0.8 * special_limit_pages - ): # 前10页不全是大图,说明可能是个文字版pdf,把垃圾图片list置空 - junk_img_bojids = [] - else: # 前10页都有图,而且80%都是大图,且每页图片数量一致并都很多,说明是扫描版1,不需要清空junklist - pass - else: # 每页图片数量不一致,需要清掉junklist全量跑前50页图片 - junk_img_bojids = [] - - # 正式进入取前50页图片的信息流程 - result = [] - for i, page in enumerate(doc): - if i >= scan_max_page: - break - page_result = process_image(page, junk_img_bojids) - # logger.info(f"page {i} img_len: {len(page_result)}") - result.append(page_result) - - return result, junk_img_bojids - - -def get_pdf_page_size_pts(doc: fitz.Document): - page_cnt = len(doc) - l: int = min(page_cnt, 50) - # 把所有宽度和高度塞到两个list 分别取中位数(中间遇到了个在纵页里塞横页的pdf,导致宽高互换了) - page_width_list = [] - page_height_list = [] - for i in range(l): - page = doc[i] - page_rect = page.rect - page_width_list.append(page_rect.width) - page_height_list.append(page_rect.height) - - page_width_list.sort() - page_height_list.sort() - - median_width = page_width_list[len(page_width_list) // 2] - median_height = page_height_list[len(page_height_list) // 2] - - return median_width, median_height - - -def get_pdf_textlen_per_page(doc: fitz.Document): - text_len_lst = [] - for page in doc: - # 拿包含img和text的所有blocks - # text_block = page.get_text("blocks") - # 拿所有text的blocks - # text_block = page.get_text("words") - # text_block_len = sum([len(t[4]) for t in text_block]) - # 拿所有text的str - text_block = page.get_text('text') - text_block_len = len(text_block) - # logger.info(f"page {page.number} text_block_len: {text_block_len}") - text_len_lst.append(text_block_len) - - return text_len_lst - - -def get_pdf_text_layout_per_page(doc: fitz.Document): - """根据PDF文档的每一页文本布局,判断该页的文本布局是横向、纵向还是未知。 - - Args: - doc (fitz.Document): PDF文档对象。 - - Returns: - List[str]: 每一页的文本布局(横向、纵向、未知)。 - """ - text_layout_list = [] - - for page_id, page in enumerate(doc): - if page_id >= scan_max_page: - break - # 创建每一页的纵向和横向的文本行数计数器 - vertical_count = 0 - horizontal_count = 0 - text_dict = page.get_text('dict') - if 'blocks' in text_dict: - for block in text_dict['blocks']: - if 'lines' in block: - for line in block['lines']: - # 获取line的bbox顶点坐标 - x0, y0, x1, y1 = line['bbox'] - # 计算bbox的宽高 - width = x1 - x0 - height = y1 - y0 - # 计算bbox的面积 - area = width * height - font_sizes = [] - for span in line['spans']: - if 'size' in span: - font_sizes.append(span['size']) - if len(font_sizes) > 0: - average_font_size = sum(font_sizes) / len(font_sizes) - else: - average_font_size = ( - 10 # 有的line拿不到font_size,先定一个阈值100 - ) - if ( - area <= average_font_size**2 - ): # 判断bbox的面积是否小于平均字体大小的平方,单字无法计算是横向还是纵向 - continue - else: - if 'wmode' in line: # 通过wmode判断文本方向 - if line['wmode'] == 1: # 判断是否为竖向文本 - vertical_count += 1 - elif line['wmode'] == 0: # 判断是否为横向文本 - horizontal_count += 1 - # if 'dir' in line: # 通过旋转角度计算判断文本方向 - # # 获取行的 "dir" 值 - # dir_value = line['dir'] - # cosine, sine = dir_value - # # 计算角度 - # angle = math.degrees(math.acos(cosine)) - # - # # 判断是否为横向文本 - # if abs(angle - 0) < 0.01 or abs(angle - 180) < 0.01: - # # line_text = ' '.join(span['text'] for span in line['spans']) - # # print('This line is horizontal:', line_text) - # horizontal_count += 1 - # # 判断是否为纵向文本 - # elif abs(angle - 90) < 0.01 or abs(angle - 270) < 0.01: - # # line_text = ' '.join(span['text'] for span in line['spans']) - # # print('This line is vertical:', line_text) - # vertical_count += 1 - # print(f"page_id: {page_id}, vertical_count: {vertical_count}, horizontal_count: {horizontal_count}") - # 判断每一页的文本布局 - if vertical_count == 0 and horizontal_count == 0: # 该页没有文本,无法判断 - text_layout_list.append('unknow') - continue - else: - if vertical_count > horizontal_count: # 该页的文本纵向行数大于横向的 - text_layout_list.append('vertical') - else: # 该页的文本横向行数大于纵向的 - text_layout_list.append('horizontal') - # logger.info(f"page_id: {page_id}, vertical_count: {vertical_count}, horizontal_count: {horizontal_count}") - return text_layout_list - - -"""定义一个自定义异常用来抛出单页svg太多的pdf""" - - -class PageSvgsTooManyError(Exception): - def __init__(self, message='Page SVGs are too many'): - self.message = message - super().__init__(self.message) - - -def get_svgs_per_page(doc: fitz.Document): - svgs_len_list = [] - for page_id, page in enumerate(doc): - # svgs = page.get_drawings() - svgs = page.get_cdrawings() # 切换成get_cdrawings,效率更高 - len_svgs = len(svgs) - if len_svgs >= 3000: - raise PageSvgsTooManyError() - else: - svgs_len_list.append(len_svgs) - # logger.info(f"page_id: {page_id}, svgs_len: {len(svgs)}") - return svgs_len_list - - -def get_imgs_per_page(doc: fitz.Document): - imgs_len_list = [] - for page_id, page in enumerate(doc): - imgs = page.get_images() - imgs_len_list.append(len(imgs)) - # logger.info(f"page_id: {page}, imgs_len: {len(imgs)}") - - return imgs_len_list - - -def get_language(doc: fitz.Document): - """ - 获取PDF文档的语言。 - Args: - doc (fitz.Document): PDF文档对象。 - Returns: - str: 文档语言,如 "en-US"。 - """ - language_lst = [] - for page_id, page in enumerate(doc): - if page_id >= scan_max_page: - break - # 拿所有text的str - text_block = page.get_text('text') - page_language = detect_lang(text_block) - language_lst.append(page_language) - - # logger.info(f"page_id: {page_id}, page_language: {page_language}") - - # 统计text_language_list中每种语言的个数 - count_dict = Counter(language_lst) - # 输出text_language_list中出现的次数最多的语言 - language = max(count_dict, key=count_dict.get) - return language - - -def check_invalid_chars(pdf_bytes): - """乱码检测.""" - # return detect_invalid_chars_by_pymupdf(pdf_bytes) - return detect_invalid_chars(pdf_bytes) - - -def pdf_meta_scan(pdf_bytes: bytes): - """ - :param s3_pdf_path: - :param pdf_bytes: pdf文件的二进制数据 - 几个维度来评价:是否加密,是否需要密码,纸张大小,总页数,是否文字可提取 - """ - doc = fitz.open('pdf', pdf_bytes) - is_needs_password = doc.needs_pass - is_encrypted = doc.is_encrypted - total_page = len(doc) - if total_page == 0: - logger.warning(f'drop this pdf, drop_reason: {DropReason.EMPTY_PDF}') - result = {'_need_drop': True, '_drop_reason': DropReason.EMPTY_PDF} - return result - else: - page_width_pts, page_height_pts = get_pdf_page_size_pts(doc) - # logger.info(f"page_width_pts: {page_width_pts}, page_height_pts: {page_height_pts}") - - # svgs_per_page = get_svgs_per_page(doc) - # logger.info(f"svgs_per_page: {svgs_per_page}") - imgs_per_page = get_imgs_per_page(doc) - # logger.info(f"imgs_per_page: {imgs_per_page}") - - image_info_per_page, junk_img_bojids = get_image_info( - doc, page_width_pts, page_height_pts - ) - # logger.info(f"image_info_per_page: {image_info_per_page}, junk_img_bojids: {junk_img_bojids}") - text_len_per_page = get_pdf_textlen_per_page(doc) - # logger.info(f"text_len_per_page: {text_len_per_page}") - # text_layout_per_page = get_pdf_text_layout_per_page(doc) - # logger.info(f"text_layout_per_page: {text_layout_per_page}") - # text_language = get_language(doc) - # logger.info(f"text_language: {text_language}") - invalid_chars = check_invalid_chars(pdf_bytes) - # logger.info(f"invalid_chars: {invalid_chars}") - - # 最后输出一条json - res = { - 'is_needs_password': is_needs_password, - 'is_encrypted': is_encrypted, - 'total_page': total_page, - 'page_width_pts': int(page_width_pts), - 'page_height_pts': int(page_height_pts), - 'image_info_per_page': image_info_per_page, - 'text_len_per_page': text_len_per_page, - # 'text_layout_per_page': text_layout_per_page, - # 'text_language': text_language, - # "svgs_per_page": svgs_per_page, - 'imgs_per_page': imgs_per_page, # 增加每页img数量list - 'junk_img_bojids': junk_img_bojids, # 增加垃圾图片的bojid list - 'invalid_chars': invalid_chars, - 'metadata': doc.metadata, - } - # logger.info(json.dumps(res, ensure_ascii=False)) - return res - - -if __name__ == '__main__': - pass - # "D:\project/20231108code-clean\pdf_cost_time\竖排例子\净空法师-大乘无量寿.pdf" - # "D:\project/20231108code-clean\pdf_cost_time\竖排例子\三国演义_繁体竖排版.pdf" - # "D:\project/20231108code-clean\pdf_cost_time\scihub\scihub_86800000\libgen.scimag86880000-86880999.zip_10.1021/acsami.1c03109.s002.pdf" - # "D:/project/20231108code-clean/pdf_cost_time/scihub/scihub_18600000/libgen.scimag18645000-18645999.zip_10.1021/om3006239.pdf" - # file_content = read_file("D:/project/20231108code-clean/pdf_cost_time/scihub/scihub_31000000/libgen.scimag31098000-31098999.zip_10.1109/isit.2006.261791.pdf","") # noqa: E501 - # file_content = read_file("D:\project/20231108code-clean\pdf_cost_time\竖排例子\净空法师_大乘无量寿.pdf","") - # doc = fitz.open("pdf", file_content) - # text_layout_lst = get_pdf_text_layout_per_page(doc) - # print(text_layout_lst) diff --git a/magic_pdf/integrations/__init__.py b/magic_pdf/integrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/integrations/rag/__init__.py b/magic_pdf/integrations/rag/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/integrations/rag/api.py b/magic_pdf/integrations/rag/api.py deleted file mode 100644 index 5c05f91169dad911b147a4f9c518af26a419b449..0000000000000000000000000000000000000000 --- a/magic_pdf/integrations/rag/api.py +++ /dev/null @@ -1,82 +0,0 @@ -import os -from pathlib import Path - -from loguru import logger - -from magic_pdf.integrations.rag.type import (ElementRelation, LayoutElements, - Node) -from magic_pdf.integrations.rag.utils import inference - - -class RagPageReader: - - def __init__(self, pagedata: LayoutElements): - self.o = [ - Node( - category_type=v.category_type, - text=v.text, - image_path=v.image_path, - anno_id=v.anno_id, - latex=v.latex, - html=v.html, - ) for v in pagedata.layout_dets - ] - - self.pagedata = pagedata - - def __iter__(self): - return iter(self.o) - - def get_rel_map(self) -> list[ElementRelation]: - return self.pagedata.extra.element_relation - - -class RagDocumentReader: - - def __init__(self, ragdata: list[LayoutElements]): - self.o = [RagPageReader(v) for v in ragdata] - - def __iter__(self): - return iter(self.o) - - -class DataReader: - - def __init__(self, path_or_directory: str, method: str, output_dir: str): - self.path_or_directory = path_or_directory - self.method = method - self.output_dir = output_dir - self.pdfs = [] - if os.path.isdir(path_or_directory): - for doc_path in Path(path_or_directory).glob('*.pdf'): - self.pdfs.append(doc_path) - else: - assert path_or_directory.endswith('.pdf') - self.pdfs.append(Path(path_or_directory)) - - def get_documents_count(self) -> int: - """Returns the number of documents in the directory.""" - return len(self.pdfs) - - def get_document_result(self, idx: int) -> RagDocumentReader | None: - """ - Args: - idx (int): the index of documents under the - directory path_or_directory - - Returns: - RagDocumentReader | None: RagDocumentReader is an iterable object, - more details @RagDocumentReader - """ - if idx >= self.get_documents_count() or idx < 0: - logger.error(f'invalid idx: {idx}') - return None - res = inference(str(self.pdfs[idx]), self.output_dir, self.method) - if res is None: - logger.warning(f'failed to inference pdf {self.pdfs[idx]}') - return None - return RagDocumentReader(res) - - def get_document_filename(self, idx: int) -> Path: - """get the filename of the document.""" - return self.pdfs[idx] diff --git a/magic_pdf/integrations/rag/type.py b/magic_pdf/integrations/rag/type.py deleted file mode 100644 index 11258af39487f3084a900d44c5bc4eb364ef2230..0000000000000000000000000000000000000000 --- a/magic_pdf/integrations/rag/type.py +++ /dev/null @@ -1,82 +0,0 @@ -from enum import Enum - -from pydantic import BaseModel, Field - - -# rag -class CategoryType(Enum): # py310 not support StrEnum - text = 'text' - title = 'title' - interline_equation = 'interline_equation' - image = 'image' - image_body = 'image_body' - image_caption = 'image_caption' - table = 'table' - table_body = 'table_body' - table_caption = 'table_caption' - table_footnote = 'table_footnote' - - -class ElementRelType(Enum): - sibling = 'sibling' - - -class PageInfo(BaseModel): - page_no: int = Field(description='the index of page, start from zero', - ge=0) - height: int = Field(description='the height of page', gt=0) - width: int = Field(description='the width of page', ge=0) - image_path: str | None = Field(description='the image of this page', - default=None) - - -class ContentObject(BaseModel): - category_type: CategoryType = Field(description='类别') - poly: list[float] = Field( - description=('Coordinates, need to convert back to PDF coordinates,' - ' order is top-left, top-right, bottom-right, bottom-left' - ' x,y coordinates')) - ignore: bool = Field(description='whether ignore this object', - default=False) - text: str | None = Field(description='text content of the object', - default=None) - image_path: str | None = Field(description='path of embedded image', - default=None) - order: int = Field(description='the order of this object within a page', - default=-1) - anno_id: int = Field(description='unique id', default=-1) - latex: str | None = Field(description='latex result', default=None) - html: str | None = Field(description='html result', default=None) - - -class ElementRelation(BaseModel): - source_anno_id: int = Field(description='unique id of the source object', - default=-1) - target_anno_id: int = Field(description='unique id of the target object', - default=-1) - relation: ElementRelType = Field( - description='the relation between source and target element') - - -class LayoutElementsExtra(BaseModel): - element_relation: list[ElementRelation] = Field( - description='the relation between source and target element') - - -class LayoutElements(BaseModel): - layout_dets: list[ContentObject] = Field( - description='layout element details') - page_info: PageInfo = Field(description='page info') - extra: LayoutElementsExtra = Field(description='extra information') - - -# iter data format -class Node(BaseModel): - category_type: CategoryType = Field(description='类别') - text: str | None = Field(description='text content of the object', - default=None) - image_path: str | None = Field(description='path of embedded image', - default=None) - anno_id: int = Field(description='unique id', default=-1) - latex: str | None = Field(description='latex result', default=None) - html: str | None = Field(description='html result', default=None) diff --git a/magic_pdf/integrations/rag/utils.py b/magic_pdf/integrations/rag/utils.py deleted file mode 100644 index 49e9dc0ee2a6955219012dd05aa58d6e56b1f25d..0000000000000000000000000000000000000000 --- a/magic_pdf/integrations/rag/utils.py +++ /dev/null @@ -1,284 +0,0 @@ -import json -import os -from pathlib import Path - -from loguru import logger - -import magic_pdf.model as model_config -from magic_pdf.config.ocr_content_type import BlockType, ContentType -from magic_pdf.data.data_reader_writer import FileBasedDataReader -from magic_pdf.dict2md.ocr_mkcontent import merge_para_with_text -from magic_pdf.integrations.rag.type import (CategoryType, ContentObject, - ElementRelation, ElementRelType, - LayoutElements, - LayoutElementsExtra, PageInfo) -from magic_pdf.tools.common import do_parse, prepare_env - - -def convert_middle_json_to_layout_elements( - json_data: dict, - output_dir: str, -) -> list[LayoutElements]: - uniq_anno_id = 0 - - res: list[LayoutElements] = [] - for page_no, page_data in enumerate(json_data['pdf_info']): - order_id = 0 - page_info = PageInfo( - height=int(page_data['page_size'][1]), - width=int(page_data['page_size'][0]), - page_no=page_no, - ) - layout_dets: list[ContentObject] = [] - extra_element_relation: list[ElementRelation] = [] - - for para_block in page_data['para_blocks']: - para_text = '' - para_type = para_block['type'] - - if para_type == BlockType.Text: - para_text = merge_para_with_text(para_block) - x0, y0, x1, y1 = para_block['bbox'] - content = ContentObject( - anno_id=uniq_anno_id, - category_type=CategoryType.text, - text=para_text, - order=order_id, - poly=[x0, y0, x1, y0, x1, y1, x0, y1], - ) - uniq_anno_id += 1 - order_id += 1 - layout_dets.append(content) - - elif para_type == BlockType.Title: - para_text = merge_para_with_text(para_block) - x0, y0, x1, y1 = para_block['bbox'] - content = ContentObject( - anno_id=uniq_anno_id, - category_type=CategoryType.title, - text=para_text, - order=order_id, - poly=[x0, y0, x1, y0, x1, y1, x0, y1], - ) - uniq_anno_id += 1 - order_id += 1 - layout_dets.append(content) - - elif para_type == BlockType.InterlineEquation: - para_text = merge_para_with_text(para_block) - x0, y0, x1, y1 = para_block['bbox'] - content = ContentObject( - anno_id=uniq_anno_id, - category_type=CategoryType.interline_equation, - text=para_text, - order=order_id, - poly=[x0, y0, x1, y0, x1, y1, x0, y1], - ) - uniq_anno_id += 1 - order_id += 1 - layout_dets.append(content) - - elif para_type == BlockType.Image: - body_anno_id = -1 - caption_anno_id = -1 - - for block in para_block['blocks']: - if block['type'] == BlockType.ImageBody: - for line in block['lines']: - for span in line['spans']: - if span['type'] == ContentType.Image: - x0, y0, x1, y1 = block['bbox'] - content = ContentObject( - anno_id=uniq_anno_id, - category_type=CategoryType.image_body, - image_path=os.path.join( - output_dir, span['image_path']), - order=order_id, - poly=[x0, y0, x1, y0, x1, y1, x0, y1], - ) - body_anno_id = uniq_anno_id - uniq_anno_id += 1 - order_id += 1 - layout_dets.append(content) - - for block in para_block['blocks']: - if block['type'] == BlockType.ImageCaption: - para_text += merge_para_with_text(block) - x0, y0, x1, y1 = block['bbox'] - content = ContentObject( - anno_id=uniq_anno_id, - category_type=CategoryType.image_caption, - text=para_text, - order=order_id, - poly=[x0, y0, x1, y0, x1, y1, x0, y1], - ) - caption_anno_id = uniq_anno_id - uniq_anno_id += 1 - order_id += 1 - layout_dets.append(content) - - if body_anno_id > 0 and caption_anno_id > 0: - element_relation = ElementRelation( - relation=ElementRelType.sibling, - source_anno_id=body_anno_id, - target_anno_id=caption_anno_id, - ) - extra_element_relation.append(element_relation) - - elif para_type == BlockType.Table: - body_anno_id, caption_anno_id, footnote_anno_id = -1, -1, -1 - - for block in para_block['blocks']: - if block['type'] == BlockType.TableCaption: - para_text += merge_para_with_text(block) - x0, y0, x1, y1 = block['bbox'] - content = ContentObject( - anno_id=uniq_anno_id, - category_type=CategoryType.table_caption, - text=para_text, - order=order_id, - poly=[x0, y0, x1, y0, x1, y1, x0, y1], - ) - caption_anno_id = uniq_anno_id - uniq_anno_id += 1 - order_id += 1 - layout_dets.append(content) - - for block in para_block['blocks']: - if block['type'] == BlockType.TableBody: - for line in block['lines']: - for span in line['spans']: - if span['type'] == ContentType.Table: - x0, y0, x1, y1 = para_block['bbox'] - content = ContentObject( - anno_id=uniq_anno_id, - category_type=CategoryType.table_body, - order=order_id, - poly=[x0, y0, x1, y0, x1, y1, x0, y1], - ) - body_anno_id = uniq_anno_id - uniq_anno_id += 1 - order_id += 1 - # if processed by table model - if span.get('latex', ''): - content.latex = span['latex'] - else: - content.image_path = os.path.join( - output_dir, span['image_path']) - layout_dets.append(content) - - for block in para_block['blocks']: - if block['type'] == BlockType.TableFootnote: - para_text += merge_para_with_text(block) - x0, y0, x1, y1 = block['bbox'] - content = ContentObject( - anno_id=uniq_anno_id, - category_type=CategoryType.table_footnote, - text=para_text, - order=order_id, - poly=[x0, y0, x1, y0, x1, y1, x0, y1], - ) - footnote_anno_id = uniq_anno_id - uniq_anno_id += 1 - order_id += 1 - layout_dets.append(content) - - if caption_anno_id != -1 and body_anno_id != -1: - element_relation = ElementRelation( - relation=ElementRelType.sibling, - source_anno_id=body_anno_id, - target_anno_id=caption_anno_id, - ) - extra_element_relation.append(element_relation) - - if footnote_anno_id != -1 and body_anno_id != -1: - element_relation = ElementRelation( - relation=ElementRelType.sibling, - source_anno_id=body_anno_id, - target_anno_id=footnote_anno_id, - ) - extra_element_relation.append(element_relation) - - res.append( - LayoutElements( - page_info=page_info, - layout_dets=layout_dets, - extra=LayoutElementsExtra( - element_relation=extra_element_relation), - )) - - return res - - -def inference(path, output_dir, method): - model_config.__use_inside_model__ = True - model_config.__model_mode__ = 'full' - if output_dir == '': - if os.path.isdir(path): - output_dir = os.path.join(path, 'output') - else: - output_dir = os.path.join(os.path.dirname(path), 'output') - - local_image_dir, local_md_dir = prepare_env(output_dir, - str(Path(path).stem), method) - - def read_fn(path): - disk_rw = FileBasedDataReader(os.path.dirname(path)) - return disk_rw.read(os.path.basename(path)) - - def parse_doc(doc_path: str): - try: - file_name = str(Path(doc_path).stem) - pdf_data = read_fn(doc_path) - do_parse( - output_dir, - file_name, - pdf_data, - [], - method, - False, - f_draw_span_bbox=False, - f_draw_layout_bbox=False, - f_dump_md=False, - f_dump_middle_json=True, - f_dump_model_json=False, - f_dump_orig_pdf=False, - f_dump_content_list=False, - f_draw_model_bbox=False, - ) - - middle_json_fn = os.path.join(local_md_dir, - f'{file_name}_middle.json') - with open(middle_json_fn) as fd: - jso = json.load(fd) - os.remove(middle_json_fn) - return convert_middle_json_to_layout_elements(jso, local_image_dir) - - except Exception as e: - logger.exception(e) - - return parse_doc(path) - - -if __name__ == '__main__': - import pprint - - base_dir = '/opt/data/pdf/resources/samples/' - if 0: - with open(base_dir + 'json_outputs/middle.json') as f: - d = json.load(f) - result = convert_middle_json_to_layout_elements(d, '/tmp') - pprint.pp(result) - if 0: - with open(base_dir + 'json_outputs/middle.3.json') as f: - d = json.load(f) - result = convert_middle_json_to_layout_elements(d, '/tmp') - pprint.pp(result) - - if 1: - res = inference( - base_dir + 'samples/pdf/one_page_with_table_image.pdf', - '/tmp/output', - 'ocr', - ) - pprint.pp(res) diff --git a/magic_pdf/libs/__init__.py b/magic_pdf/libs/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/libs/boxbase.py b/magic_pdf/libs/boxbase.py deleted file mode 100644 index 2813121bb3fcde988d510b89646478c97461da74..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/boxbase.py +++ /dev/null @@ -1,485 +0,0 @@ -import math - - -def _is_in_or_part_overlap(box1, box2) -> bool: - """两个bbox是否有部分重叠或者包含.""" - if box1 is None or box2 is None: - return False - - x0_1, y0_1, x1_1, y1_1 = box1 - x0_2, y0_2, x1_2, y1_2 = box2 - - return not (x1_1 < x0_2 or # box1在box2的左边 - x0_1 > x1_2 or # box1在box2的右边 - y1_1 < y0_2 or # box1在box2的上边 - y0_1 > y1_2) # box1在box2的下边 - - -def _is_in_or_part_overlap_with_area_ratio(box1, - box2, - area_ratio_threshold=0.6): - """判断box1是否在box2里面,或者box1和box2有部分重叠,且重叠面积占box1的比例超过area_ratio_threshold.""" - if box1 is None or box2 is None: - return False - - x0_1, y0_1, x1_1, y1_1 = box1 - x0_2, y0_2, x1_2, y1_2 = box2 - - if not _is_in_or_part_overlap(box1, box2): - return False - - # 计算重叠面积 - x_left = max(x0_1, x0_2) - y_top = max(y0_1, y0_2) - x_right = min(x1_1, x1_2) - y_bottom = min(y1_1, y1_2) - overlap_area = (x_right - x_left) * (y_bottom - y_top) - - # 计算box1的面积 - box1_area = (x1_1 - x0_1) * (y1_1 - y0_1) - - return overlap_area / box1_area > area_ratio_threshold - - -def _is_in(box1, box2) -> bool: - """box1是否完全在box2里面.""" - x0_1, y0_1, x1_1, y1_1 = box1 - x0_2, y0_2, x1_2, y1_2 = box2 - - return (x0_1 >= x0_2 and # box1的左边界不在box2的左边外 - y0_1 >= y0_2 and # box1的上边界不在box2的上边外 - x1_1 <= x1_2 and # box1的右边界不在box2的右边外 - y1_1 <= y1_2) # box1的下边界不在box2的下边外 - - -def _is_part_overlap(box1, box2) -> bool: - """两个bbox是否有部分重叠,但不完全包含.""" - if box1 is None or box2 is None: - return False - - return _is_in_or_part_overlap(box1, box2) and not _is_in(box1, box2) - - -def _left_intersect(left_box, right_box): - """检查两个box的左边界是否有交集,也就是left_box的右边界是否在right_box的左边界内.""" - if left_box is None or right_box is None: - return False - - x0_1, y0_1, x1_1, y1_1 = left_box - x0_2, y0_2, x1_2, y1_2 = right_box - - return x1_1 > x0_2 and x0_1 < x0_2 and (y0_1 <= y0_2 <= y1_1 - or y0_1 <= y1_2 <= y1_1) - - -def _right_intersect(left_box, right_box): - """检查box是否在右侧边界有交集,也就是left_box的左边界是否在right_box的右边界内.""" - if left_box is None or right_box is None: - return False - - x0_1, y0_1, x1_1, y1_1 = left_box - x0_2, y0_2, x1_2, y1_2 = right_box - - return x0_1 < x1_2 and x1_1 > x1_2 and (y0_1 <= y0_2 <= y1_1 - or y0_1 <= y1_2 <= y1_1) - - -def _is_vertical_full_overlap(box1, box2, x_torlence=2): - """x方向上:要么box1包含box2, 要么box2包含box1。不能部分包含 y方向上:box1和box2有重叠.""" - # 解析box的坐标 - x11, y11, x12, y12 = box1 # 左上角和右下角的坐标 (x1, y1, x2, y2) - x21, y21, x22, y22 = box2 - - # 在x轴方向上,box1是否包含box2 或 box2包含box1 - contains_in_x = (x11 - x_torlence <= x21 and x12 + x_torlence >= x22) or ( - x21 - x_torlence <= x11 and x22 + x_torlence >= x12) - - # 在y轴方向上,box1和box2是否有重叠 - overlap_in_y = not (y12 < y21 or y11 > y22) - - return contains_in_x and overlap_in_y - - -def _is_bottom_full_overlap(box1, box2, y_tolerance=2): - """检查box1下方和box2的上方有轻微的重叠,轻微程度收到y_tolerance的限制 这个函数和_is_vertical- - full_overlap的区别是,这个函数允许box1和box2在x方向上有轻微的重叠,允许一定的模糊度.""" - if box1 is None or box2 is None: - return False - - x0_1, y0_1, x1_1, y1_1 = box1 - x0_2, y0_2, x1_2, y1_2 = box2 - tolerance_margin = 2 - is_xdir_full_overlap = ( - (x0_1 - tolerance_margin <= x0_2 <= x1_1 + tolerance_margin - and x0_1 - tolerance_margin <= x1_2 <= x1_1 + tolerance_margin) - or (x0_2 - tolerance_margin <= x0_1 <= x1_2 + tolerance_margin - and x0_2 - tolerance_margin <= x1_1 <= x1_2 + tolerance_margin)) - - return y0_2 < y1_1 and 0 < (y1_1 - - y0_2) < y_tolerance and is_xdir_full_overlap - - -def _is_left_overlap( - box1, - box2, -): - """检查box1的左侧是否和box2有重叠 在Y方向上可以是部分重叠或者是完全重叠。不分box1和box2的上下关系,也就是无论box1在box2下 - 方还是box2在box1下方,都可以检测到重叠。 X方向上.""" - - def __overlap_y(Ay1, Ay2, By1, By2): - return max(0, min(Ay2, By2) - max(Ay1, By1)) - - if box1 is None or box2 is None: - return False - - x0_1, y0_1, x1_1, y1_1 = box1 - x0_2, y0_2, x1_2, y1_2 = box2 - - y_overlap_len = __overlap_y(y0_1, y1_1, y0_2, y1_2) - ratio_1 = 1.0 * y_overlap_len / (y1_1 - y0_1) if y1_1 - y0_1 != 0 else 0 - ratio_2 = 1.0 * y_overlap_len / (y1_2 - y0_2) if y1_2 - y0_2 != 0 else 0 - vertical_overlap_cond = ratio_1 >= 0.5 or ratio_2 >= 0.5 - - # vertical_overlap_cond = y0_1<=y0_2<=y1_1 or y0_1<=y1_2<=y1_1 or y0_2<=y0_1<=y1_2 or y0_2<=y1_1<=y1_2 - return x0_1 <= x0_2 <= x1_1 and vertical_overlap_cond - - -def __is_overlaps_y_exceeds_threshold(bbox1, - bbox2, - overlap_ratio_threshold=0.8): - """检查两个bbox在y轴上是否有重叠,并且该重叠区域的高度占两个bbox高度更低的那个超过80%""" - _, y0_1, _, y1_1 = bbox1 - _, y0_2, _, y1_2 = bbox2 - - overlap = max(0, min(y1_1, y1_2) - max(y0_1, y0_2)) - height1, height2 = y1_1 - y0_1, y1_2 - y0_2 - # max_height = max(height1, height2) - min_height = min(height1, height2) - - return (overlap / min_height) > overlap_ratio_threshold - - -def calculate_iou(bbox1, bbox2): - """计算两个边界框的交并比(IOU)。 - - Args: - bbox1 (list[float]): 第一个边界框的坐标,格式为 [x1, y1, x2, y2],其中 (x1, y1) 为左上角坐标,(x2, y2) 为右下角坐标。 - bbox2 (list[float]): 第二个边界框的坐标,格式与 `bbox1` 相同。 - - Returns: - float: 两个边界框的交并比(IOU),取值范围为 [0, 1]。 - """ - # Determine the coordinates of the intersection rectangle - x_left = max(bbox1[0], bbox2[0]) - y_top = max(bbox1[1], bbox2[1]) - x_right = min(bbox1[2], bbox2[2]) - y_bottom = min(bbox1[3], bbox2[3]) - - if x_right < x_left or y_bottom < y_top: - return 0.0 - - # The area of overlap area - intersection_area = (x_right - x_left) * (y_bottom - y_top) - - # The area of both rectangles - bbox1_area = (bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1]) - bbox2_area = (bbox2[2] - bbox2[0]) * (bbox2[3] - bbox2[1]) - - if any([bbox1_area == 0, bbox2_area == 0]): - return 0 - - # Compute the intersection over union by taking the intersection area - # and dividing it by the sum of both areas minus the intersection area - iou = intersection_area / float(bbox1_area + bbox2_area - intersection_area) - - return iou - - -def calculate_overlap_area_2_minbox_area_ratio(bbox1, bbox2): - """计算box1和box2的重叠面积占最小面积的box的比例.""" - # Determine the coordinates of the intersection rectangle - x_left = max(bbox1[0], bbox2[0]) - y_top = max(bbox1[1], bbox2[1]) - x_right = min(bbox1[2], bbox2[2]) - y_bottom = min(bbox1[3], bbox2[3]) - - if x_right < x_left or y_bottom < y_top: - return 0.0 - - # The area of overlap area - intersection_area = (x_right - x_left) * (y_bottom - y_top) - min_box_area = min([(bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1]), - (bbox2[3] - bbox2[1]) * (bbox2[2] - bbox2[0])]) - if min_box_area == 0: - return 0 - else: - return intersection_area / min_box_area - - -def calculate_overlap_area_in_bbox1_area_ratio(bbox1, bbox2): - """计算box1和box2的重叠面积占bbox1的比例.""" - # Determine the coordinates of the intersection rectangle - x_left = max(bbox1[0], bbox2[0]) - y_top = max(bbox1[1], bbox2[1]) - x_right = min(bbox1[2], bbox2[2]) - y_bottom = min(bbox1[3], bbox2[3]) - - if x_right < x_left or y_bottom < y_top: - return 0.0 - - # The area of overlap area - intersection_area = (x_right - x_left) * (y_bottom - y_top) - bbox1_area = (bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1]) - if bbox1_area == 0: - return 0 - else: - return intersection_area / bbox1_area - - -def get_minbox_if_overlap_by_ratio(bbox1, bbox2, ratio): - """通过calculate_overlap_area_2_minbox_area_ratio计算两个bbox重叠的面积占最小面积的box的比例 - 如果比例大于ratio,则返回小的那个bbox, 否则返回None.""" - x1_min, y1_min, x1_max, y1_max = bbox1 - x2_min, y2_min, x2_max, y2_max = bbox2 - area1 = (x1_max - x1_min) * (y1_max - y1_min) - area2 = (x2_max - x2_min) * (y2_max - y2_min) - overlap_ratio = calculate_overlap_area_2_minbox_area_ratio(bbox1, bbox2) - if overlap_ratio > ratio: - if area1 <= area2: - return bbox1 - else: - return bbox2 - else: - return None - - -def get_bbox_in_boundary(bboxes: list, boundary: tuple) -> list: - x0, y0, x1, y1 = boundary - new_boxes = [ - box for box in bboxes - if box[0] >= x0 and box[1] >= y0 and box[2] <= x1 and box[3] <= y1 - ] - return new_boxes - - -def is_vbox_on_side(bbox, width, height, side_threshold=0.2): - """判断一个bbox是否在pdf页面的边缘.""" - x0, x1 = bbox[0], bbox[2] - if x1 <= width * side_threshold or x0 >= width * (1 - side_threshold): - return True - return False - - -def find_top_nearest_text_bbox(pymu_blocks, obj_bbox): - tolerance_margin = 4 - top_boxes = [ - box for box in pymu_blocks - if obj_bbox[1] - box['bbox'][3] >= -tolerance_margin - and not _is_in(box['bbox'], obj_bbox) - ] - # 然后找到X方向上有互相重叠的 - top_boxes = [ - box for box in top_boxes if any([ - obj_bbox[0] - tolerance_margin <= box['bbox'][0] <= obj_bbox[2] + - tolerance_margin, obj_bbox[0] - - tolerance_margin <= box['bbox'][2] <= obj_bbox[2] + - tolerance_margin, box['bbox'][0] - - tolerance_margin <= obj_bbox[0] <= box['bbox'][2] + - tolerance_margin, box['bbox'][0] - - tolerance_margin <= obj_bbox[2] <= box['bbox'][2] + - tolerance_margin - ]) - ] - - # 然后找到y1最大的那个 - if len(top_boxes) > 0: - top_boxes.sort(key=lambda x: x['bbox'][3], reverse=True) - return top_boxes[0] - else: - return None - - -def find_bottom_nearest_text_bbox(pymu_blocks, obj_bbox): - bottom_boxes = [ - box for box in pymu_blocks if box['bbox'][1] - - obj_bbox[3] >= -2 and not _is_in(box['bbox'], obj_bbox) - ] - # 然后找到X方向上有互相重叠的 - bottom_boxes = [ - box for box in bottom_boxes if any([ - obj_bbox[0] - 2 <= box['bbox'][0] <= obj_bbox[2] + 2, obj_bbox[0] - - 2 <= box['bbox'][2] <= obj_bbox[2] + 2, box['bbox'][0] - - 2 <= obj_bbox[0] <= box['bbox'][2] + 2, box['bbox'][0] - - 2 <= obj_bbox[2] <= box['bbox'][2] + 2 - ]) - ] - - # 然后找到y0最小的那个 - if len(bottom_boxes) > 0: - bottom_boxes.sort(key=lambda x: x['bbox'][1], reverse=False) - return bottom_boxes[0] - else: - return None - - -def find_left_nearest_text_bbox(pymu_blocks, obj_bbox): - """寻找左侧最近的文本block.""" - left_boxes = [ - box for box in pymu_blocks if obj_bbox[0] - - box['bbox'][2] >= -2 and not _is_in(box['bbox'], obj_bbox) - ] - # 然后找到X方向上有互相重叠的 - left_boxes = [ - box for box in left_boxes if any([ - obj_bbox[1] - 2 <= box['bbox'][1] <= obj_bbox[3] + 2, obj_bbox[1] - - 2 <= box['bbox'][3] <= obj_bbox[3] + 2, box['bbox'][1] - - 2 <= obj_bbox[1] <= box['bbox'][3] + 2, box['bbox'][1] - - 2 <= obj_bbox[3] <= box['bbox'][3] + 2 - ]) - ] - - # 然后找到x1最大的那个 - if len(left_boxes) > 0: - left_boxes.sort(key=lambda x: x['bbox'][2], reverse=True) - return left_boxes[0] - else: - return None - - -def find_right_nearest_text_bbox(pymu_blocks, obj_bbox): - """寻找右侧最近的文本block.""" - right_boxes = [ - box for box in pymu_blocks if box['bbox'][0] - - obj_bbox[2] >= -2 and not _is_in(box['bbox'], obj_bbox) - ] - # 然后找到X方向上有互相重叠的 - right_boxes = [ - box for box in right_boxes if any([ - obj_bbox[1] - 2 <= box['bbox'][1] <= obj_bbox[3] + 2, obj_bbox[1] - - 2 <= box['bbox'][3] <= obj_bbox[3] + 2, box['bbox'][1] - - 2 <= obj_bbox[1] <= box['bbox'][3] + 2, box['bbox'][1] - - 2 <= obj_bbox[3] <= box['bbox'][3] + 2 - ]) - ] - - # 然后找到x0最小的那个 - if len(right_boxes) > 0: - right_boxes.sort(key=lambda x: x['bbox'][0], reverse=False) - return right_boxes[0] - else: - return None - - -def bbox_relative_pos(bbox1, bbox2): - """判断两个矩形框的相对位置关系. - - Args: - bbox1: 一个四元组,表示第一个矩形框的左上角和右下角的坐标,格式为(x1, y1, x1b, y1b) - bbox2: 一个四元组,表示第二个矩形框的左上角和右下角的坐标,格式为(x2, y2, x2b, y2b) - - Returns: - 一个四元组,表示矩形框1相对于矩形框2的位置关系,格式为(left, right, bottom, top) - 其中,left表示矩形框1是否在矩形框2的左侧,right表示矩形框1是否在矩形框2的右侧, - bottom表示矩形框1是否在矩形框2的下方,top表示矩形框1是否在矩形框2的上方 - """ - x1, y1, x1b, y1b = bbox1 - x2, y2, x2b, y2b = bbox2 - - left = x2b < x1 - right = x1b < x2 - bottom = y2b < y1 - top = y1b < y2 - return left, right, bottom, top - - -def bbox_distance(bbox1, bbox2): - """计算两个矩形框的距离。 - - Args: - bbox1 (tuple): 第一个矩形框的坐标,格式为 (x1, y1, x2, y2),其中 (x1, y1) 为左上角坐标,(x2, y2) 为右下角坐标。 - bbox2 (tuple): 第二个矩形框的坐标,格式为 (x1, y1, x2, y2),其中 (x1, y1) 为左上角坐标,(x2, y2) 为右下角坐标。 - - Returns: - float: 矩形框之间的距离。 - """ - - def dist(point1, point2): - return math.sqrt((point1[0] - point2[0])**2 + - (point1[1] - point2[1])**2) - - x1, y1, x1b, y1b = bbox1 - x2, y2, x2b, y2b = bbox2 - - left, right, bottom, top = bbox_relative_pos(bbox1, bbox2) - - if top and left: - return dist((x1, y1b), (x2b, y2)) - elif left and bottom: - return dist((x1, y1), (x2b, y2b)) - elif bottom and right: - return dist((x1b, y1), (x2, y2b)) - elif right and top: - return dist((x1b, y1b), (x2, y2)) - elif left: - return x1 - x2b - elif right: - return x2 - x1b - elif bottom: - return y1 - y2b - elif top: - return y2 - y1b - return 0.0 - - -def box_area(bbox): - return (bbox[2] - bbox[0]) * (bbox[3] - bbox[1]) - - -def get_overlap_area(bbox1, bbox2): - """计算box1和box2的重叠面积占bbox1的比例.""" - # Determine the coordinates of the intersection rectangle - x_left = max(bbox1[0], bbox2[0]) - y_top = max(bbox1[1], bbox2[1]) - x_right = min(bbox1[2], bbox2[2]) - y_bottom = min(bbox1[3], bbox2[3]) - - if x_right < x_left or y_bottom < y_top: - return 0.0 - - # The area of overlap area - return (x_right - x_left) * (y_bottom - y_top) - - -def calculate_vertical_projection_overlap_ratio(block1, block2): - """ - Calculate the proportion of the x-axis covered by the vertical projection of two blocks. - - Args: - block1 (tuple): Coordinates of the first block (x0, y0, x1, y1). - block2 (tuple): Coordinates of the second block (x0, y0, x1, y1). - - Returns: - float: The proportion of the x-axis covered by the vertical projection of the two blocks. - """ - x0_1, _, x1_1, _ = block1 - x0_2, _, x1_2, _ = block2 - - # Calculate the intersection of the x-coordinates - x_left = max(x0_1, x0_2) - x_right = min(x1_1, x1_2) - - if x_right < x_left: - return 0.0 - - # Length of the intersection - intersection_length = x_right - x_left - - # Length of the x-axis projection of the first block - block1_length = x1_1 - x0_1 - - if block1_length == 0: - return 0.0 - - # Proportion of the x-axis covered by the intersection - # logger.info(f"intersection_length: {intersection_length}, block1_length: {block1_length}") - return intersection_length / block1_length diff --git a/magic_pdf/libs/clean_memory.py b/magic_pdf/libs/clean_memory.py deleted file mode 100644 index 930b99eadb71463816d938936649d82905723bd0..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/clean_memory.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) Opendatalab. All rights reserved. -import torch -import gc - - -def clean_memory(device='cuda'): - if device == 'cuda': - if torch.cuda.is_available(): - torch.cuda.empty_cache() - torch.cuda.ipc_collect() - elif str(device).startswith("npu"): - import torch_npu - if torch_npu.npu.is_available(): - torch_npu.npu.empty_cache() - elif str(device).startswith("mps"): - torch.mps.empty_cache() - gc.collect() \ No newline at end of file diff --git a/magic_pdf/libs/commons.py b/magic_pdf/libs/commons.py deleted file mode 100644 index 20f29ffd309737cfd06f04fa0426eab1ceb4a4b9..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/commons.py +++ /dev/null @@ -1,43 +0,0 @@ - -def join_path(*args): - return '/'.join(str(s).rstrip('/') for s in args) - - -def get_top_percent_list(num_list, percent): - """ - 获取列表中前百分之多少的元素 - :param num_list: - :param percent: - :return: - """ - if len(num_list) == 0: - top_percent_list = [] - else: - # 对imgs_len_list排序 - sorted_imgs_len_list = sorted(num_list, reverse=True) - # 计算 percent 的索引 - top_percent_index = int(len(sorted_imgs_len_list) * percent) - # 取前80%的元素 - top_percent_list = sorted_imgs_len_list[:top_percent_index] - return top_percent_list - - -def mymax(alist: list): - if len(alist) == 0: - return 0 # 空是0, 0*0也是0大小q - else: - return max(alist) - - -def parse_bucket_key(s3_full_path: str): - """ - 输入 s3://bucket/path/to/my/file.txt - 输出 bucket, path/to/my/file.txt - """ - s3_full_path = s3_full_path.strip() - if s3_full_path.startswith("s3://"): - s3_full_path = s3_full_path[5:] - if s3_full_path.startswith("/"): - s3_full_path = s3_full_path[1:] - bucket, key = s3_full_path.split("/", 1) - return bucket, key diff --git a/magic_pdf/libs/config_reader.py b/magic_pdf/libs/config_reader.py deleted file mode 100644 index 2b7e949621a606e4f8a83865945c501056fbefb6..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/config_reader.py +++ /dev/null @@ -1,139 +0,0 @@ -"""根据bucket的名字返回对应的s3 AK, SK,endpoint三元组.""" - -import json -import os - -from loguru import logger - -from magic_pdf.config.constants import MODEL_NAME -from magic_pdf.libs.commons import parse_bucket_key - -# 定义配置文件名常量 -CONFIG_FILE_NAME = os.getenv('MINERU_TOOLS_CONFIG_JSON', 'magic-pdf.json') - - -def read_config(): - if os.path.isabs(CONFIG_FILE_NAME): - config_file = CONFIG_FILE_NAME - else: - home_dir = os.path.expanduser('~') - config_file = os.path.join(home_dir, CONFIG_FILE_NAME) - - if not os.path.exists(config_file): - raise FileNotFoundError(f'{config_file} not found') - - with open(config_file, 'r', encoding='utf-8') as f: - config = json.load(f) - return config - - -def get_s3_config(bucket_name: str): - """~/magic-pdf.json 读出来.""" - config = read_config() - - bucket_info = config.get('bucket_info') - if bucket_name not in bucket_info: - access_key, secret_key, storage_endpoint = bucket_info['[default]'] - else: - access_key, secret_key, storage_endpoint = bucket_info[bucket_name] - - if access_key is None or secret_key is None or storage_endpoint is None: - raise Exception(f'ak, sk or endpoint not found in {CONFIG_FILE_NAME}') - - # logger.info(f"get_s3_config: ak={access_key}, sk={secret_key}, endpoint={storage_endpoint}") - - return access_key, secret_key, storage_endpoint - - -def get_s3_config_dict(path: str): - access_key, secret_key, storage_endpoint = get_s3_config(get_bucket_name(path)) - return {'ak': access_key, 'sk': secret_key, 'endpoint': storage_endpoint} - - -def get_bucket_name(path): - bucket, key = parse_bucket_key(path) - return bucket - - -def get_local_models_dir(): - config = read_config() - models_dir = config.get('models-dir') - if models_dir is None: - logger.warning(f"'models-dir' not found in {CONFIG_FILE_NAME}, use '/tmp/models' as default") - return '/tmp/models' - else: - return models_dir - - -def get_local_layoutreader_model_dir(): - config = read_config() - layoutreader_model_dir = config.get('layoutreader-model-dir') - if layoutreader_model_dir is None or not os.path.exists(layoutreader_model_dir): - home_dir = os.path.expanduser('~') - layoutreader_at_modelscope_dir_path = os.path.join(home_dir, '.cache/modelscope/hub/ppaanngggg/layoutreader') - logger.warning(f"'layoutreader-model-dir' not exists, use {layoutreader_at_modelscope_dir_path} as default") - return layoutreader_at_modelscope_dir_path - else: - return layoutreader_model_dir - - -def get_device(): - config = read_config() - device = config.get('device-mode') - if device is None: - logger.warning(f"'device-mode' not found in {CONFIG_FILE_NAME}, use 'cpu' as default") - return 'cpu' - else: - return device - - -def get_table_recog_config(): - config = read_config() - table_config = config.get('table-config') - if table_config is None: - logger.warning(f"'table-config' not found in {CONFIG_FILE_NAME}, use 'False' as default") - return json.loads(f'{{"model": "{MODEL_NAME.RAPID_TABLE}","enable": false, "max_time": 400}}') - else: - return table_config - - -def get_layout_config(): - config = read_config() - layout_config = config.get('layout-config') - if layout_config is None: - logger.warning(f"'layout-config' not found in {CONFIG_FILE_NAME}, use '{MODEL_NAME.LAYOUTLMv3}' as default") - return json.loads(f'{{"model": "{MODEL_NAME.LAYOUTLMv3}"}}') - else: - return layout_config - - -def get_formula_config(): - config = read_config() - formula_config = config.get('formula-config') - if formula_config is None: - logger.warning(f"'formula-config' not found in {CONFIG_FILE_NAME}, use 'True' as default") - return json.loads(f'{{"mfd_model": "{MODEL_NAME.YOLO_V8_MFD}","mfr_model": "{MODEL_NAME.UniMerNet_v2_Small}","enable": true}}') - else: - return formula_config - -def get_llm_aided_config(): - config = read_config() - llm_aided_config = config.get('llm-aided-config') - if llm_aided_config is None: - logger.warning(f"'llm-aided-config' not found in {CONFIG_FILE_NAME}, use 'None' as default") - return None - else: - return llm_aided_config - -def get_latex_delimiter_config(): - config = read_config() - latex_delimiter_config = config.get('latex-delimiter-config') - if latex_delimiter_config is None: - logger.warning(f"'latex-delimiter-config' not found in {CONFIG_FILE_NAME}, use 'None' as default") - return None - else: - return latex_delimiter_config - - -if __name__ == '__main__': - ak, sk, endpoint = get_s3_config('llm-raw') diff --git a/magic_pdf/libs/convert_utils.py b/magic_pdf/libs/convert_utils.py deleted file mode 100644 index 99a1879d46befa2de63aa1a379ab83dbf6fdb1f1..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/convert_utils.py +++ /dev/null @@ -1,5 +0,0 @@ -def dict_to_list(input_dict): - items_list = [] - for _, item in input_dict.items(): - items_list.append(item) - return items_list diff --git a/magic_pdf/libs/coordinate_transform.py b/magic_pdf/libs/coordinate_transform.py deleted file mode 100644 index 7cd7a0768596174d71ea8b3c8309c0ec998b3c81..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/coordinate_transform.py +++ /dev/null @@ -1,9 +0,0 @@ -def get_scale_ratio(model_page_info, page): - pix = page.get_pixmap(dpi=72) - pymu_width = int(pix.w) - pymu_height = int(pix.h) - width_from_json = model_page_info['page_info']['width'] - height_from_json = model_page_info['page_info']['height'] - horizontal_scale_ratio = width_from_json / pymu_width - vertical_scale_ratio = height_from_json / pymu_height - return horizontal_scale_ratio, vertical_scale_ratio diff --git a/magic_pdf/libs/draw_bbox.py b/magic_pdf/libs/draw_bbox.py deleted file mode 100644 index c2ad21d091cff9c2d3026f97da486129b6b34edf..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/draw_bbox.py +++ /dev/null @@ -1,418 +0,0 @@ -import fitz -from magic_pdf.config.constants import CROSS_PAGE -from magic_pdf.config.ocr_content_type import (BlockType, CategoryId, - ContentType) -from magic_pdf.data.dataset import Dataset -from magic_pdf.model.magic_model import MagicModel - - -def draw_bbox_without_number(i, bbox_list, page, rgb_config, fill_config): - new_rgb = [] - for item in rgb_config: - item = float(item) / 255 - new_rgb.append(item) - page_data = bbox_list[i] - for bbox in page_data: - x0, y0, x1, y1 = bbox - rect_coords = fitz.Rect(x0, y0, x1, y1) # Define the rectangle - if fill_config: - page.draw_rect( - rect_coords, - color=None, - fill=new_rgb, - fill_opacity=0.3, - width=0.5, - overlay=True, - ) # Draw the rectangle - else: - page.draw_rect( - rect_coords, - color=new_rgb, - fill=None, - fill_opacity=1, - width=0.5, - overlay=True, - ) # Draw the rectangle - - -def draw_bbox_with_number(i, bbox_list, page, rgb_config, fill_config, draw_bbox=True): - new_rgb = [] - for item in rgb_config: - item = float(item) / 255 - new_rgb.append(item) - page_data = bbox_list[i] - for j, bbox in enumerate(page_data): - x0, y0, x1, y1 = bbox - rect_coords = fitz.Rect(x0, y0, x1, y1) # Define the rectangle - if draw_bbox: - if fill_config: - page.draw_rect( - rect_coords, - color=None, - fill=new_rgb, - fill_opacity=0.3, - width=0.5, - overlay=True, - ) # Draw the rectangle - else: - page.draw_rect( - rect_coords, - color=new_rgb, - fill=None, - fill_opacity=1, - width=0.5, - overlay=True, - ) # Draw the rectangle - page.insert_text( - (x1 + 2, y0 + 10), str(j + 1), fontsize=10, color=new_rgb - ) # Insert the index in the top left corner of the rectangle - - -def draw_layout_bbox(pdf_info, pdf_bytes, out_path, filename): - dropped_bbox_list = [] - tables_list, tables_body_list = [], [] - tables_caption_list, tables_footnote_list = [], [] - imgs_list, imgs_body_list, imgs_caption_list = [], [], [] - imgs_footnote_list = [] - titles_list = [] - texts_list = [] - interequations_list = [] - lists_list = [] - indexs_list = [] - for page in pdf_info: - - page_dropped_list = [] - tables, tables_body, tables_caption, tables_footnote = [], [], [], [] - imgs, imgs_body, imgs_caption, imgs_footnote = [], [], [], [] - titles = [] - texts = [] - interequations = [] - lists = [] - indices = [] - - for dropped_bbox in page['discarded_blocks']: - page_dropped_list.append(dropped_bbox['bbox']) - dropped_bbox_list.append(page_dropped_list) - for block in page['para_blocks']: - bbox = block['bbox'] - if block['type'] == BlockType.Table: - tables.append(bbox) - for nested_block in block['blocks']: - bbox = nested_block['bbox'] - if nested_block['type'] == BlockType.TableBody: - tables_body.append(bbox) - elif nested_block['type'] == BlockType.TableCaption: - tables_caption.append(bbox) - elif nested_block['type'] == BlockType.TableFootnote: - tables_footnote.append(bbox) - elif block['type'] == BlockType.Image: - imgs.append(bbox) - for nested_block in block['blocks']: - bbox = nested_block['bbox'] - if nested_block['type'] == BlockType.ImageBody: - imgs_body.append(bbox) - elif nested_block['type'] == BlockType.ImageCaption: - imgs_caption.append(bbox) - elif nested_block['type'] == BlockType.ImageFootnote: - imgs_footnote.append(bbox) - elif block['type'] == BlockType.Title: - titles.append(bbox) - elif block['type'] == BlockType.Text: - texts.append(bbox) - elif block['type'] == BlockType.InterlineEquation: - interequations.append(bbox) - elif block['type'] == BlockType.List: - lists.append(bbox) - elif block['type'] == BlockType.Index: - indices.append(bbox) - - tables_list.append(tables) - tables_body_list.append(tables_body) - tables_caption_list.append(tables_caption) - tables_footnote_list.append(tables_footnote) - imgs_list.append(imgs) - imgs_body_list.append(imgs_body) - imgs_caption_list.append(imgs_caption) - imgs_footnote_list.append(imgs_footnote) - titles_list.append(titles) - texts_list.append(texts) - interequations_list.append(interequations) - lists_list.append(lists) - indexs_list.append(indices) - - layout_bbox_list = [] - - table_type_order = { - 'table_caption': 1, - 'table_body': 2, - 'table_footnote': 3 - } - for page in pdf_info: - page_block_list = [] - for block in page['para_blocks']: - if block['type'] in [ - BlockType.Text, - BlockType.Title, - BlockType.InterlineEquation, - BlockType.List, - BlockType.Index, - ]: - bbox = block['bbox'] - page_block_list.append(bbox) - elif block['type'] in [BlockType.Image]: - for sub_block in block['blocks']: - bbox = sub_block['bbox'] - page_block_list.append(bbox) - elif block['type'] in [BlockType.Table]: - sorted_blocks = sorted(block['blocks'], key=lambda x: table_type_order[x['type']]) - for sub_block in sorted_blocks: - bbox = sub_block['bbox'] - page_block_list.append(bbox) - - layout_bbox_list.append(page_block_list) - - pdf_docs = fitz.open('pdf', pdf_bytes) - - for i, page in enumerate(pdf_docs): - - draw_bbox_without_number(i, dropped_bbox_list, page, [158, 158, 158], True) - # draw_bbox_without_number(i, tables_list, page, [153, 153, 0], True) # color ! - draw_bbox_without_number(i, tables_body_list, page, [204, 204, 0], True) - draw_bbox_without_number(i, tables_caption_list, page, [255, 255, 102], True) - draw_bbox_without_number(i, tables_footnote_list, page, [229, 255, 204], True) - # draw_bbox_without_number(i, imgs_list, page, [51, 102, 0], True) - draw_bbox_without_number(i, imgs_body_list, page, [153, 255, 51], True) - draw_bbox_without_number(i, imgs_caption_list, page, [102, 178, 255], True) - draw_bbox_without_number(i, imgs_footnote_list, page, [255, 178, 102], True), - draw_bbox_without_number(i, titles_list, page, [102, 102, 255], True) - draw_bbox_without_number(i, texts_list, page, [153, 0, 76], True) - draw_bbox_without_number(i, interequations_list, page, [0, 255, 0], True) - draw_bbox_without_number(i, lists_list, page, [40, 169, 92], True) - draw_bbox_without_number(i, indexs_list, page, [40, 169, 92], True) - - draw_bbox_with_number( - i, layout_bbox_list, page, [255, 0, 0], False, draw_bbox=False - ) - - # Save the PDF - pdf_docs.save(f'{out_path}/{filename}') - - -def draw_span_bbox(pdf_info, pdf_bytes, out_path, filename): - text_list = [] - inline_equation_list = [] - interline_equation_list = [] - image_list = [] - table_list = [] - dropped_list = [] - next_page_text_list = [] - next_page_inline_equation_list = [] - - def get_span_info(span): - if span['type'] == ContentType.Text: - if span.get(CROSS_PAGE, False): - next_page_text_list.append(span['bbox']) - else: - page_text_list.append(span['bbox']) - elif span['type'] == ContentType.InlineEquation: - if span.get(CROSS_PAGE, False): - next_page_inline_equation_list.append(span['bbox']) - else: - page_inline_equation_list.append(span['bbox']) - elif span['type'] == ContentType.InterlineEquation: - page_interline_equation_list.append(span['bbox']) - elif span['type'] == ContentType.Image: - page_image_list.append(span['bbox']) - elif span['type'] == ContentType.Table: - page_table_list.append(span['bbox']) - - for page in pdf_info: - page_text_list = [] - page_inline_equation_list = [] - page_interline_equation_list = [] - page_image_list = [] - page_table_list = [] - page_dropped_list = [] - - # 将跨页的span放到移动到下一页的列表中 - if len(next_page_text_list) > 0: - page_text_list.extend(next_page_text_list) - next_page_text_list.clear() - if len(next_page_inline_equation_list) > 0: - page_inline_equation_list.extend(next_page_inline_equation_list) - next_page_inline_equation_list.clear() - - # 构造dropped_list - for block in page['discarded_blocks']: - if block['type'] == BlockType.Discarded: - for line in block['lines']: - for span in line['spans']: - page_dropped_list.append(span['bbox']) - dropped_list.append(page_dropped_list) - # 构造其余useful_list - # for block in page['para_blocks']: # span直接用分段合并前的结果就可以 - for block in page['preproc_blocks']: - if block['type'] in [ - BlockType.Text, - BlockType.Title, - BlockType.InterlineEquation, - BlockType.List, - BlockType.Index, - ]: - for line in block['lines']: - for span in line['spans']: - get_span_info(span) - elif block['type'] in [BlockType.Image, BlockType.Table]: - for sub_block in block['blocks']: - for line in sub_block['lines']: - for span in line['spans']: - get_span_info(span) - text_list.append(page_text_list) - inline_equation_list.append(page_inline_equation_list) - interline_equation_list.append(page_interline_equation_list) - image_list.append(page_image_list) - table_list.append(page_table_list) - pdf_docs = fitz.open('pdf', pdf_bytes) - for i, page in enumerate(pdf_docs): - # 获取当前页面的数据 - draw_bbox_without_number(i, text_list, page, [255, 0, 0], False) - draw_bbox_without_number(i, inline_equation_list, page, [0, 255, 0], False) - draw_bbox_without_number(i, interline_equation_list, page, [0, 0, 255], False) - draw_bbox_without_number(i, image_list, page, [255, 204, 0], False) - draw_bbox_without_number(i, table_list, page, [204, 0, 255], False) - draw_bbox_without_number(i, dropped_list, page, [158, 158, 158], False) - - # Save the PDF - pdf_docs.save(f'{out_path}/{filename}') - - -def draw_model_bbox(model_list, dataset: Dataset, out_path, filename): - dropped_bbox_list = [] - tables_body_list, tables_caption_list, tables_footnote_list = [], [], [] - imgs_body_list, imgs_caption_list, imgs_footnote_list = [], [], [] - titles_list = [] - texts_list = [] - interequations_list = [] - magic_model = MagicModel(model_list, dataset) - for i in range(len(model_list)): - page_dropped_list = [] - tables_body, tables_caption, tables_footnote = [], [], [] - imgs_body, imgs_caption, imgs_footnote = [], [], [] - titles = [] - texts = [] - interequations = [] - page_info = magic_model.get_model_list(i) - layout_dets = page_info['layout_dets'] - for layout_det in layout_dets: - bbox = layout_det['bbox'] - if layout_det['category_id'] == CategoryId.Text: - texts.append(bbox) - elif layout_det['category_id'] == CategoryId.Title: - titles.append(bbox) - elif layout_det['category_id'] == CategoryId.TableBody: - tables_body.append(bbox) - elif layout_det['category_id'] == CategoryId.TableCaption: - tables_caption.append(bbox) - elif layout_det['category_id'] == CategoryId.TableFootnote: - tables_footnote.append(bbox) - elif layout_det['category_id'] == CategoryId.ImageBody: - imgs_body.append(bbox) - elif layout_det['category_id'] == CategoryId.ImageCaption: - imgs_caption.append(bbox) - elif layout_det['category_id'] == CategoryId.InterlineEquation_YOLO: - interequations.append(bbox) - elif layout_det['category_id'] == CategoryId.Abandon: - page_dropped_list.append(bbox) - elif layout_det['category_id'] == CategoryId.ImageFootnote: - imgs_footnote.append(bbox) - - tables_body_list.append(tables_body) - tables_caption_list.append(tables_caption) - tables_footnote_list.append(tables_footnote) - imgs_body_list.append(imgs_body) - imgs_caption_list.append(imgs_caption) - titles_list.append(titles) - texts_list.append(texts) - interequations_list.append(interequations) - dropped_bbox_list.append(page_dropped_list) - imgs_footnote_list.append(imgs_footnote) - - for i in range(len(dataset)): - page = dataset.get_page(i) - draw_bbox_with_number( - i, dropped_bbox_list, page, [158, 158, 158], True - ) # color ! - draw_bbox_with_number(i, tables_body_list, page, [204, 204, 0], True) - draw_bbox_with_number(i, tables_caption_list, page, [255, 255, 102], True) - draw_bbox_with_number(i, tables_footnote_list, page, [229, 255, 204], True) - draw_bbox_with_number(i, imgs_body_list, page, [153, 255, 51], True) - draw_bbox_with_number(i, imgs_caption_list, page, [102, 178, 255], True) - draw_bbox_with_number(i, imgs_footnote_list, page, [255, 178, 102], True) - draw_bbox_with_number(i, titles_list, page, [102, 102, 255], True) - draw_bbox_with_number(i, texts_list, page, [153, 0, 76], True) - draw_bbox_with_number(i, interequations_list, page, [0, 255, 0], True) - - # Save the PDF - dataset.dump_to_file(f'{out_path}/{filename}') - - -def draw_line_sort_bbox(pdf_info, pdf_bytes, out_path, filename): - layout_bbox_list = [] - - for page in pdf_info: - page_line_list = [] - for block in page['preproc_blocks']: - if block['type'] in [BlockType.Text]: - for line in block['lines']: - bbox = line['bbox'] - index = line['index'] - page_line_list.append({'index': index, 'bbox': bbox}) - elif block['type'] in [BlockType.Title, BlockType.InterlineEquation]: - if 'virtual_lines' in block: - if len(block['virtual_lines']) > 0 and block['virtual_lines'][0].get('index', None) is not None: - for line in block['virtual_lines']: - bbox = line['bbox'] - index = line['index'] - page_line_list.append({'index': index, 'bbox': bbox}) - else: - for line in block['lines']: - bbox = line['bbox'] - index = line['index'] - page_line_list.append({'index': index, 'bbox': bbox}) - elif block['type'] in [BlockType.Image, BlockType.Table]: - for sub_block in block['blocks']: - if sub_block['type'] in [BlockType.ImageBody, BlockType.TableBody]: - if len(sub_block['virtual_lines']) > 0 and sub_block['virtual_lines'][0].get('index', None) is not None: - for line in sub_block['virtual_lines']: - bbox = line['bbox'] - index = line['index'] - page_line_list.append({'index': index, 'bbox': bbox}) - else: - for line in sub_block['lines']: - bbox = line['bbox'] - index = line['index'] - page_line_list.append({'index': index, 'bbox': bbox}) - elif sub_block['type'] in [BlockType.ImageCaption, BlockType.TableCaption, BlockType.ImageFootnote, BlockType.TableFootnote]: - for line in sub_block['lines']: - bbox = line['bbox'] - index = line['index'] - page_line_list.append({'index': index, 'bbox': bbox}) - sorted_bboxes = sorted(page_line_list, key=lambda x: x['index']) - layout_bbox_list.append(sorted_bbox['bbox'] for sorted_bbox in sorted_bboxes) - pdf_docs = fitz.open('pdf', pdf_bytes) - for i, page in enumerate(pdf_docs): - draw_bbox_with_number(i, layout_bbox_list, page, [255, 0, 0], False) - - pdf_docs.save(f'{out_path}/{filename}') - - -def draw_char_bbox(pdf_bytes, out_path, filename): - pdf_docs = fitz.open('pdf', pdf_bytes) - for i, page in enumerate(pdf_docs): - for block in page.get_text('rawdict', flags=fitz.TEXT_PRESERVE_LIGATURES | fitz.TEXT_PRESERVE_WHITESPACE | fitz.TEXT_MEDIABOX_CLIP)['blocks']: - for line in block['lines']: - for span in line['spans']: - for char in span['chars']: - char_bbox = char['bbox'] - page.draw_rect(char_bbox, color=[1, 0, 0], fill=None, fill_opacity=1, width=0.3, overlay=True,) - pdf_docs.save(f'{out_path}/{filename}') diff --git a/magic_pdf/libs/hash_utils.py b/magic_pdf/libs/hash_utils.py deleted file mode 100644 index 47b8aea746eb04eeb427b775227692ef6b4d9d29..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/hash_utils.py +++ /dev/null @@ -1,15 +0,0 @@ -import hashlib - - -def compute_md5(file_bytes): - hasher = hashlib.md5() - hasher.update(file_bytes) - return hasher.hexdigest().upper() - - -def compute_sha256(input_string): - hasher = hashlib.sha256() - # 在Python3中,需要将字符串转化为字节对象才能被哈希函数处理 - input_bytes = input_string.encode('utf-8') - hasher.update(input_bytes) - return hasher.hexdigest() diff --git a/magic_pdf/libs/json_compressor.py b/magic_pdf/libs/json_compressor.py deleted file mode 100644 index 77ef1c876fcae0b34a42355b3edb079bb5dd891b..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/json_compressor.py +++ /dev/null @@ -1,27 +0,0 @@ -import json -import brotli -import base64 - -class JsonCompressor: - - @staticmethod - def compress_json(data): - """ - Compress a json object and encode it with base64 - """ - json_str = json.dumps(data) - json_bytes = json_str.encode('utf-8') - compressed = brotli.compress(json_bytes, quality=6) - compressed_str = base64.b64encode(compressed).decode('utf-8') # convert bytes to string - return compressed_str - - @staticmethod - def decompress_json(compressed_str): - """ - Decode the base64 string and decompress the json object - """ - compressed = base64.b64decode(compressed_str.encode('utf-8')) # convert string to bytes - decompressed_bytes = brotli.decompress(compressed) - json_str = decompressed_bytes.decode('utf-8') - data = json.loads(json_str) - return data diff --git a/magic_pdf/libs/local_math.py b/magic_pdf/libs/local_math.py deleted file mode 100644 index 9edbcc7074dfa189a8508eb76366ae31dba4d665..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/local_math.py +++ /dev/null @@ -1,9 +0,0 @@ -def float_gt(a, b): - if 0.0001 >= abs(a -b): - return False - return a > b - -def float_equal(a, b): - if 0.0001 >= abs(a-b): - return True - return False \ No newline at end of file diff --git a/magic_pdf/libs/markdown_utils.py b/magic_pdf/libs/markdown_utils.py deleted file mode 100644 index 036232c880b584573a4cd031fed4f457d8d63e6f..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/markdown_utils.py +++ /dev/null @@ -1,10 +0,0 @@ - -def ocr_escape_special_markdown_char(content): - """ - 转义正文里对markdown语法有特殊意义的字符 - """ - special_chars = ["*", "`", "~", "$"] - for char in special_chars: - content = content.replace(char, "\\" + char) - - return content diff --git a/magic_pdf/libs/pdf_check.py b/magic_pdf/libs/pdf_check.py deleted file mode 100644 index 98402b383b74800817a0770cb495e280a52b5e6c..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/pdf_check.py +++ /dev/null @@ -1,99 +0,0 @@ -import fitz -import numpy as np -from loguru import logger -import re -from io import BytesIO -from pdfminer.high_level import extract_text -from pdfminer.layout import LAParams - - -def calculate_sample_count(total_page: int): - """ - 根据总页数和采样率计算采样页面的数量。 - """ - select_page_cnt = min(10, total_page) - return select_page_cnt - - -def extract_pages(src_pdf_bytes: bytes) -> fitz.Document: - pdf_docs = fitz.open("pdf", src_pdf_bytes) - total_page = len(pdf_docs) - if total_page == 0: - # 如果PDF没有页面,直接返回空文档 - logger.warning("PDF is empty, return empty document") - return fitz.Document() - select_page_cnt = calculate_sample_count(total_page) - - page_num = np.random.choice(total_page, select_page_cnt, replace=False) - sample_docs = fitz.Document() - try: - for index in page_num: - sample_docs.insert_pdf(pdf_docs, from_page=int(index), to_page=int(index)) - except Exception as e: - logger.exception(e) - return sample_docs - - -def detect_invalid_chars(src_pdf_bytes: bytes) -> bool: - """" - 检测PDF中是否包含非法字符 - """ - '''pdfminer比较慢,需要先随机抽取10页左右的sample''' - sample_docs = extract_pages(src_pdf_bytes) - sample_pdf_bytes = sample_docs.tobytes() - sample_pdf_file_like_object = BytesIO(sample_pdf_bytes) - laparams = LAParams( - line_overlap=0.5, - char_margin=2.0, - line_margin=0.5, - word_margin=0.1, - boxes_flow=None, - detect_vertical=False, - all_texts=False, - ) - text = extract_text(pdf_file=sample_pdf_file_like_object, laparams=laparams) - text = text.replace("\n", "") - # logger.info(text) - '''乱码文本用pdfminer提取出来的文本特征是(cid:xxx)''' - cid_pattern = re.compile(r'\(cid:\d+\)') - matches = cid_pattern.findall(text) - cid_count = len(matches) - cid_len = sum(len(match) for match in matches) - text_len = len(text) - if text_len == 0: - cid_chars_radio = 0 - else: - cid_chars_radio = cid_count/(cid_count + text_len - cid_len) - logger.info(f"cid_count: {cid_count}, text_len: {text_len}, cid_chars_radio: {cid_chars_radio}") - '''当一篇文章存在5%以上的文本是乱码时,认为该文档为乱码文档''' - if cid_chars_radio > 0.05: - return False # 乱码文档 - else: - return True # 正常文档 - - -def count_replacement_characters(text: str) -> int: - """ - 统计字符串中 0xfffd 字符的数量。 - """ - return text.count('\ufffd') - - -def detect_invalid_chars_by_pymupdf(src_pdf_bytes: bytes) -> bool: - sample_docs = extract_pages(src_pdf_bytes) - doc_text = "" - for page in sample_docs: - page_text = page.get_text('text', flags=fitz.TEXT_PRESERVE_WHITESPACE | fitz.TEXT_MEDIABOX_CLIP) - doc_text += page_text - text_len = len(doc_text) - uffd_count = count_replacement_characters(doc_text) - if text_len == 0: - uffd_chars_radio = 0 - else: - uffd_chars_radio = uffd_count / text_len - logger.info(f"uffd_count: {uffd_count}, text_len: {text_len}, uffd_chars_radio: {uffd_chars_radio}") - '''当一篇文章存在1%以上的文本是乱码时,认为该文档为乱码文档''' - if uffd_chars_radio > 0.01: - return False # 乱码文档 - else: - return True # 正常文档 \ No newline at end of file diff --git a/magic_pdf/libs/pdf_image_tools.py b/magic_pdf/libs/pdf_image_tools.py deleted file mode 100644 index 80201167da768f8f182c1d0eb2ae10771d96caa9..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/pdf_image_tools.py +++ /dev/null @@ -1,63 +0,0 @@ -from io import BytesIO -import cv2 -import fitz -import numpy as np -from PIL import Image -from magic_pdf.data.data_reader_writer import DataWriter -from magic_pdf.libs.commons import join_path -from magic_pdf.libs.hash_utils import compute_sha256 - - -def cut_image(bbox: tuple, page_num: int, page: fitz.Page, return_path, imageWriter: DataWriter): - """从第page_num页的page中,根据bbox进行裁剪出一张jpg图片,返回图片路径 save_path:需要同时支持s3和本地, - 图片存放在save_path下,文件名是: - {page_num}_{bbox[0]}_{bbox[1]}_{bbox[2]}_{bbox[3]}.jpg , bbox内数字取整。""" - # 拼接文件名 - filename = f'{page_num}_{int(bbox[0])}_{int(bbox[1])}_{int(bbox[2])}_{int(bbox[3])}' - - # 老版本返回不带bucket的路径 - img_path = join_path(return_path, filename) if return_path is not None else None - - # 新版本生成平铺路径 - img_hash256_path = f'{compute_sha256(img_path)}.jpg' - - # 将坐标转换为fitz.Rect对象 - rect = fitz.Rect(*bbox) - # 配置缩放倍数为3倍 - zoom = fitz.Matrix(3, 3) - # 截取图片 - pix = page.get_pixmap(clip=rect, matrix=zoom) - - byte_data = pix.tobytes(output='jpeg', jpg_quality=95) - - imageWriter.write(img_hash256_path, byte_data) - - return img_hash256_path - - -def cut_image_to_pil_image(bbox: tuple, page: fitz.Page, mode="pillow"): - - # 将坐标转换为fitz.Rect对象 - rect = fitz.Rect(*bbox) - # 配置缩放倍数为3倍 - zoom = fitz.Matrix(3, 3) - # 截取图片 - pix = page.get_pixmap(clip=rect, matrix=zoom) - - if mode == "cv2": - # 直接转换为numpy数组供cv2使用 - img_array = np.frombuffer(pix.samples, dtype=np.uint8).reshape(pix.height, pix.width, pix.n) - # PyMuPDF使用RGB顺序,而cv2使用BGR顺序 - if pix.n == 3 or pix.n == 4: - image_result = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR) - else: - image_result = img_array - elif mode == "pillow": - # 将字节数据转换为文件对象 - image_file = BytesIO(pix.tobytes(output='png')) - # 使用 Pillow 打开图像 - image_result = Image.open(image_file) - else: - raise ValueError(f"mode: {mode} is not supported.") - - return image_result \ No newline at end of file diff --git a/magic_pdf/libs/performance_stats.py b/magic_pdf/libs/performance_stats.py deleted file mode 100644 index 3aeaeb33cb6832c35fea5520a78cf31626c4270c..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/performance_stats.py +++ /dev/null @@ -1,65 +0,0 @@ -import time -import functools -from collections import defaultdict -from typing import Dict, List - - -class PerformanceStats: - """性能统计类,用于收集和展示方法执行时间""" - - _stats: Dict[str, List[float]] = defaultdict(list) - - @classmethod - def add_execution_time(cls, func_name: str, execution_time: float): - """添加执行时间记录""" - cls._stats[func_name].append(execution_time) - - @classmethod - def get_stats(cls) -> Dict[str, dict]: - """获取统计结果""" - results = {} - for func_name, times in cls._stats.items(): - results[func_name] = { - 'count': len(times), - 'total_time': sum(times), - 'avg_time': sum(times) / len(times), - 'min_time': min(times), - 'max_time': max(times) - } - return results - - @classmethod - def print_stats(cls): - """打印统计结果""" - stats = cls.get_stats() - print("\n性能统计结果:") - print("-" * 80) - print(f"{'方法名':<40} {'调用次数':>8} {'总时间(s)':>12} {'平均时间(s)':>12}") - print("-" * 80) - for func_name, data in stats.items(): - print(f"{func_name:<40} {data['count']:8d} {data['total_time']:12.6f} {data['avg_time']:12.6f}") - - -def measure_time(func): - """测量方法执行时间的装饰器""" - - @functools.wraps(func) - def wrapper(*args, **kwargs): - start_time = time.time() - result = func(*args, **kwargs) - execution_time = time.time() - start_time - - # 获取更详细的函数标识 - if hasattr(func, "__self__"): # 实例方法 - class_name = func.__self__.__class__.__name__ - full_name = f"{class_name}.{func.__name__}" - elif hasattr(func, "__qualname__"): # 类方法或静态方法 - full_name = func.__qualname__ - else: - module_name = func.__module__ - full_name = f"{module_name}.{func.__name__}" - - PerformanceStats.add_execution_time(full_name, execution_time) - return result - - return wrapper \ No newline at end of file diff --git a/magic_pdf/libs/safe_filename.py b/magic_pdf/libs/safe_filename.py deleted file mode 100644 index 1076a4bae218e180351ef2ec4692f156e03be1c7..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/safe_filename.py +++ /dev/null @@ -1,11 +0,0 @@ -import os - - -def sanitize_filename(filename, replacement="_"): - if os.name == 'nt': - invalid_chars = '<>:"|?*' - - for char in invalid_chars: - filename = filename.replace(char, replacement) - - return filename diff --git a/magic_pdf/libs/version.py b/magic_pdf/libs/version.py deleted file mode 100644 index c45d9dbf3a2fb0a83065d719614b463df244d2b3..0000000000000000000000000000000000000000 --- a/magic_pdf/libs/version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "1.3.12" diff --git a/magic_pdf/model/__init__.py b/magic_pdf/model/__init__.py deleted file mode 100644 index 859d01b33457ba56047073fdfefb9ef718cfa236..0000000000000000000000000000000000000000 --- a/magic_pdf/model/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -__use_inside_model__ = True -__model_mode__ = 'full' \ No newline at end of file diff --git a/magic_pdf/model/batch_analyze.py b/magic_pdf/model/batch_analyze.py deleted file mode 100644 index be5e331fd801433fea2f41de317c9e1424649b00..0000000000000000000000000000000000000000 --- a/magic_pdf/model/batch_analyze.py +++ /dev/null @@ -1,265 +0,0 @@ -import time -import cv2 -from loguru import logger -from tqdm import tqdm - -from magic_pdf.config.constants import MODEL_NAME -from magic_pdf.model.sub_modules.model_init import AtomModelSingleton -from magic_pdf.model.sub_modules.model_utils import ( - clean_vram, crop_img, get_res_list_from_layout_res, get_coords_and_area) -from magic_pdf.model.sub_modules.ocr.paddleocr2pytorch.ocr_utils import ( - get_adjusted_mfdetrec_res, get_ocr_result_list) - -YOLO_LAYOUT_BASE_BATCH_SIZE = 1 -MFD_BASE_BATCH_SIZE = 1 -MFR_BASE_BATCH_SIZE = 16 - - -class BatchAnalyze: - def __init__(self, model_manager, batch_ratio: int, show_log, layout_model, formula_enable, table_enable): - self.model_manager = model_manager - self.batch_ratio = batch_ratio - self.show_log = show_log - self.layout_model = layout_model - self.formula_enable = formula_enable - self.table_enable = table_enable - - def __call__(self, images_with_extra_info: list) -> list: - if len(images_with_extra_info) == 0: - return [] - - images_layout_res = [] - layout_start_time = time.time() - self.model = self.model_manager.get_model( - ocr=True, - show_log=self.show_log, - lang = None, - layout_model = self.layout_model, - formula_enable = self.formula_enable, - table_enable = self.table_enable, - ) - - images = [image for image, _, _ in images_with_extra_info] - - if self.model.layout_model_name == MODEL_NAME.LAYOUTLMv3: - # layoutlmv3 - for image in images: - layout_res = self.model.layout_model(image, ignore_catids=[]) - images_layout_res.append(layout_res) - elif self.model.layout_model_name == MODEL_NAME.DocLayout_YOLO: - # doclayout_yolo - layout_images = [] - for image_index, image in enumerate(images): - layout_images.append(image) - - images_layout_res += self.model.layout_model.batch_predict( - # layout_images, self.batch_ratio * YOLO_LAYOUT_BASE_BATCH_SIZE - layout_images, YOLO_LAYOUT_BASE_BATCH_SIZE - ) - - # logger.info( - # f'layout time: {round(time.time() - layout_start_time, 2)}, image num: {len(images)}' - # ) - - if self.model.apply_formula: - # 公式检测 - mfd_start_time = time.time() - images_mfd_res = self.model.mfd_model.batch_predict( - # images, self.batch_ratio * MFD_BASE_BATCH_SIZE - images, MFD_BASE_BATCH_SIZE - ) - # logger.info( - # f'mfd time: {round(time.time() - mfd_start_time, 2)}, image num: {len(images)}' - # ) - - # 公式识别 - mfr_start_time = time.time() - images_formula_list = self.model.mfr_model.batch_predict( - images_mfd_res, - images, - batch_size=self.batch_ratio * MFR_BASE_BATCH_SIZE, - ) - mfr_count = 0 - for image_index in range(len(images)): - images_layout_res[image_index] += images_formula_list[image_index] - mfr_count += len(images_formula_list[image_index]) - # logger.info( - # f'mfr time: {round(time.time() - mfr_start_time, 2)}, image num: {mfr_count}' - # ) - - # 清理显存 - # clean_vram(self.model.device, vram_threshold=8) - - ocr_res_list_all_page = [] - table_res_list_all_page = [] - for index in range(len(images)): - _, ocr_enable, _lang = images_with_extra_info[index] - layout_res = images_layout_res[index] - np_array_img = images[index] - - ocr_res_list, table_res_list, single_page_mfdetrec_res = ( - get_res_list_from_layout_res(layout_res) - ) - - ocr_res_list_all_page.append({'ocr_res_list':ocr_res_list, - 'lang':_lang, - 'ocr_enable':ocr_enable, - 'np_array_img':np_array_img, - 'single_page_mfdetrec_res':single_page_mfdetrec_res, - 'layout_res':layout_res, - }) - - for table_res in table_res_list: - table_img, _ = crop_img(table_res, np_array_img) - table_res_list_all_page.append({'table_res':table_res, - 'lang':_lang, - 'table_img':table_img, - }) - - # 文本框检测 - det_start = time.time() - det_count = 0 - # for ocr_res_list_dict in ocr_res_list_all_page: - for ocr_res_list_dict in tqdm(ocr_res_list_all_page, desc="OCR-det Predict"): - # Process each area that requires OCR processing - _lang = ocr_res_list_dict['lang'] - # Get OCR results for this language's images - atom_model_manager = AtomModelSingleton() - ocr_model = atom_model_manager.get_atom_model( - atom_model_name='ocr', - ocr_show_log=False, - det_db_box_thresh=0.3, - lang=_lang - ) - for res in ocr_res_list_dict['ocr_res_list']: - new_image, useful_list = crop_img( - res, ocr_res_list_dict['np_array_img'], crop_paste_x=50, crop_paste_y=50 - ) - adjusted_mfdetrec_res = get_adjusted_mfdetrec_res( - ocr_res_list_dict['single_page_mfdetrec_res'], useful_list - ) - - # OCR-det - new_image = cv2.cvtColor(new_image, cv2.COLOR_RGB2BGR) - ocr_res = ocr_model.ocr( - new_image, mfd_res=adjusted_mfdetrec_res, rec=False - )[0] - - # Integration results - if ocr_res: - ocr_result_list = get_ocr_result_list(ocr_res, useful_list, ocr_res_list_dict['ocr_enable'], new_image, _lang) - - if res["category_id"] == 3: - # ocr_result_list中所有bbox的面积之和 - ocr_res_area = sum(get_coords_and_area(ocr_res_item)[4] for ocr_res_item in ocr_result_list if 'poly' in ocr_res_item) - # 求ocr_res_area和res的面积的比值 - res_area = get_coords_and_area(res)[4] - if res_area > 0: - ratio = ocr_res_area / res_area - if ratio > 0.25: - res["category_id"] = 1 - else: - continue - - ocr_res_list_dict['layout_res'].extend(ocr_result_list) - - # det_count += len(ocr_res_list_dict['ocr_res_list']) - # logger.info(f'ocr-det time: {round(time.time()-det_start, 2)}, image num: {det_count}') - - - # 表格识别 table recognition - if self.model.apply_table: - table_start = time.time() - # for table_res_list_dict in table_res_list_all_page: - for table_res_dict in tqdm(table_res_list_all_page, desc="Table Predict"): - _lang = table_res_dict['lang'] - atom_model_manager = AtomModelSingleton() - table_model = atom_model_manager.get_atom_model( - atom_model_name='table', - table_model_name='rapid_table', - table_model_path='', - table_max_time=400, - device='cpu', - lang=_lang, - table_sub_model_name='slanet_plus' - ) - html_code, table_cell_bboxes, logic_points, elapse = table_model.predict(table_res_dict['table_img']) - # 判断是否返回正常 - if html_code: - expected_ending = html_code.strip().endswith( - '' - ) or html_code.strip().endswith('') - if expected_ending: - table_res_dict['table_res']['html'] = html_code - else: - logger.warning( - 'table recognition processing fails, not found expected HTML table end' - ) - else: - logger.warning( - 'table recognition processing fails, not get html return' - ) - # logger.info(f'table time: {round(time.time() - table_start, 2)}, image num: {len(table_res_list_all_page)}') - - # Create dictionaries to store items by language - need_ocr_lists_by_lang = {} # Dict of lists for each language - img_crop_lists_by_lang = {} # Dict of lists for each language - - for layout_res in images_layout_res: - for layout_res_item in layout_res: - if layout_res_item['category_id'] in [15]: - if 'np_img' in layout_res_item and 'lang' in layout_res_item: - lang = layout_res_item['lang'] - - # Initialize lists for this language if not exist - if lang not in need_ocr_lists_by_lang: - need_ocr_lists_by_lang[lang] = [] - img_crop_lists_by_lang[lang] = [] - - # Add to the appropriate language-specific lists - need_ocr_lists_by_lang[lang].append(layout_res_item) - img_crop_lists_by_lang[lang].append(layout_res_item['np_img']) - - # Remove the fields after adding to lists - layout_res_item.pop('np_img') - layout_res_item.pop('lang') - - - if len(img_crop_lists_by_lang) > 0: - - # Process OCR by language - rec_time = 0 - rec_start = time.time() - total_processed = 0 - - # Process each language separately - for lang, img_crop_list in img_crop_lists_by_lang.items(): - if len(img_crop_list) > 0: - # Get OCR results for this language's images - atom_model_manager = AtomModelSingleton() - ocr_model = atom_model_manager.get_atom_model( - atom_model_name='ocr', - ocr_show_log=False, - det_db_box_thresh=0.3, - lang=lang - ) - ocr_res_list = ocr_model.ocr(img_crop_list, det=False, tqdm_enable=True)[0] - - # Verify we have matching counts - assert len(ocr_res_list) == len( - need_ocr_lists_by_lang[lang]), f'ocr_res_list: {len(ocr_res_list)}, need_ocr_list: {len(need_ocr_lists_by_lang[lang])} for lang: {lang}' - - # Process OCR results for this language - for index, layout_res_item in enumerate(need_ocr_lists_by_lang[lang]): - ocr_text, ocr_score = ocr_res_list[index] - layout_res_item['text'] = ocr_text - layout_res_item['score'] = float(f"{ocr_score:.3f}") - - total_processed += len(img_crop_list) - - rec_time += time.time() - rec_start - # logger.info(f'ocr-rec time: {round(rec_time, 2)}, total images processed: {total_processed}') - - - - return images_layout_res diff --git a/magic_pdf/model/doc_analyze_by_custom_model.py b/magic_pdf/model/doc_analyze_by_custom_model.py deleted file mode 100644 index 93eecc6892f0986823d0a84693c96145dc8b9fea..0000000000000000000000000000000000000000 --- a/magic_pdf/model/doc_analyze_by_custom_model.py +++ /dev/null @@ -1,301 +0,0 @@ -import os -import time - -import numpy as np -import torch - -os.environ['FLAGS_npu_jit_compile'] = '0' # 关闭paddle的jit编译 -os.environ['FLAGS_use_stride_kernel'] = '0' -os.environ['PYTORCH_ENABLE_MPS_FALLBACK'] = '1' # 让mps可以fallback -os.environ['NO_ALBUMENTATIONS_UPDATE'] = '1' # 禁止albumentations检查更新 - - -from loguru import logger - -from magic_pdf.model.sub_modules.model_utils import get_vram -from magic_pdf.config.enums import SupportedPdfParseMethod -import magic_pdf.model as model_config -from magic_pdf.data.dataset import Dataset -from magic_pdf.libs.clean_memory import clean_memory -from magic_pdf.libs.config_reader import (get_device, get_formula_config, - get_layout_config, - get_local_models_dir, - get_table_recog_config) -from magic_pdf.model.model_list import MODEL - -class ModelSingleton: - _instance = None - _models = {} - - def __new__(cls, *args, **kwargs): - if cls._instance is None: - cls._instance = super().__new__(cls) - return cls._instance - - def get_model( - self, - ocr: bool, - show_log: bool, - lang=None, - layout_model=None, - formula_enable=None, - table_enable=None, - ): - key = (ocr, show_log, lang, layout_model, formula_enable, table_enable) - if key not in self._models: - self._models[key] = custom_model_init( - ocr=ocr, - show_log=show_log, - lang=lang, - layout_model=layout_model, - formula_enable=formula_enable, - table_enable=table_enable, - ) - return self._models[key] - - -def custom_model_init( - ocr: bool = False, - show_log: bool = False, - lang=None, - layout_model=None, - formula_enable=None, - table_enable=None, -): - model = None - if model_config.__model_mode__ == 'lite': - logger.warning( - 'The Lite mode is provided for developers to conduct testing only, and the output quality is ' - 'not guaranteed to be reliable.' - ) - model = MODEL.Paddle - elif model_config.__model_mode__ == 'full': - model = MODEL.PEK - - if model_config.__use_inside_model__: - model_init_start = time.time() - if model == MODEL.Paddle: - from magic_pdf.model.pp_structure_v2 import CustomPaddleModel - - custom_model = CustomPaddleModel(ocr=ocr, show_log=show_log, lang=lang) - elif model == MODEL.PEK: - from magic_pdf.model.pdf_extract_kit import CustomPEKModel - - # 从配置文件读取model-dir和device - local_models_dir = get_local_models_dir() - device = get_device() - - layout_config = get_layout_config() - if layout_model is not None: - layout_config['model'] = layout_model - - formula_config = get_formula_config() - if formula_enable is not None: - formula_config['enable'] = formula_enable - - table_config = get_table_recog_config() - if table_enable is not None: - table_config['enable'] = table_enable - - model_input = { - 'ocr': ocr, - 'show_log': show_log, - 'models_dir': local_models_dir, - 'device': device, - 'table_config': table_config, - 'layout_config': layout_config, - 'formula_config': formula_config, - 'lang': lang, - } - - custom_model = CustomPEKModel(**model_input) - else: - logger.error('Not allow model_name!') - exit(1) - model_init_cost = time.time() - model_init_start - logger.info(f'model init cost: {model_init_cost}') - else: - logger.error('use_inside_model is False, not allow to use inside model') - exit(1) - - return custom_model - -def doc_analyze( - dataset: Dataset, - ocr: bool = False, - show_log: bool = False, - start_page_id=0, - end_page_id=None, - lang=None, - layout_model=None, - formula_enable=None, - table_enable=None, -): - end_page_id = ( - end_page_id - if end_page_id is not None and end_page_id >= 0 - else len(dataset) - 1 - ) - - MIN_BATCH_INFERENCE_SIZE = int(os.environ.get('MINERU_MIN_BATCH_INFERENCE_SIZE', 200)) - images = [] - page_wh_list = [] - for index in range(len(dataset)): - if start_page_id <= index <= end_page_id: - page_data = dataset.get_page(index) - img_dict = page_data.get_image() - images.append(img_dict['img']) - page_wh_list.append((img_dict['width'], img_dict['height'])) - - images_with_extra_info = [(images[index], ocr, dataset._lang) for index in range(len(images))] - - if len(images) >= MIN_BATCH_INFERENCE_SIZE: - batch_size = MIN_BATCH_INFERENCE_SIZE - batch_images = [images_with_extra_info[i:i+batch_size] for i in range(0, len(images_with_extra_info), batch_size)] - else: - batch_images = [images_with_extra_info] - - results = [] - processed_images_count = 0 - for index, batch_image in enumerate(batch_images): - processed_images_count += len(batch_image) - logger.info(f'Batch {index + 1}/{len(batch_images)}: {processed_images_count} pages/{len(images_with_extra_info)} pages') - result = may_batch_image_analyze(batch_image, ocr, show_log,layout_model, formula_enable, table_enable) - results.extend(result) - - model_json = [] - for index in range(len(dataset)): - if start_page_id <= index <= end_page_id: - result = results.pop(0) - page_width, page_height = page_wh_list.pop(0) - else: - result = [] - page_height = 0 - page_width = 0 - - page_info = {'page_no': index, 'width': page_width, 'height': page_height} - page_dict = {'layout_dets': result, 'page_info': page_info} - model_json.append(page_dict) - - from magic_pdf.operators.models import InferenceResult - return InferenceResult(model_json, dataset) - -def batch_doc_analyze( - datasets: list[Dataset], - parse_method: str = 'auto', - show_log: bool = False, - lang=None, - layout_model=None, - formula_enable=None, - table_enable=None, -): - MIN_BATCH_INFERENCE_SIZE = int(os.environ.get('MINERU_MIN_BATCH_INFERENCE_SIZE', 100)) - batch_size = MIN_BATCH_INFERENCE_SIZE - page_wh_list = [] - - images_with_extra_info = [] - for dataset in datasets: - - ocr = False - if parse_method == 'auto': - if dataset.classify() == SupportedPdfParseMethod.TXT: - ocr = False - elif dataset.classify() == SupportedPdfParseMethod.OCR: - ocr = True - elif parse_method == 'ocr': - ocr = True - elif parse_method == 'txt': - ocr = False - - _lang = dataset._lang - - for index in range(len(dataset)): - page_data = dataset.get_page(index) - img_dict = page_data.get_image() - page_wh_list.append((img_dict['width'], img_dict['height'])) - images_with_extra_info.append((img_dict['img'], ocr, _lang)) - - batch_images = [images_with_extra_info[i:i+batch_size] for i in range(0, len(images_with_extra_info), batch_size)] - results = [] - processed_images_count = 0 - for index, batch_image in enumerate(batch_images): - processed_images_count += len(batch_image) - logger.info(f'Batch {index + 1}/{len(batch_images)}: {processed_images_count} pages/{len(images_with_extra_info)} pages') - result = may_batch_image_analyze(batch_image, True, show_log, layout_model, formula_enable, table_enable) - results.extend(result) - - infer_results = [] - from magic_pdf.operators.models import InferenceResult - for index in range(len(datasets)): - dataset = datasets[index] - model_json = [] - for i in range(len(dataset)): - result = results.pop(0) - page_width, page_height = page_wh_list.pop(0) - page_info = {'page_no': i, 'width': page_width, 'height': page_height} - page_dict = {'layout_dets': result, 'page_info': page_info} - model_json.append(page_dict) - infer_results.append(InferenceResult(model_json, dataset)) - return infer_results - - -def may_batch_image_analyze( - images_with_extra_info: list[(np.ndarray, bool, str)], - ocr: bool, - show_log: bool = False, - layout_model=None, - formula_enable=None, - table_enable=None): - # os.environ['CUDA_VISIBLE_DEVICES'] = str(idx) - - from magic_pdf.model.batch_analyze import BatchAnalyze - - model_manager = ModelSingleton() - - # images = [image for image, _, _ in images_with_extra_info] - batch_ratio = 1 - device = get_device() - - if str(device).startswith('npu'): - import torch_npu - if torch_npu.npu.is_available(): - torch.npu.set_compile_mode(jit_compile=False) - - if str(device).startswith('npu') or str(device).startswith('cuda'): - vram = get_vram(device) - if vram is not None: - gpu_memory = int(os.getenv('VIRTUAL_VRAM_SIZE', round(vram))) - if gpu_memory >= 16: - batch_ratio = 16 - elif gpu_memory >= 12: - batch_ratio = 8 - elif gpu_memory >= 8: - batch_ratio = 4 - elif gpu_memory >= 6: - batch_ratio = 2 - else: - batch_ratio = 1 - logger.info(f'gpu_memory: {gpu_memory} GB, batch_ratio: {batch_ratio}') - else: - # Default batch_ratio when VRAM can't be determined - batch_ratio = 1 - logger.info(f'Could not determine GPU memory, using default batch_ratio: {batch_ratio}') - - - # doc_analyze_start = time.time() - - batch_model = BatchAnalyze(model_manager, batch_ratio, show_log, layout_model, formula_enable, table_enable) - results = batch_model(images_with_extra_info) - - # gc_start = time.time() - clean_memory(get_device()) - # gc_time = round(time.time() - gc_start, 2) - # logger.debug(f'gc time: {gc_time}') - - # doc_analyze_time = round(time.time() - doc_analyze_start, 2) - # doc_analyze_speed = round(len(images) / doc_analyze_time, 2) - # logger.debug( - # f'doc analyze time: {round(time.time() - doc_analyze_start, 2)},' - # f' speed: {doc_analyze_speed} pages/second' - # ) - return results \ No newline at end of file diff --git a/magic_pdf/model/magic_model.py b/magic_pdf/model/magic_model.py deleted file mode 100644 index b5922d35cf9622685bde3478d872476ca63d7487..0000000000000000000000000000000000000000 --- a/magic_pdf/model/magic_model.py +++ /dev/null @@ -1,771 +0,0 @@ -import enum - -from magic_pdf.config.model_block_type import ModelBlockTypeEnum -from magic_pdf.config.ocr_content_type import CategoryId, ContentType -from magic_pdf.data.dataset import Dataset -from magic_pdf.libs.boxbase import (_is_in, bbox_distance, bbox_relative_pos, - calculate_iou) -from magic_pdf.libs.coordinate_transform import get_scale_ratio -from magic_pdf.pre_proc.remove_bbox_overlap import _remove_overlap_between_bbox - -CAPATION_OVERLAP_AREA_RATIO = 0.6 -MERGE_BOX_OVERLAP_AREA_RATIO = 1.1 - - -class PosRelationEnum(enum.Enum): - LEFT = 'left' - RIGHT = 'right' - UP = 'up' - BOTTOM = 'bottom' - ALL = 'all' - - -class MagicModel: - """每个函数没有得到元素的时候返回空list.""" - - def __fix_axis(self): - for model_page_info in self.__model_list: - need_remove_list = [] - page_no = model_page_info['page_info']['page_no'] - horizontal_scale_ratio, vertical_scale_ratio = get_scale_ratio( - model_page_info, self.__docs.get_page(page_no) - ) - layout_dets = model_page_info['layout_dets'] - for layout_det in layout_dets: - - if layout_det.get('bbox') is not None: - # 兼容直接输出bbox的模型数据,如paddle - x0, y0, x1, y1 = layout_det['bbox'] - else: - # 兼容直接输出poly的模型数据,如xxx - x0, y0, _, _, x1, y1, _, _ = layout_det['poly'] - - bbox = [ - int(x0 / horizontal_scale_ratio), - int(y0 / vertical_scale_ratio), - int(x1 / horizontal_scale_ratio), - int(y1 / vertical_scale_ratio), - ] - layout_det['bbox'] = bbox - # 删除高度或者宽度小于等于0的spans - if bbox[2] - bbox[0] <= 0 or bbox[3] - bbox[1] <= 0: - need_remove_list.append(layout_det) - for need_remove in need_remove_list: - layout_dets.remove(need_remove) - - def __fix_by_remove_low_confidence(self): - for model_page_info in self.__model_list: - need_remove_list = [] - layout_dets = model_page_info['layout_dets'] - for layout_det in layout_dets: - if layout_det['score'] <= 0.05: - need_remove_list.append(layout_det) - else: - continue - for need_remove in need_remove_list: - layout_dets.remove(need_remove) - - def __fix_by_remove_high_iou_and_low_confidence(self): - for model_page_info in self.__model_list: - need_remove_list = [] - layout_dets = model_page_info['layout_dets'] - for layout_det1 in layout_dets: - for layout_det2 in layout_dets: - if layout_det1 == layout_det2: - continue - if layout_det1['category_id'] in [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - ] and layout_det2['category_id'] in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]: - if ( - calculate_iou(layout_det1['bbox'], layout_det2['bbox']) - > 0.9 - ): - if layout_det1['score'] < layout_det2['score']: - layout_det_need_remove = layout_det1 - else: - layout_det_need_remove = layout_det2 - - if layout_det_need_remove not in need_remove_list: - need_remove_list.append(layout_det_need_remove) - else: - continue - else: - continue - for need_remove in need_remove_list: - layout_dets.remove(need_remove) - - def __init__(self, model_list: list, docs: Dataset): - self.__model_list = model_list - self.__docs = docs - """为所有模型数据添加bbox信息(缩放,poly->bbox)""" - self.__fix_axis() - """删除置信度特别低的模型数据(<0.05),提高质量""" - self.__fix_by_remove_low_confidence() - """删除高iou(>0.9)数据中置信度较低的那个""" - self.__fix_by_remove_high_iou_and_low_confidence() - self.__fix_footnote() - - def _bbox_distance(self, bbox1, bbox2): - left, right, bottom, top = bbox_relative_pos(bbox1, bbox2) - flags = [left, right, bottom, top] - count = sum([1 if v else 0 for v in flags]) - if count > 1: - return float('inf') - if left or right: - l1 = bbox1[3] - bbox1[1] - l2 = bbox2[3] - bbox2[1] - else: - l1 = bbox1[2] - bbox1[0] - l2 = bbox2[2] - bbox2[0] - - if l2 > l1 and (l2 - l1) / l1 > 0.3: - return float('inf') - - return bbox_distance(bbox1, bbox2) - - def __fix_footnote(self): - # 3: figure, 5: table, 7: footnote - for model_page_info in self.__model_list: - footnotes = [] - figures = [] - tables = [] - - for obj in model_page_info['layout_dets']: - if obj['category_id'] == 7: - footnotes.append(obj) - elif obj['category_id'] == 3: - figures.append(obj) - elif obj['category_id'] == 5: - tables.append(obj) - if len(footnotes) * len(figures) == 0: - continue - dis_figure_footnote = {} - dis_table_footnote = {} - - for i in range(len(footnotes)): - for j in range(len(figures)): - pos_flag_count = sum( - list( - map( - lambda x: 1 if x else 0, - bbox_relative_pos( - footnotes[i]['bbox'], figures[j]['bbox'] - ), - ) - ) - ) - if pos_flag_count > 1: - continue - dis_figure_footnote[i] = min( - self._bbox_distance(figures[j]['bbox'], footnotes[i]['bbox']), - dis_figure_footnote.get(i, float('inf')), - ) - for i in range(len(footnotes)): - for j in range(len(tables)): - pos_flag_count = sum( - list( - map( - lambda x: 1 if x else 0, - bbox_relative_pos( - footnotes[i]['bbox'], tables[j]['bbox'] - ), - ) - ) - ) - if pos_flag_count > 1: - continue - - dis_table_footnote[i] = min( - self._bbox_distance(tables[j]['bbox'], footnotes[i]['bbox']), - dis_table_footnote.get(i, float('inf')), - ) - for i in range(len(footnotes)): - if i not in dis_figure_footnote: - continue - if dis_table_footnote.get(i, float('inf')) > dis_figure_footnote[i]: - footnotes[i]['category_id'] = CategoryId.ImageFootnote - - def __reduct_overlap(self, bboxes): - N = len(bboxes) - keep = [True] * N - for i in range(N): - for j in range(N): - if i == j: - continue - if _is_in(bboxes[i]['bbox'], bboxes[j]['bbox']): - keep[i] = False - return [bboxes[i] for i in range(N) if keep[i]] - - def __tie_up_category_by_distance_v2( - self, - page_no: int, - subject_category_id: int, - object_category_id: int, - priority_pos: PosRelationEnum, - ): - """_summary_ - - Args: - page_no (int): _description_ - subject_category_id (int): _description_ - object_category_id (int): _description_ - priority_pos (PosRelationEnum): _description_ - - Returns: - _type_: _description_ - """ - AXIS_MULPLICITY = 0.5 - subjects = self.__reduct_overlap( - list( - map( - lambda x: {'bbox': x['bbox'], 'score': x['score']}, - filter( - lambda x: x['category_id'] == subject_category_id, - self.__model_list[page_no]['layout_dets'], - ), - ) - ) - ) - - objects = self.__reduct_overlap( - list( - map( - lambda x: {'bbox': x['bbox'], 'score': x['score']}, - filter( - lambda x: x['category_id'] == object_category_id, - self.__model_list[page_no]['layout_dets'], - ), - ) - ) - ) - M = len(objects) - - subjects.sort(key=lambda x: x['bbox'][0] ** 2 + x['bbox'][1] ** 2) - objects.sort(key=lambda x: x['bbox'][0] ** 2 + x['bbox'][1] ** 2) - - sub_obj_map_h = {i: [] for i in range(len(subjects))} - - dis_by_directions = { - 'top': [[-1, float('inf')]] * M, - 'bottom': [[-1, float('inf')]] * M, - 'left': [[-1, float('inf')]] * M, - 'right': [[-1, float('inf')]] * M, - } - - for i, obj in enumerate(objects): - l_x_axis, l_y_axis = ( - obj['bbox'][2] - obj['bbox'][0], - obj['bbox'][3] - obj['bbox'][1], - ) - axis_unit = min(l_x_axis, l_y_axis) - for j, sub in enumerate(subjects): - - bbox1, bbox2, _ = _remove_overlap_between_bbox( - objects[i]['bbox'], subjects[j]['bbox'] - ) - left, right, bottom, top = bbox_relative_pos(bbox1, bbox2) - flags = [left, right, bottom, top] - if sum([1 if v else 0 for v in flags]) > 1: - continue - - if left: - if dis_by_directions['left'][i][1] > bbox_distance( - obj['bbox'], sub['bbox'] - ): - dis_by_directions['left'][i] = [ - j, - bbox_distance(obj['bbox'], sub['bbox']), - ] - if right: - if dis_by_directions['right'][i][1] > bbox_distance( - obj['bbox'], sub['bbox'] - ): - dis_by_directions['right'][i] = [ - j, - bbox_distance(obj['bbox'], sub['bbox']), - ] - if bottom: - if dis_by_directions['bottom'][i][1] > bbox_distance( - obj['bbox'], sub['bbox'] - ): - dis_by_directions['bottom'][i] = [ - j, - bbox_distance(obj['bbox'], sub['bbox']), - ] - if top: - if dis_by_directions['top'][i][1] > bbox_distance( - obj['bbox'], sub['bbox'] - ): - dis_by_directions['top'][i] = [ - j, - bbox_distance(obj['bbox'], sub['bbox']), - ] - - if ( - dis_by_directions['top'][i][1] != float('inf') - and dis_by_directions['bottom'][i][1] != float('inf') - and priority_pos in (PosRelationEnum.BOTTOM, PosRelationEnum.UP) - ): - RATIO = 3 - if ( - abs( - dis_by_directions['top'][i][1] - - dis_by_directions['bottom'][i][1] - ) - < RATIO * axis_unit - ): - - if priority_pos == PosRelationEnum.BOTTOM: - sub_obj_map_h[dis_by_directions['bottom'][i][0]].append(i) - else: - sub_obj_map_h[dis_by_directions['top'][i][0]].append(i) - continue - - if dis_by_directions['left'][i][1] != float('inf') or dis_by_directions[ - 'right' - ][i][1] != float('inf'): - if dis_by_directions['left'][i][1] != float( - 'inf' - ) and dis_by_directions['right'][i][1] != float('inf'): - if AXIS_MULPLICITY * axis_unit >= abs( - dis_by_directions['left'][i][1] - - dis_by_directions['right'][i][1] - ): - left_sub_bbox = subjects[dis_by_directions['left'][i][0]][ - 'bbox' - ] - right_sub_bbox = subjects[dis_by_directions['right'][i][0]][ - 'bbox' - ] - - left_sub_bbox_y_axis = left_sub_bbox[3] - left_sub_bbox[1] - right_sub_bbox_y_axis = right_sub_bbox[3] - right_sub_bbox[1] - - if ( - abs(left_sub_bbox_y_axis - l_y_axis) - + dis_by_directions['left'][i][0] - > abs(right_sub_bbox_y_axis - l_y_axis) - + dis_by_directions['right'][i][0] - ): - left_or_right = dis_by_directions['right'][i] - else: - left_or_right = dis_by_directions['left'][i] - else: - left_or_right = dis_by_directions['left'][i] - if left_or_right[1] > dis_by_directions['right'][i][1]: - left_or_right = dis_by_directions['right'][i] - else: - left_or_right = dis_by_directions['left'][i] - if left_or_right[1] == float('inf'): - left_or_right = dis_by_directions['right'][i] - else: - left_or_right = [-1, float('inf')] - - if dis_by_directions['top'][i][1] != float('inf') or dis_by_directions[ - 'bottom' - ][i][1] != float('inf'): - if dis_by_directions['top'][i][1] != float('inf') and dis_by_directions[ - 'bottom' - ][i][1] != float('inf'): - if AXIS_MULPLICITY * axis_unit >= abs( - dis_by_directions['top'][i][1] - - dis_by_directions['bottom'][i][1] - ): - top_bottom = subjects[dis_by_directions['bottom'][i][0]]['bbox'] - bottom_top = subjects[dis_by_directions['top'][i][0]]['bbox'] - - top_bottom_x_axis = top_bottom[2] - top_bottom[0] - bottom_top_x_axis = bottom_top[2] - bottom_top[0] - if ( - abs(top_bottom_x_axis - l_x_axis) - + dis_by_directions['bottom'][i][1] - > abs(bottom_top_x_axis - l_x_axis) - + dis_by_directions['top'][i][1] - ): - top_or_bottom = dis_by_directions['top'][i] - else: - top_or_bottom = dis_by_directions['bottom'][i] - else: - top_or_bottom = dis_by_directions['top'][i] - if top_or_bottom[1] > dis_by_directions['bottom'][i][1]: - top_or_bottom = dis_by_directions['bottom'][i] - else: - top_or_bottom = dis_by_directions['top'][i] - if top_or_bottom[1] == float('inf'): - top_or_bottom = dis_by_directions['bottom'][i] - else: - top_or_bottom = [-1, float('inf')] - - if left_or_right[1] != float('inf') or top_or_bottom[1] != float('inf'): - if left_or_right[1] != float('inf') and top_or_bottom[1] != float( - 'inf' - ): - if AXIS_MULPLICITY * axis_unit >= abs( - left_or_right[1] - top_or_bottom[1] - ): - y_axis_bbox = subjects[left_or_right[0]]['bbox'] - x_axis_bbox = subjects[top_or_bottom[0]]['bbox'] - - if ( - abs((x_axis_bbox[2] - x_axis_bbox[0]) - l_x_axis) / l_x_axis - > abs((y_axis_bbox[3] - y_axis_bbox[1]) - l_y_axis) - / l_y_axis - ): - sub_obj_map_h[left_or_right[0]].append(i) - else: - sub_obj_map_h[top_or_bottom[0]].append(i) - else: - if left_or_right[1] > top_or_bottom[1]: - sub_obj_map_h[top_or_bottom[0]].append(i) - else: - sub_obj_map_h[left_or_right[0]].append(i) - else: - if left_or_right[1] != float('inf'): - sub_obj_map_h[left_or_right[0]].append(i) - else: - sub_obj_map_h[top_or_bottom[0]].append(i) - ret = [] - for i in sub_obj_map_h.keys(): - ret.append( - { - 'sub_bbox': { - 'bbox': subjects[i]['bbox'], - 'score': subjects[i]['score'], - }, - 'obj_bboxes': [ - {'score': objects[j]['score'], 'bbox': objects[j]['bbox']} - for j in sub_obj_map_h[i] - ], - 'sub_idx': i, - } - ) - return ret - - - def __tie_up_category_by_distance_v3( - self, - page_no: int, - subject_category_id: int, - object_category_id: int, - priority_pos: PosRelationEnum, - ): - subjects = self.__reduct_overlap( - list( - map( - lambda x: {'bbox': x['bbox'], 'score': x['score']}, - filter( - lambda x: x['category_id'] == subject_category_id, - self.__model_list[page_no]['layout_dets'], - ), - ) - ) - ) - objects = self.__reduct_overlap( - list( - map( - lambda x: {'bbox': x['bbox'], 'score': x['score']}, - filter( - lambda x: x['category_id'] == object_category_id, - self.__model_list[page_no]['layout_dets'], - ), - ) - ) - ) - - ret = [] - N, M = len(subjects), len(objects) - subjects.sort(key=lambda x: x['bbox'][0] ** 2 + x['bbox'][1] ** 2) - objects.sort(key=lambda x: x['bbox'][0] ** 2 + x['bbox'][1] ** 2) - - OBJ_IDX_OFFSET = 10000 - SUB_BIT_KIND, OBJ_BIT_KIND = 0, 1 - - all_boxes_with_idx = [(i, SUB_BIT_KIND, sub['bbox'][0], sub['bbox'][1]) for i, sub in enumerate(subjects)] + [(i + OBJ_IDX_OFFSET , OBJ_BIT_KIND, obj['bbox'][0], obj['bbox'][1]) for i, obj in enumerate(objects)] - seen_idx = set() - seen_sub_idx = set() - - while N > len(seen_sub_idx): - candidates = [] - for idx, kind, x0, y0 in all_boxes_with_idx: - if idx in seen_idx: - continue - candidates.append((idx, kind, x0, y0)) - - if len(candidates) == 0: - break - left_x = min([v[2] for v in candidates]) - top_y = min([v[3] for v in candidates]) - - candidates.sort(key=lambda x: (x[2]-left_x) ** 2 + (x[3] - top_y) ** 2) - - - fst_idx, fst_kind, left_x, top_y = candidates[0] - candidates.sort(key=lambda x: (x[2] - left_x) ** 2 + (x[3] - top_y)**2) - nxt = None - - for i in range(1, len(candidates)): - if candidates[i][1] ^ fst_kind == 1: - nxt = candidates[i] - break - if nxt is None: - break - - if fst_kind == SUB_BIT_KIND: - sub_idx, obj_idx = fst_idx, nxt[0] - OBJ_IDX_OFFSET - - else: - sub_idx, obj_idx = nxt[0], fst_idx - OBJ_IDX_OFFSET - - pair_dis = bbox_distance(subjects[sub_idx]['bbox'], objects[obj_idx]['bbox']) - nearest_dis = float('inf') - for i in range(N): - if i in seen_idx or i == sub_idx:continue - nearest_dis = min(nearest_dis, bbox_distance(subjects[i]['bbox'], objects[obj_idx]['bbox'])) - - if pair_dis >= 3*nearest_dis: - seen_idx.add(sub_idx) - continue - - seen_idx.add(sub_idx) - seen_idx.add(obj_idx + OBJ_IDX_OFFSET) - seen_sub_idx.add(sub_idx) - - ret.append( - { - 'sub_bbox': { - 'bbox': subjects[sub_idx]['bbox'], - 'score': subjects[sub_idx]['score'], - }, - 'obj_bboxes': [ - {'score': objects[obj_idx]['score'], 'bbox': objects[obj_idx]['bbox']} - ], - 'sub_idx': sub_idx, - } - ) - - for i in range(len(objects)): - j = i + OBJ_IDX_OFFSET - if j in seen_idx: - continue - seen_idx.add(j) - nearest_dis, nearest_sub_idx = float('inf'), -1 - for k in range(len(subjects)): - dis = bbox_distance(objects[i]['bbox'], subjects[k]['bbox']) - if dis < nearest_dis: - nearest_dis = dis - nearest_sub_idx = k - - for k in range(len(subjects)): - if k != nearest_sub_idx: continue - if k in seen_sub_idx: - for kk in range(len(ret)): - if ret[kk]['sub_idx'] == k: - ret[kk]['obj_bboxes'].append({'score': objects[i]['score'], 'bbox': objects[i]['bbox']}) - break - else: - ret.append( - { - 'sub_bbox': { - 'bbox': subjects[k]['bbox'], - 'score': subjects[k]['score'], - }, - 'obj_bboxes': [ - {'score': objects[i]['score'], 'bbox': objects[i]['bbox']} - ], - 'sub_idx': k, - } - ) - seen_sub_idx.add(k) - seen_idx.add(k) - - - for i in range(len(subjects)): - if i in seen_sub_idx: - continue - ret.append( - { - 'sub_bbox': { - 'bbox': subjects[i]['bbox'], - 'score': subjects[i]['score'], - }, - 'obj_bboxes': [], - 'sub_idx': i, - } - ) - - - return ret - - - def get_imgs_v2(self, page_no: int): - with_captions = self.__tie_up_category_by_distance_v3( - page_no, 3, 4, PosRelationEnum.BOTTOM - ) - with_footnotes = self.__tie_up_category_by_distance_v3( - page_no, 3, CategoryId.ImageFootnote, PosRelationEnum.ALL - ) - ret = [] - for v in with_captions: - record = { - 'image_body': v['sub_bbox'], - 'image_caption_list': v['obj_bboxes'], - } - filter_idx = v['sub_idx'] - d = next(filter(lambda x: x['sub_idx'] == filter_idx, with_footnotes)) - record['image_footnote_list'] = d['obj_bboxes'] - ret.append(record) - return ret - - def get_tables_v2(self, page_no: int) -> list: - with_captions = self.__tie_up_category_by_distance_v3( - page_no, 5, 6, PosRelationEnum.UP - ) - with_footnotes = self.__tie_up_category_by_distance_v3( - page_no, 5, 7, PosRelationEnum.ALL - ) - ret = [] - for v in with_captions: - record = { - 'table_body': v['sub_bbox'], - 'table_caption_list': v['obj_bboxes'], - } - filter_idx = v['sub_idx'] - d = next(filter(lambda x: x['sub_idx'] == filter_idx, with_footnotes)) - record['table_footnote_list'] = d['obj_bboxes'] - ret.append(record) - return ret - - def get_imgs(self, page_no: int): - return self.get_imgs_v2(page_no) - - def get_tables( - self, page_no: int - ) -> list: # 3个坐标, caption, table主体,table-note - return self.get_tables_v2(page_no) - - def get_equations(self, page_no: int) -> list: # 有坐标,也有字 - inline_equations = self.__get_blocks_by_type( - ModelBlockTypeEnum.EMBEDDING.value, page_no, ['latex'] - ) - interline_equations = self.__get_blocks_by_type( - ModelBlockTypeEnum.ISOLATED.value, page_no, ['latex'] - ) - interline_equations_blocks = self.__get_blocks_by_type( - ModelBlockTypeEnum.ISOLATE_FORMULA.value, page_no - ) - return inline_equations, interline_equations, interline_equations_blocks - - def get_discarded(self, page_no: int) -> list: # 自研模型,只有坐标 - blocks = self.__get_blocks_by_type(ModelBlockTypeEnum.ABANDON.value, page_no) - return blocks - - def get_text_blocks(self, page_no: int) -> list: # 自研模型搞的,只有坐标,没有字 - blocks = self.__get_blocks_by_type(ModelBlockTypeEnum.PLAIN_TEXT.value, page_no) - return blocks - - def get_title_blocks(self, page_no: int) -> list: # 自研模型,只有坐标,没字 - blocks = self.__get_blocks_by_type(ModelBlockTypeEnum.TITLE.value, page_no) - return blocks - - def get_ocr_text(self, page_no: int) -> list: # paddle 搞的,有字也有坐标 - text_spans = [] - model_page_info = self.__model_list[page_no] - layout_dets = model_page_info['layout_dets'] - for layout_det in layout_dets: - if layout_det['category_id'] == '15': - span = { - 'bbox': layout_det['bbox'], - 'content': layout_det['text'], - } - text_spans.append(span) - return text_spans - - def get_all_spans(self, page_no: int) -> list: - - def remove_duplicate_spans(spans): - new_spans = [] - for span in spans: - if not any(span == existing_span for existing_span in new_spans): - new_spans.append(span) - return new_spans - - all_spans = [] - model_page_info = self.__model_list[page_no] - layout_dets = model_page_info['layout_dets'] - allow_category_id_list = [3, 5, 13, 14, 15] - """当成span拼接的""" - # 3: 'image', # 图片 - # 5: 'table', # 表格 - # 13: 'inline_equation', # 行内公式 - # 14: 'interline_equation', # 行间公式 - # 15: 'text', # ocr识别文本 - for layout_det in layout_dets: - category_id = layout_det['category_id'] - if category_id in allow_category_id_list: - span = {'bbox': layout_det['bbox'], 'score': layout_det['score']} - if category_id == 3: - span['type'] = ContentType.Image - elif category_id == 5: - # 获取table模型结果 - latex = layout_det.get('latex', None) - html = layout_det.get('html', None) - if latex: - span['latex'] = latex - elif html: - span['html'] = html - span['type'] = ContentType.Table - elif category_id == 13: - span['content'] = layout_det['latex'] - span['type'] = ContentType.InlineEquation - elif category_id == 14: - span['content'] = layout_det['latex'] - span['type'] = ContentType.InterlineEquation - elif category_id == 15: - span['content'] = layout_det['text'] - span['type'] = ContentType.Text - all_spans.append(span) - return remove_duplicate_spans(all_spans) - - def get_page_size(self, page_no: int): # 获取页面宽高 - # 获取当前页的page对象 - page = self.__docs.get_page(page_no).get_page_info() - # 获取当前页的宽高 - page_w = page.w - page_h = page.h - return page_w, page_h - - def __get_blocks_by_type( - self, type: int, page_no: int, extra_col: list[str] = [] - ) -> list: - blocks = [] - for page_dict in self.__model_list: - layout_dets = page_dict.get('layout_dets', []) - page_info = page_dict.get('page_info', {}) - page_number = page_info.get('page_no', -1) - if page_no != page_number: - continue - for item in layout_dets: - category_id = item.get('category_id', -1) - bbox = item.get('bbox', None) - - if category_id == type: - block = { - 'bbox': bbox, - 'score': item.get('score'), - } - for col in extra_col: - block[col] = item.get(col, None) - blocks.append(block) - return blocks - - def get_model_list(self, page_no): - return self.__model_list[page_no] diff --git a/magic_pdf/model/pdf_extract_kit.py b/magic_pdf/model/pdf_extract_kit.py deleted file mode 100644 index f389a306565e20ff00dfef7c784bce30151583f1..0000000000000000000000000000000000000000 --- a/magic_pdf/model/pdf_extract_kit.py +++ /dev/null @@ -1,266 +0,0 @@ -# flake8: noqa -import os -import time - -import cv2 -import torch -import yaml -from loguru import logger - -os.environ['NO_ALBUMENTATIONS_UPDATE'] = '1' # 禁止albumentations检查更新 - -from magic_pdf.config.constants import * -from magic_pdf.model.model_list import AtomicModel -from magic_pdf.model.sub_modules.model_init import AtomModelSingleton -from magic_pdf.model.sub_modules.model_utils import ( - clean_vram, crop_img, get_res_list_from_layout_res) -from magic_pdf.model.sub_modules.ocr.paddleocr2pytorch.ocr_utils import ( - get_adjusted_mfdetrec_res, get_ocr_result_list) - - -class CustomPEKModel: - - def __init__(self, ocr: bool = False, show_log: bool = False, **kwargs): - """ - ======== model init ======== - """ - # 获取当前文件(即 pdf_extract_kit.py)的绝对路径 - current_file_path = os.path.abspath(__file__) - # 获取当前文件所在的目录(model) - current_dir = os.path.dirname(current_file_path) - # 上一级目录(magic_pdf) - root_dir = os.path.dirname(current_dir) - # model_config目录 - model_config_dir = os.path.join(root_dir, 'resources', 'model_config') - # 构建 model_configs.yaml 文件的完整路径 - config_path = os.path.join(model_config_dir, 'model_configs.yaml') - with open(config_path, 'r', encoding='utf-8') as f: - self.configs = yaml.load(f, Loader=yaml.FullLoader) - # 初始化解析配置 - - # layout config - self.layout_config = kwargs.get('layout_config') - self.layout_model_name = self.layout_config.get( - 'model', MODEL_NAME.DocLayout_YOLO - ) - - # formula config - self.formula_config = kwargs.get('formula_config') - self.mfd_model_name = self.formula_config.get( - 'mfd_model', MODEL_NAME.YOLO_V8_MFD - ) - self.mfr_model_name = self.formula_config.get( - 'mfr_model', MODEL_NAME.UniMerNet_v2_Small - ) - self.apply_formula = self.formula_config.get('enable', True) - - # table config - self.table_config = kwargs.get('table_config') - self.apply_table = self.table_config.get('enable', False) - self.table_max_time = self.table_config.get('max_time', TABLE_MAX_TIME_VALUE) - self.table_model_name = self.table_config.get('model', MODEL_NAME.RAPID_TABLE) - self.table_sub_model_name = self.table_config.get('sub_model', None) - - # ocr config - self.apply_ocr = ocr - self.lang = kwargs.get('lang', None) - - logger.info( - 'DocAnalysis init, this may take some times, layout_model: {}, apply_formula: {}, apply_ocr: {}, ' - 'apply_table: {}, table_model: {}, lang: {}'.format( - self.layout_model_name, - self.apply_formula, - self.apply_ocr, - self.apply_table, - self.table_model_name, - self.lang, - ) - ) - # 初始化解析方案 - self.device = kwargs.get('device', 'cpu') - - logger.info('using device: {}'.format(self.device)) - models_dir = kwargs.get( - 'models_dir', os.path.join(root_dir, 'resources', 'models') - ) - logger.info('using models_dir: {}'.format(models_dir)) - - atom_model_manager = AtomModelSingleton() - - # 初始化公式识别 - if self.apply_formula: - # 初始化公式检测模型 - self.mfd_model = atom_model_manager.get_atom_model( - atom_model_name=AtomicModel.MFD, - mfd_weights=str( - os.path.join( - models_dir, self.configs['weights'][self.mfd_model_name] - ) - ), - device=self.device, - ) - - # 初始化公式解析模型 - mfr_weight_dir = str( - os.path.join(models_dir, self.configs['weights'][self.mfr_model_name]) - ) - mfr_cfg_path = str(os.path.join(model_config_dir, 'UniMERNet', 'demo.yaml')) - - self.mfr_model = atom_model_manager.get_atom_model( - atom_model_name=AtomicModel.MFR, - mfr_weight_dir=mfr_weight_dir, - mfr_cfg_path=mfr_cfg_path, - device=self.device, - ) - - # 初始化layout模型 - if self.layout_model_name == MODEL_NAME.LAYOUTLMv3: - self.layout_model = atom_model_manager.get_atom_model( - atom_model_name=AtomicModel.Layout, - layout_model_name=MODEL_NAME.LAYOUTLMv3, - layout_weights=str( - os.path.join( - models_dir, self.configs['weights'][self.layout_model_name] - ) - ), - layout_config_file=str( - os.path.join( - model_config_dir, 'layoutlmv3', 'layoutlmv3_base_inference.yaml' - ) - ), - device='cpu' if str(self.device).startswith("mps") else self.device, - ) - elif self.layout_model_name == MODEL_NAME.DocLayout_YOLO: - self.layout_model = atom_model_manager.get_atom_model( - atom_model_name=AtomicModel.Layout, - layout_model_name=MODEL_NAME.DocLayout_YOLO, - doclayout_yolo_weights=str( - os.path.join( - models_dir, self.configs['weights'][self.layout_model_name] - ) - ), - device=self.device, - ) - # 初始化ocr - self.ocr_model = atom_model_manager.get_atom_model( - atom_model_name=AtomicModel.OCR, - ocr_show_log=show_log, - det_db_box_thresh=0.3, - lang=self.lang - ) - # init table model - if self.apply_table: - table_model_dir = self.configs['weights'][self.table_model_name] - self.table_model = atom_model_manager.get_atom_model( - atom_model_name=AtomicModel.Table, - table_model_name=self.table_model_name, - table_model_path=str(os.path.join(models_dir, table_model_dir)), - table_max_time=self.table_max_time, - device=self.device, - ocr_engine=self.ocr_model, - table_sub_model_name=self.table_sub_model_name - ) - - logger.info('DocAnalysis init done!') - - def __call__(self, image): - # layout检测 - layout_start = time.time() - layout_res = [] - if self.layout_model_name == MODEL_NAME.LAYOUTLMv3: - # layoutlmv3 - layout_res = self.layout_model(image, ignore_catids=[]) - elif self.layout_model_name == MODEL_NAME.DocLayout_YOLO: - layout_res = self.layout_model.predict(image) - - layout_cost = round(time.time() - layout_start, 2) - logger.info(f'layout detection time: {layout_cost}') - - if self.apply_formula: - # 公式检测 - mfd_start = time.time() - mfd_res = self.mfd_model.predict(image) - logger.info(f'mfd time: {round(time.time() - mfd_start, 2)}') - - # 公式识别 - mfr_start = time.time() - formula_list = self.mfr_model.predict(mfd_res, image) - layout_res.extend(formula_list) - mfr_cost = round(time.time() - mfr_start, 2) - logger.info(f'formula nums: {len(formula_list)}, mfr time: {mfr_cost}') - - # 清理显存 - clean_vram(self.device, vram_threshold=6) - - # 从layout_res中获取ocr区域、表格区域、公式区域 - ocr_res_list, table_res_list, single_page_mfdetrec_res = ( - get_res_list_from_layout_res(layout_res) - ) - - # ocr识别 - ocr_start = time.time() - # Process each area that requires OCR processing - for res in ocr_res_list: - new_image, useful_list = crop_img(res, image, crop_paste_x=50, crop_paste_y=50) - adjusted_mfdetrec_res = get_adjusted_mfdetrec_res(single_page_mfdetrec_res, useful_list) - - # OCR recognition - new_image = cv2.cvtColor(new_image, cv2.COLOR_RGB2BGR) - - if self.apply_ocr: - ocr_res = self.ocr_model.ocr(new_image, mfd_res=adjusted_mfdetrec_res)[0] - else: - ocr_res = self.ocr_model.ocr(new_image, mfd_res=adjusted_mfdetrec_res, rec=False)[0] - - # Integration results - if ocr_res: - ocr_result_list = get_ocr_result_list(ocr_res, useful_list) - layout_res.extend(ocr_result_list) - - ocr_cost = round(time.time() - ocr_start, 2) - if self.apply_ocr: - logger.info(f"ocr time: {ocr_cost}") - else: - logger.info(f"det time: {ocr_cost}") - - # 表格识别 table recognition - if self.apply_table: - table_start = time.time() - for res in table_res_list: - new_image, _ = crop_img(res, image) - single_table_start_time = time.time() - html_code = None - if self.table_model_name == MODEL_NAME.STRUCT_EQTABLE: - with torch.no_grad(): - table_result = self.table_model.predict(new_image, 'html') - if len(table_result) > 0: - html_code = table_result[0] - elif self.table_model_name == MODEL_NAME.TABLE_MASTER: - html_code = self.table_model.img2html(new_image) - elif self.table_model_name == MODEL_NAME.RAPID_TABLE: - html_code, table_cell_bboxes, logic_points, elapse = self.table_model.predict( - new_image - ) - run_time = time.time() - single_table_start_time - if run_time > self.table_max_time: - logger.warning( - f'table recognition processing exceeds max time {self.table_max_time}s' - ) - # 判断是否返回正常 - if html_code: - expected_ending = html_code.strip().endswith( - '' - ) or html_code.strip().endswith('') - if expected_ending: - res['html'] = html_code - else: - logger.warning( - 'table recognition processing fails, not found expected HTML table end' - ) - else: - logger.warning( - 'table recognition processing fails, not get html return' - ) - logger.info(f'table time: {round(time.time() - table_start, 2)}') - - return layout_res diff --git a/magic_pdf/model/pp_structure_v2.py b/magic_pdf/model/pp_structure_v2.py deleted file mode 100644 index ad9f71ad47d0dc9513b4913f4b156e1ab7fb65b2..0000000000000000000000000000000000000000 --- a/magic_pdf/model/pp_structure_v2.py +++ /dev/null @@ -1,110 +0,0 @@ -import random - -from loguru import logger - -try: - from paddleocr import PPStructure -except ImportError: - logger.error('paddleocr not installed, please install by "pip install magic-pdf[lite]"') - exit(1) - - -def region_to_bbox(region): - x0 = region[0][0] - y0 = region[0][1] - x1 = region[2][0] - y1 = region[2][1] - return [x0, y0, x1, y1] - - -class CustomPaddleModel: - def __init__(self, - ocr: bool = False, - show_log: bool = False, - lang=None, - det_db_box_thresh=0.3, - use_dilation=True, - det_db_unclip_ratio=1.8 - ): - if lang is not None: - self.model = PPStructure(table=False, - ocr=True, - show_log=show_log, - lang=lang, - det_db_box_thresh=det_db_box_thresh, - use_dilation=use_dilation, - det_db_unclip_ratio=det_db_unclip_ratio, - ) - else: - self.model = PPStructure(table=False, - ocr=True, - show_log=show_log, - det_db_box_thresh=det_db_box_thresh, - use_dilation=use_dilation, - det_db_unclip_ratio=det_db_unclip_ratio, - ) - - def __call__(self, img): - try: - import cv2 - except ImportError: - logger.error("opencv-python not installed, please install by pip.") - exit(1) - # 将RGB图片转换为BGR格式适配paddle - img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) - result = self.model(img) - spans = [] - for line in result: - line.pop("img") - """ - 为paddle输出适配type no. - title: 0 # 标题 - text: 1 # 文本 - header: 2 # abandon - footer: 2 # abandon - reference: 1 # 文本 or abandon - equation: 8 # 行间公式 block - equation: 14 # 行间公式 text - figure: 3 # 图片 - figure_caption: 4 # 图片描述 - table: 5 # 表格 - table_caption: 6 # 表格描述 - """ - if line["type"] == "title": - line["category_id"] = 0 - elif line["type"] in ["text", "reference"]: - line["category_id"] = 1 - elif line["type"] == "figure": - line["category_id"] = 3 - elif line["type"] == "figure_caption": - line["category_id"] = 4 - elif line["type"] == "table": - line["category_id"] = 5 - elif line["type"] == "table_caption": - line["category_id"] = 6 - elif line["type"] == "equation": - line["category_id"] = 8 - elif line["type"] in ["header", "footer"]: - line["category_id"] = 2 - else: - logger.warning(f"unknown type: {line['type']}") - - # 兼容不输出score的paddleocr版本 - if line.get("score") is None: - line["score"] = 0.5 + random.random() * 0.5 - - res = line.pop("res", None) - if res is not None and len(res) > 0: - for span in res: - new_span = { - "category_id": 15, - "bbox": region_to_bbox(span["text_region"]), - "score": span["confidence"], - "text": span["text"], - } - spans.append(new_span) - - if len(spans) > 0: - result.extend(spans) - - return result diff --git a/magic_pdf/model/sub_modules/__init__.py b/magic_pdf/model/sub_modules/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/language_detection/utils.py b/magic_pdf/model/sub_modules/language_detection/utils.py deleted file mode 100644 index 20aefaf6a870edb0247e094cd583314d35bbb5d2..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/language_detection/utils.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright (c) Opendatalab. All rights reserved. -import os -from pathlib import Path - -import yaml -os.environ['NO_ALBUMENTATIONS_UPDATE'] = '1' # 禁止albumentations检查更新 - -from magic_pdf.config.constants import MODEL_NAME -from magic_pdf.data.utils import load_images_from_pdf -from magic_pdf.libs.config_reader import get_local_models_dir, get_device -from magic_pdf.libs.pdf_check import extract_pages -from magic_pdf.model.model_list import AtomicModel -from magic_pdf.model.sub_modules.model_init import AtomModelSingleton - - -def get_model_config(): - local_models_dir = get_local_models_dir() - device = get_device() - current_file_path = os.path.abspath(__file__) - root_dir = Path(current_file_path).parents[3] - model_config_dir = os.path.join(root_dir, 'resources', 'model_config') - config_path = os.path.join(model_config_dir, 'model_configs.yaml') - with open(config_path, 'r', encoding='utf-8') as f: - configs = yaml.load(f, Loader=yaml.FullLoader) - return root_dir, local_models_dir, device, configs - - -def get_text_images(simple_images): - _, local_models_dir, device, configs = get_model_config() - atom_model_manager = AtomModelSingleton() - temp_layout_model = atom_model_manager.get_atom_model( - atom_model_name=AtomicModel.Layout, - layout_model_name=MODEL_NAME.DocLayout_YOLO, - doclayout_yolo_weights=str( - os.path.join( - local_models_dir, configs['weights'][MODEL_NAME.DocLayout_YOLO] - ) - ), - device=device, - ) - text_images = [] - for simple_image in simple_images: - image = simple_image['img'] - layout_res = temp_layout_model.predict(image) - # 给textblock截图 - for res in layout_res: - if res['category_id'] in [1]: - x1, y1, _, _, x2, y2, _, _ = res['poly'] - # 初步清洗(宽和高都小于100) - if x2 - x1 < 100 and y2 - y1 < 100: - continue - text_images.append(image[y1:y2, x1:x2]) - return text_images - - -def auto_detect_lang(pdf_bytes: bytes): - sample_docs = extract_pages(pdf_bytes) - sample_pdf_bytes = sample_docs.tobytes() - simple_images = load_images_from_pdf(sample_pdf_bytes, dpi=200) - text_images = get_text_images(simple_images) - langdetect_model = model_init(MODEL_NAME.YOLO_V11_LangDetect) - lang = langdetect_model.do_detect(text_images) - return lang - - -def model_init(model_name: str): - atom_model_manager = AtomModelSingleton() - - if model_name == MODEL_NAME.YOLO_V11_LangDetect: - root_dir, _, device, _ = get_model_config() - model = atom_model_manager.get_atom_model( - atom_model_name=AtomicModel.LangDetect, - langdetect_model_name=MODEL_NAME.YOLO_V11_LangDetect, - langdetect_model_weight=str(os.path.join(root_dir, 'resources', 'yolov11-langdetect', 'yolo_v11_ft.pt')), - device=device, - ) - else: - raise ValueError(f"model_name {model_name} not found") - return model - diff --git a/magic_pdf/model/sub_modules/language_detection/yolov11/YOLOv11.py b/magic_pdf/model/sub_modules/language_detection/yolov11/YOLOv11.py deleted file mode 100644 index 28cdb17cd0f06aa8edfd3037e680edacec63a90e..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/language_detection/yolov11/YOLOv11.py +++ /dev/null @@ -1,145 +0,0 @@ -# Copyright (c) Opendatalab. All rights reserved. -import time -from collections import Counter -from uuid import uuid4 -import cv2 -import numpy as np -import torch -from loguru import logger -from ultralytics import YOLO - -language_dict = { - "ch": "中文简体", - "en": "英语", - "japan": "日语", - "korean": "韩语", - "fr": "法语", - "german": "德语", - "ar": "阿拉伯语", - "ru": "俄语" -} - - -def split_images(image, result_images=None): - """ - 对输入文件夹内的图片进行处理,若图片竖向(y方向)分辨率超过400,则进行拆分, - 每次平分图片,直至拆分出的图片竖向分辨率都满足400以下,将处理后的图片(拆分后的子图片)保存到输出文件夹。 - 避免保存因裁剪区域超出图片范围导致出现的无效黑色图片部分。 - """ - if result_images is None: - result_images = [] - - height, width = image.shape[:2] - long_side = max(width, height) # 获取较长边长度 - - if long_side <= 400: - result_images.append(image) - return result_images - - new_long_side = long_side // 2 - sub_images = [] - - if width >= height: # 如果宽度是较长边 - for x in range(0, width, new_long_side): - # 判断裁剪区域是否超出图片范围,如果超出则不进行裁剪保存操作 - if x + new_long_side > width: - continue - sub_image = image[0:height, x:x + new_long_side] - sub_images.append(sub_image) - else: # 如果高度是较长边 - for y in range(0, height, new_long_side): - # 判断裁剪区域是否超出图片范围,如果超出则不进行裁剪保存操作 - if y + new_long_side > height: - continue - sub_image = image[y:y + new_long_side, 0:width] - sub_images.append(sub_image) - - for sub_image in sub_images: - split_images(sub_image, result_images) - - return result_images - - -def resize_images_to_224(image): - """ - 若分辨率小于224则用黑色背景补齐到224*224大小,若大于等于224则调整为224*224大小。 - Works directly with NumPy arrays. - """ - try: - height, width = image.shape[:2] - - if width < 224 or height < 224: - # Create black background - new_image = np.zeros((224, 224, 3), dtype=np.uint8) - # Calculate paste position (ensure they're not negative) - paste_x = max(0, (224 - width) // 2) - paste_y = max(0, (224 - height) // 2) - # Make sure we don't exceed the boundaries of new_image - paste_width = min(width, 224) - paste_height = min(height, 224) - # Paste original image onto black background - new_image[paste_y:paste_y + paste_height, paste_x:paste_x + paste_width] = image[:paste_height, :paste_width] - image = new_image - else: - # Resize using cv2 - image = cv2.resize(image, (224, 224), interpolation=cv2.INTER_LANCZOS4) - - return image - except Exception as e: - logger.exception(f"Error in resize_images_to_224: {e}") - return None - - -class YOLOv11LangDetModel(object): - def __init__(self, langdetect_model_weight, device): - - self.model = YOLO(langdetect_model_weight) - - if str(device).startswith("npu"): - self.device = torch.device(device) - else: - self.device = device - def do_detect(self, images: list): - all_images = [] - for image in images: - height, width = image.shape[:2] - if width < 100 and height < 100: - continue - temp_images = split_images(image) - for temp_image in temp_images: - all_images.append(resize_images_to_224(temp_image)) - # langdetect_start = time.time() - images_lang_res = self.batch_predict(all_images, batch_size=256) - # logger.info(f"image number of langdetect: {len(images_lang_res)}, langdetect time: {round(time.time() - langdetect_start, 2)}") - if len(images_lang_res) > 0: - count_dict = Counter(images_lang_res) - language = max(count_dict, key=count_dict.get) - else: - language = None - return language - - def predict(self, image): - results = self.model.predict(image, verbose=False, device=self.device) - predicted_class_id = int(results[0].probs.top1) - predicted_class_name = self.model.names[predicted_class_id] - return predicted_class_name - - - def batch_predict(self, images: list, batch_size: int) -> list: - images_lang_res = [] - - for index in range(0, len(images), batch_size): - lang_res = [ - image_res.cpu() - for image_res in self.model.predict( - images[index: index + batch_size], - verbose = False, - device=self.device, - ) - ] - for res in lang_res: - predicted_class_id = int(res.probs.top1) - predicted_class_name = self.model.names[predicted_class_id] - images_lang_res.append(predicted_class_name) - - return images_lang_res \ No newline at end of file diff --git a/magic_pdf/model/sub_modules/layout/__init__.py b/magic_pdf/model/sub_modules/layout/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/layout/doclayout_yolo/__init__.py b/magic_pdf/model/sub_modules/layout/doclayout_yolo/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/__init__.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/backbone.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/backbone.py deleted file mode 100644 index 5364f862e78205c65ffe3fdeba6aef09da148c39..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/backbone.py +++ /dev/null @@ -1,179 +0,0 @@ -# -------------------------------------------------------------------------------- -# VIT: Multi-Path Vision Transformer for Dense Prediction -# Copyright (c) 2022 Electronics and Telecommunications Research Institute (ETRI). -# All Rights Reserved. -# Written by Youngwan Lee -# This source code is licensed(Dual License(GPL3.0 & Commercial)) under the license found in the -# LICENSE file in the root directory of this source tree. -# -------------------------------------------------------------------------------- -# References: -# timm: https://github.com/rwightman/pytorch-image-models/tree/master/timm -# CoaT: https://github.com/mlpc-ucsd/CoaT -# -------------------------------------------------------------------------------- - - -import torch - -from detectron2.layers import ( - ShapeSpec, -) -from detectron2.modeling import Backbone, BACKBONE_REGISTRY, FPN -from detectron2.modeling.backbone.fpn import LastLevelP6P7, LastLevelMaxPool - -from .beit import beit_base_patch16, dit_base_patch16, dit_large_patch16, beit_large_patch16 -from .deit import deit_base_patch16, mae_base_patch16 -from .layoutlmft.models.layoutlmv3 import LayoutLMv3Model -from transformers import AutoConfig - -__all__ = [ - "build_vit_fpn_backbone", -] - - -class VIT_Backbone(Backbone): - """ - Implement VIT backbone. - """ - - def __init__(self, name, out_features, drop_path, img_size, pos_type, model_kwargs, - config_path=None, image_only=False, cfg=None): - super().__init__() - self._out_features = out_features - if 'base' in name: - self._out_feature_strides = {"layer3": 4, "layer5": 8, "layer7": 16, "layer11": 32} - self._out_feature_channels = {"layer3": 768, "layer5": 768, "layer7": 768, "layer11": 768} - else: - self._out_feature_strides = {"layer7": 4, "layer11": 8, "layer15": 16, "layer23": 32} - self._out_feature_channels = {"layer7": 1024, "layer11": 1024, "layer15": 1024, "layer23": 1024} - - if name == 'beit_base_patch16': - model_func = beit_base_patch16 - elif name == 'dit_base_patch16': - model_func = dit_base_patch16 - elif name == "deit_base_patch16": - model_func = deit_base_patch16 - elif name == "mae_base_patch16": - model_func = mae_base_patch16 - elif name == "dit_large_patch16": - model_func = dit_large_patch16 - elif name == "beit_large_patch16": - model_func = beit_large_patch16 - - if 'beit' in name or 'dit' in name: - if pos_type == "abs": - self.backbone = model_func(img_size=img_size, - out_features=out_features, - drop_path_rate=drop_path, - use_abs_pos_emb=True, - **model_kwargs) - elif pos_type == "shared_rel": - self.backbone = model_func(img_size=img_size, - out_features=out_features, - drop_path_rate=drop_path, - use_shared_rel_pos_bias=True, - **model_kwargs) - elif pos_type == "rel": - self.backbone = model_func(img_size=img_size, - out_features=out_features, - drop_path_rate=drop_path, - use_rel_pos_bias=True, - **model_kwargs) - else: - raise ValueError() - elif "layoutlmv3" in name: - config = AutoConfig.from_pretrained(config_path) - # disable relative bias as DiT - config.has_spatial_attention_bias = False - config.has_relative_attention_bias = False - self.backbone = LayoutLMv3Model(config, detection=True, - out_features=out_features, image_only=image_only) - else: - self.backbone = model_func(img_size=img_size, - out_features=out_features, - drop_path_rate=drop_path, - **model_kwargs) - self.name = name - - def forward(self, x): - """ - Args: - x: Tensor of shape (N,C,H,W). H, W must be a multiple of ``self.size_divisibility``. - - Returns: - dict[str->Tensor]: names and the corresponding features - """ - if "layoutlmv3" in self.name: - return self.backbone.forward( - input_ids=x["input_ids"] if "input_ids" in x else None, - bbox=x["bbox"] if "bbox" in x else None, - images=x["images"] if "images" in x else None, - attention_mask=x["attention_mask"] if "attention_mask" in x else None, - # output_hidden_states=True, - ) - assert x.dim() == 4, f"VIT takes an input of shape (N, C, H, W). Got {x.shape} instead!" - return self.backbone.forward_features(x) - - def output_shape(self): - return { - name: ShapeSpec( - channels=self._out_feature_channels[name], stride=self._out_feature_strides[name] - ) - for name in self._out_features - } - - -def build_VIT_backbone(cfg): - """ - Create a VIT instance from config. - - Args: - cfg: a detectron2 CfgNode - - Returns: - A VIT backbone instance. - """ - # fmt: off - name = cfg.MODEL.VIT.NAME - out_features = cfg.MODEL.VIT.OUT_FEATURES - drop_path = cfg.MODEL.VIT.DROP_PATH - img_size = cfg.MODEL.VIT.IMG_SIZE - pos_type = cfg.MODEL.VIT.POS_TYPE - - model_kwargs = eval(str(cfg.MODEL.VIT.MODEL_KWARGS).replace("`", "")) - - if 'layoutlmv3' in name: - if cfg.MODEL.CONFIG_PATH != '': - config_path = cfg.MODEL.CONFIG_PATH - else: - config_path = cfg.MODEL.WEIGHTS.replace('pytorch_model.bin', '') # layoutlmv3 pre-trained models - config_path = config_path.replace('model_final.pth', '') # detection fine-tuned models - else: - config_path = None - - return VIT_Backbone(name, out_features, drop_path, img_size, pos_type, model_kwargs, - config_path=config_path, image_only=cfg.MODEL.IMAGE_ONLY, cfg=cfg) - - -@BACKBONE_REGISTRY.register() -def build_vit_fpn_backbone(cfg, input_shape: ShapeSpec): - """ - Create a VIT w/ FPN backbone. - - Args: - cfg: a detectron2 CfgNode - - Returns: - backbone (Backbone): backbone module, must be a subclass of :class:`Backbone`. - """ - bottom_up = build_VIT_backbone(cfg) - in_features = cfg.MODEL.FPN.IN_FEATURES - out_channels = cfg.MODEL.FPN.OUT_CHANNELS - backbone = FPN( - bottom_up=bottom_up, - in_features=in_features, - out_channels=out_channels, - norm=cfg.MODEL.FPN.NORM, - top_block=LastLevelMaxPool(), - fuse_type=cfg.MODEL.FPN.FUSE_TYPE, - ) - return backbone diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/beit.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/beit.py deleted file mode 100644 index 03d4fabdc7816f19a8810e3c443643bc9e53e6b9..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/beit.py +++ /dev/null @@ -1,671 +0,0 @@ -""" Vision Transformer (ViT) in PyTorch - -A PyTorch implement of Vision Transformers as described in -'An Image Is Worth 16 x 16 Words: Transformers for Image Recognition at Scale' - https://arxiv.org/abs/2010.11929 - -The official jax code is released and available at https://github.com/google-research/vision_transformer - -Status/TODO: -* Models updated to be compatible with official impl. Args added to support backward compat for old PyTorch weights. -* Weights ported from official jax impl for 384x384 base and small models, 16x16 and 32x32 patches. -* Trained (supervised on ImageNet-1k) my custom 'small' patch model to 77.9, 'base' to 79.4 top-1 with this code. -* Hopefully find time and GPUs for SSL or unsupervised pretraining on OpenImages w/ ImageNet fine-tune in future. - -Acknowledgments: -* The paper authors for releasing code and weights, thanks! -* I fixed my class token impl based on Phil Wang's https://github.com/lucidrains/vit-pytorch ... check it out -for some einops/einsum fun -* Simple transformer style inspired by Andrej Karpathy's https://github.com/karpathy/minGPT -* Bert reference code checks against Huggingface Transformers and Tensorflow Bert - -Hacked together by / Copyright 2020 Ross Wightman -""" -import warnings -import math -import torch -from functools import partial -import torch.nn as nn -import torch.nn.functional as F -import torch.utils.checkpoint as checkpoint -from timm.models.layers import drop_path, to_2tuple, trunc_normal_ - - -def _cfg(url='', **kwargs): - return { - 'url': url, - 'num_classes': 1000, 'input_size': (3, 224, 224), 'pool_size': None, - 'crop_pct': .9, 'interpolation': 'bicubic', - 'mean': (0.5, 0.5, 0.5), 'std': (0.5, 0.5, 0.5), - **kwargs - } - - -class DropPath(nn.Module): - """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). - """ - - def __init__(self, drop_prob=None): - super(DropPath, self).__init__() - self.drop_prob = drop_prob - - def forward(self, x): - return drop_path(x, self.drop_prob, self.training) - - def extra_repr(self) -> str: - return 'p={}'.format(self.drop_prob) - - -class Mlp(nn.Module): - def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.): - super().__init__() - out_features = out_features or in_features - hidden_features = hidden_features or in_features - self.fc1 = nn.Linear(in_features, hidden_features) - self.act = act_layer() - self.fc2 = nn.Linear(hidden_features, out_features) - self.drop = nn.Dropout(drop) - - def forward(self, x): - x = self.fc1(x) - x = self.act(x) - # x = self.drop(x) - # commit this for the orignal BERT implement - x = self.fc2(x) - x = self.drop(x) - return x - - -class Attention(nn.Module): - def __init__( - self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0., - proj_drop=0., window_size=None, attn_head_dim=None): - super().__init__() - self.num_heads = num_heads - head_dim = dim // num_heads - if attn_head_dim is not None: - head_dim = attn_head_dim - all_head_dim = head_dim * self.num_heads - # NOTE scale factor was wrong in my original version, can set manually to be compat with prev weights - self.scale = qk_scale or head_dim ** -0.5 - - self.qkv = nn.Linear(dim, all_head_dim * 3, bias=False) - if qkv_bias: - self.q_bias = nn.Parameter(torch.zeros(all_head_dim)) - self.v_bias = nn.Parameter(torch.zeros(all_head_dim)) - else: - self.q_bias = None - self.v_bias = None - - if window_size: - self.window_size = window_size - self.num_relative_distance = (2 * window_size[0] - 1) * (2 * window_size[1] - 1) + 3 - self.relative_position_bias_table = nn.Parameter( - torch.zeros(self.num_relative_distance, num_heads)) # 2*Wh-1 * 2*Ww-1, nH - # cls to token & token 2 cls & cls to cls - - # get pair-wise relative position index for each token inside the window - coords_h = torch.arange(window_size[0]) - coords_w = torch.arange(window_size[1]) - coords = torch.stack(torch.meshgrid([coords_h, coords_w])) # 2, Wh, Ww - coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww - relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww - relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2 - relative_coords[:, :, 0] += window_size[0] - 1 # shift to start from 0 - relative_coords[:, :, 1] += window_size[1] - 1 - relative_coords[:, :, 0] *= 2 * window_size[1] - 1 - relative_position_index = \ - torch.zeros(size=(window_size[0] * window_size[1] + 1,) * 2, dtype=relative_coords.dtype) - relative_position_index[1:, 1:] = relative_coords.sum(-1) # Wh*Ww, Wh*Ww - relative_position_index[0, 0:] = self.num_relative_distance - 3 - relative_position_index[0:, 0] = self.num_relative_distance - 2 - relative_position_index[0, 0] = self.num_relative_distance - 1 - - self.register_buffer("relative_position_index", relative_position_index) - - # trunc_normal_(self.relative_position_bias_table, std=.0) - else: - self.window_size = None - self.relative_position_bias_table = None - self.relative_position_index = None - - self.attn_drop = nn.Dropout(attn_drop) - self.proj = nn.Linear(all_head_dim, dim) - self.proj_drop = nn.Dropout(proj_drop) - - def forward(self, x, rel_pos_bias=None, training_window_size=None): - B, N, C = x.shape - qkv_bias = None - if self.q_bias is not None: - qkv_bias = torch.cat((self.q_bias, torch.zeros_like(self.v_bias, requires_grad=False), self.v_bias)) - # qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4) - qkv = F.linear(input=x, weight=self.qkv.weight, bias=qkv_bias) - qkv = qkv.reshape(B, N, 3, self.num_heads, -1).permute(2, 0, 3, 1, 4) - q, k, v = qkv[0], qkv[1], qkv[2] # make torchscript happy (cannot use tensor as tuple) - - q = q * self.scale - attn = (q @ k.transpose(-2, -1)) - - if self.relative_position_bias_table is not None: - if training_window_size == self.window_size: - relative_position_bias = \ - self.relative_position_bias_table[self.relative_position_index.view(-1)].view( - self.window_size[0] * self.window_size[1] + 1, - self.window_size[0] * self.window_size[1] + 1, -1) # Wh*Ww,Wh*Ww,nH - relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww - attn = attn + relative_position_bias.unsqueeze(0) - else: - training_window_size = tuple(training_window_size.tolist()) - new_num_relative_distance = (2 * training_window_size[0] - 1) * (2 * training_window_size[1] - 1) + 3 - # new_num_relative_dis 为 所有可能的相对位置选项,包含cls-cls,tok-cls,与cls-tok - new_relative_position_bias_table = F.interpolate( - self.relative_position_bias_table[:-3, :].permute(1, 0).view(1, self.num_heads, - 2 * self.window_size[0] - 1, - 2 * self.window_size[1] - 1), - size=(2 * training_window_size[0] - 1, 2 * training_window_size[1] - 1), mode='bicubic', - align_corners=False) - new_relative_position_bias_table = new_relative_position_bias_table.view(self.num_heads, - new_num_relative_distance - 3).permute( - 1, 0) - new_relative_position_bias_table = torch.cat( - [new_relative_position_bias_table, self.relative_position_bias_table[-3::]], dim=0) - - # get pair-wise relative position index for each token inside the window - coords_h = torch.arange(training_window_size[0]) - coords_w = torch.arange(training_window_size[1]) - coords = torch.stack(torch.meshgrid([coords_h, coords_w])) # 2, Wh, Ww - coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww - relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww - relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2 - relative_coords[:, :, 0] += training_window_size[0] - 1 # shift to start from 0 - relative_coords[:, :, 1] += training_window_size[1] - 1 - relative_coords[:, :, 0] *= 2 * training_window_size[1] - 1 - relative_position_index = \ - torch.zeros(size=(training_window_size[0] * training_window_size[1] + 1,) * 2, - dtype=relative_coords.dtype) - relative_position_index[1:, 1:] = relative_coords.sum(-1) # Wh*Ww, Wh*Ww - relative_position_index[0, 0:] = new_num_relative_distance - 3 - relative_position_index[0:, 0] = new_num_relative_distance - 2 - relative_position_index[0, 0] = new_num_relative_distance - 1 - - relative_position_bias = \ - new_relative_position_bias_table[relative_position_index.view(-1)].view( - training_window_size[0] * training_window_size[1] + 1, - training_window_size[0] * training_window_size[1] + 1, -1) # Wh*Ww,Wh*Ww,nH - relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww - attn = attn + relative_position_bias.unsqueeze(0) - - if rel_pos_bias is not None: - attn = attn + rel_pos_bias - - attn = attn.softmax(dim=-1) - attn = self.attn_drop(attn) - - x = (attn @ v).transpose(1, 2).reshape(B, N, -1) - x = self.proj(x) - x = self.proj_drop(x) - return x - - -class Block(nn.Module): - - def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop=0., attn_drop=0., - drop_path=0., init_values=None, act_layer=nn.GELU, norm_layer=nn.LayerNorm, - window_size=None, attn_head_dim=None): - super().__init__() - self.norm1 = norm_layer(dim) - self.attn = Attention( - dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale, - attn_drop=attn_drop, proj_drop=drop, window_size=window_size, attn_head_dim=attn_head_dim) - # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here - self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity() - self.norm2 = norm_layer(dim) - mlp_hidden_dim = int(dim * mlp_ratio) - self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop) - - if init_values is not None: - self.gamma_1 = nn.Parameter(init_values * torch.ones((dim)), requires_grad=True) - self.gamma_2 = nn.Parameter(init_values * torch.ones((dim)), requires_grad=True) - else: - self.gamma_1, self.gamma_2 = None, None - - def forward(self, x, rel_pos_bias=None, training_window_size=None): - if self.gamma_1 is None: - x = x + self.drop_path( - self.attn(self.norm1(x), rel_pos_bias=rel_pos_bias, training_window_size=training_window_size)) - x = x + self.drop_path(self.mlp(self.norm2(x))) - else: - x = x + self.drop_path(self.gamma_1 * self.attn(self.norm1(x), rel_pos_bias=rel_pos_bias, - training_window_size=training_window_size)) - x = x + self.drop_path(self.gamma_2 * self.mlp(self.norm2(x))) - return x - - -class PatchEmbed(nn.Module): - """ Image to Patch Embedding - """ - - def __init__(self, img_size=[224, 224], patch_size=16, in_chans=3, embed_dim=768): - super().__init__() - img_size = to_2tuple(img_size) - patch_size = to_2tuple(patch_size) - num_patches = (img_size[1] // patch_size[1]) * (img_size[0] // patch_size[0]) - self.patch_shape = (img_size[0] // patch_size[0], img_size[1] // patch_size[1]) - self.num_patches_w = self.patch_shape[0] - self.num_patches_h = self.patch_shape[1] - # the so-called patch_shape is the patch shape during pre-training - self.img_size = img_size - self.patch_size = patch_size - self.num_patches = num_patches - - self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size) - - def forward(self, x, position_embedding=None, **kwargs): - # FIXME look at relaxing size constraints - # assert H == self.img_size[0] and W == self.img_size[1], \ - # f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})." - x = self.proj(x) - Hp, Wp = x.shape[2], x.shape[3] - - if position_embedding is not None: - # interpolate the position embedding to the corresponding size - position_embedding = position_embedding.view(1, self.patch_shape[0], self.patch_shape[1], -1).permute(0, 3, - 1, 2) - position_embedding = F.interpolate(position_embedding, size=(Hp, Wp), mode='bicubic') - x = x + position_embedding - - x = x.flatten(2).transpose(1, 2) - return x, (Hp, Wp) - - -class HybridEmbed(nn.Module): - """ CNN Feature Map Embedding - Extract feature map from CNN, flatten, project to embedding dim. - """ - - def __init__(self, backbone, img_size=[224, 224], feature_size=None, in_chans=3, embed_dim=768): - super().__init__() - assert isinstance(backbone, nn.Module) - img_size = to_2tuple(img_size) - self.img_size = img_size - self.backbone = backbone - if feature_size is None: - with torch.no_grad(): - # FIXME this is hacky, but most reliable way of determining the exact dim of the output feature - # map for all networks, the feature metadata has reliable channel and stride info, but using - # stride to calc feature dim requires info about padding of each stage that isn't captured. - training = backbone.training - if training: - backbone.eval() - o = self.backbone(torch.zeros(1, in_chans, img_size[0], img_size[1]))[-1] - feature_size = o.shape[-2:] - feature_dim = o.shape[1] - backbone.train(training) - else: - feature_size = to_2tuple(feature_size) - feature_dim = self.backbone.feature_info.channels()[-1] - self.num_patches = feature_size[0] * feature_size[1] - self.proj = nn.Linear(feature_dim, embed_dim) - - def forward(self, x): - x = self.backbone(x)[-1] - x = x.flatten(2).transpose(1, 2) - x = self.proj(x) - return x - - -class RelativePositionBias(nn.Module): - - def __init__(self, window_size, num_heads): - super().__init__() - self.window_size = window_size - self.num_heads = num_heads - self.num_relative_distance = (2 * window_size[0] - 1) * (2 * window_size[1] - 1) + 3 - self.relative_position_bias_table = nn.Parameter( - torch.zeros(self.num_relative_distance, num_heads)) # 2*Wh-1 * 2*Ww-1, nH - # cls to token & token 2 cls & cls to cls - - # get pair-wise relative position index for each token inside the window - coords_h = torch.arange(window_size[0]) - coords_w = torch.arange(window_size[1]) - coords = torch.stack(torch.meshgrid([coords_h, coords_w])) # 2, Wh, Ww - coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww - relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww - relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2 - relative_coords[:, :, 0] += window_size[0] - 1 # shift to start from 0 - relative_coords[:, :, 1] += window_size[1] - 1 - relative_coords[:, :, 0] *= 2 * window_size[1] - 1 - relative_position_index = \ - torch.zeros(size=(window_size[0] * window_size[1] + 1,) * 2, dtype=relative_coords.dtype) - relative_position_index[1:, 1:] = relative_coords.sum(-1) # Wh*Ww, Wh*Ww - relative_position_index[0, 0:] = self.num_relative_distance - 3 - relative_position_index[0:, 0] = self.num_relative_distance - 2 - relative_position_index[0, 0] = self.num_relative_distance - 1 - - self.register_buffer("relative_position_index", relative_position_index) - - # trunc_normal_(self.relative_position_bias_table, std=.02) - - def forward(self, training_window_size): - if training_window_size == self.window_size: - relative_position_bias = \ - self.relative_position_bias_table[self.relative_position_index.view(-1)].view( - self.window_size[0] * self.window_size[1] + 1, - self.window_size[0] * self.window_size[1] + 1, -1) # Wh*Ww,Wh*Ww,nH - relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww - else: - training_window_size = tuple(training_window_size.tolist()) - new_num_relative_distance = (2 * training_window_size[0] - 1) * (2 * training_window_size[1] - 1) + 3 - # new_num_relative_dis 为 所有可能的相对位置选项,包含cls-cls,tok-cls,与cls-tok - new_relative_position_bias_table = F.interpolate( - self.relative_position_bias_table[:-3, :].permute(1, 0).view(1, self.num_heads, - 2 * self.window_size[0] - 1, - 2 * self.window_size[1] - 1), - size=(2 * training_window_size[0] - 1, 2 * training_window_size[1] - 1), mode='bicubic', - align_corners=False) - new_relative_position_bias_table = new_relative_position_bias_table.view(self.num_heads, - new_num_relative_distance - 3).permute( - 1, 0) - new_relative_position_bias_table = torch.cat( - [new_relative_position_bias_table, self.relative_position_bias_table[-3::]], dim=0) - - # get pair-wise relative position index for each token inside the window - coords_h = torch.arange(training_window_size[0]) - coords_w = torch.arange(training_window_size[1]) - coords = torch.stack(torch.meshgrid([coords_h, coords_w])) # 2, Wh, Ww - coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww - relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww - relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2 - relative_coords[:, :, 0] += training_window_size[0] - 1 # shift to start from 0 - relative_coords[:, :, 1] += training_window_size[1] - 1 - relative_coords[:, :, 0] *= 2 * training_window_size[1] - 1 - relative_position_index = \ - torch.zeros(size=(training_window_size[0] * training_window_size[1] + 1,) * 2, - dtype=relative_coords.dtype) - relative_position_index[1:, 1:] = relative_coords.sum(-1) # Wh*Ww, Wh*Ww - relative_position_index[0, 0:] = new_num_relative_distance - 3 - relative_position_index[0:, 0] = new_num_relative_distance - 2 - relative_position_index[0, 0] = new_num_relative_distance - 1 - - relative_position_bias = \ - new_relative_position_bias_table[relative_position_index.view(-1)].view( - training_window_size[0] * training_window_size[1] + 1, - training_window_size[0] * training_window_size[1] + 1, -1) # Wh*Ww,Wh*Ww,nH - relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww - - return relative_position_bias - - -class BEiT(nn.Module): - """ Vision Transformer with support for patch or hybrid CNN input stage - """ - - def __init__(self, - img_size=[224, 224], - patch_size=16, - in_chans=3, - num_classes=80, - embed_dim=768, - depth=12, - num_heads=12, - mlp_ratio=4., - qkv_bias=False, - qk_scale=None, - drop_rate=0., - attn_drop_rate=0., - drop_path_rate=0., - hybrid_backbone=None, - norm_layer=None, - init_values=None, - use_abs_pos_emb=False, - use_rel_pos_bias=False, - use_shared_rel_pos_bias=False, - use_checkpoint=True, - pretrained=None, - out_features=None, - ): - - super(BEiT, self).__init__() - - norm_layer = norm_layer or partial(nn.LayerNorm, eps=1e-6) - self.num_classes = num_classes - self.num_features = self.embed_dim = embed_dim # num_features for consistency with other models - self.use_checkpoint = use_checkpoint - - if hybrid_backbone is not None: - self.patch_embed = HybridEmbed( - hybrid_backbone, img_size=img_size, in_chans=in_chans, embed_dim=embed_dim) - else: - self.patch_embed = PatchEmbed( - img_size=img_size, patch_size=patch_size, in_chans=in_chans, embed_dim=embed_dim) - num_patches = self.patch_embed.num_patches - self.out_features = out_features - self.out_indices = [int(name[5:]) for name in out_features] - - self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim)) - # self.mask_token = nn.Parameter(torch.zeros(1, 1, embed_dim)) - if use_abs_pos_emb: - self.pos_embed = nn.Parameter(torch.zeros(1, num_patches + 1, embed_dim)) - else: - self.pos_embed = None - self.pos_drop = nn.Dropout(p=drop_rate) - - self.use_shared_rel_pos_bias = use_shared_rel_pos_bias - if use_shared_rel_pos_bias: - self.rel_pos_bias = RelativePositionBias(window_size=self.patch_embed.patch_shape, num_heads=num_heads) - else: - self.rel_pos_bias = None - - dpr = [x.item() for x in torch.linspace(0, drop_path_rate, depth)] # stochastic depth decay rule - self.use_rel_pos_bias = use_rel_pos_bias - self.blocks = nn.ModuleList([ - Block( - dim=embed_dim, num_heads=num_heads, mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale, - drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i], norm_layer=norm_layer, - init_values=init_values, window_size=self.patch_embed.patch_shape if use_rel_pos_bias else None) - for i in range(depth)]) - - # trunc_normal_(self.mask_token, std=.02) - - if patch_size == 16: - self.fpn1 = nn.Sequential( - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - # nn.SyncBatchNorm(embed_dim), - nn.BatchNorm2d(embed_dim), - nn.GELU(), - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - ) - - self.fpn2 = nn.Sequential( - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - ) - - self.fpn3 = nn.Identity() - - self.fpn4 = nn.MaxPool2d(kernel_size=2, stride=2) - elif patch_size == 8: - self.fpn1 = nn.Sequential( - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - ) - - self.fpn2 = nn.Identity() - - self.fpn3 = nn.Sequential( - nn.MaxPool2d(kernel_size=2, stride=2), - ) - - self.fpn4 = nn.Sequential( - nn.MaxPool2d(kernel_size=4, stride=4), - ) - - if self.pos_embed is not None: - trunc_normal_(self.pos_embed, std=.02) - trunc_normal_(self.cls_token, std=.02) - self.apply(self._init_weights) - self.fix_init_weight() - - def fix_init_weight(self): - def rescale(param, layer_id): - param.div_(math.sqrt(2.0 * layer_id)) - - for layer_id, layer in enumerate(self.blocks): - rescale(layer.attn.proj.weight.data, layer_id + 1) - rescale(layer.mlp.fc2.weight.data, layer_id + 1) - - def _init_weights(self, m): - if isinstance(m, nn.Linear): - trunc_normal_(m.weight, std=.02) - if isinstance(m, nn.Linear) and m.bias is not None: - nn.init.constant_(m.bias, 0) - elif isinstance(m, nn.LayerNorm): - nn.init.constant_(m.bias, 0) - nn.init.constant_(m.weight, 1.0) - - ''' - def init_weights(self): - """Initialize the weights in backbone. - - Args: - pretrained (str, optional): Path to pre-trained weights. - Defaults to None. - """ - logger = get_root_logger() - - if self.pos_embed is not None: - trunc_normal_(self.pos_embed, std=.02) - trunc_normal_(self.cls_token, std=.02) - self.apply(self._init_weights) - self.fix_init_weight() - - if self.init_cfg is None: - logger.warn(f'No pre-trained weights for ' - f'{self.__class__.__name__}, ' - f'training start from scratch') - else: - assert 'checkpoint' in self.init_cfg, f'Only support ' \ - f'specify `Pretrained` in ' \ - f'`init_cfg` in ' \ - f'{self.__class__.__name__} ' - logger.info(f"Will load ckpt from {self.init_cfg['checkpoint']}") - load_checkpoint(self, - filename=self.init_cfg['checkpoint'], - strict=False, - logger=logger, - beit_spec_expand_rel_pos = self.use_rel_pos_bias, - ) - ''' - - def get_num_layers(self): - return len(self.blocks) - - @torch.jit.ignore - def no_weight_decay(self): - return {'pos_embed', 'cls_token'} - - def forward_features(self, x): - B, C, H, W = x.shape - x, (Hp, Wp) = self.patch_embed(x, self.pos_embed[:, 1:, :] if self.pos_embed is not None else None) - # Hp, Wp are HW for patches - batch_size, seq_len, _ = x.size() - - cls_tokens = self.cls_token.expand(batch_size, -1, -1) # stole cls_tokens impl from Phil Wang, thanks - if self.pos_embed is not None: - cls_tokens = cls_tokens + self.pos_embed[:, :1, :] - x = torch.cat((cls_tokens, x), dim=1) - x = self.pos_drop(x) - - features = [] - training_window_size = torch.tensor([Hp, Wp]) - - rel_pos_bias = self.rel_pos_bias(training_window_size) if self.rel_pos_bias is not None else None - - for i, blk in enumerate(self.blocks): - if self.use_checkpoint: - x = checkpoint.checkpoint(blk, x, rel_pos_bias, training_window_size) - else: - x = blk(x, rel_pos_bias=rel_pos_bias, training_window_size=training_window_size) - if i in self.out_indices: - xp = x[:, 1:, :].permute(0, 2, 1).reshape(B, -1, Hp, Wp) - features.append(xp.contiguous()) - - ops = [self.fpn1, self.fpn2, self.fpn3, self.fpn4] - for i in range(len(features)): - features[i] = ops[i](features[i]) - - feat_out = {} - - for name, value in zip(self.out_features, features): - feat_out[name] = value - - return feat_out - - def forward(self, x): - x = self.forward_features(x) - return x - - -def beit_base_patch16(pretrained=False, **kwargs): - model = BEiT( - patch_size=16, - embed_dim=768, - depth=12, - num_heads=12, - mlp_ratio=4, - qkv_bias=True, - norm_layer=partial(nn.LayerNorm, eps=1e-6), - init_values=None, - **kwargs) - model.default_cfg = _cfg() - return model - -def beit_large_patch16(pretrained=False, **kwargs): - model = BEiT( - patch_size=16, - embed_dim=1024, - depth=24, - num_heads=16, - mlp_ratio=4, - qkv_bias=True, - norm_layer=partial(nn.LayerNorm, eps=1e-6), - init_values=None, - **kwargs) - model.default_cfg = _cfg() - return model - -def dit_base_patch16(pretrained=False, **kwargs): - model = BEiT( - patch_size=16, - embed_dim=768, - depth=12, - num_heads=12, - mlp_ratio=4, - qkv_bias=True, - norm_layer=partial(nn.LayerNorm, eps=1e-6), - init_values=0.1, - **kwargs) - model.default_cfg = _cfg() - return model - -def dit_large_patch16(pretrained=False, **kwargs): - model = BEiT( - patch_size=16, - embed_dim=1024, - depth=24, - num_heads=16, - mlp_ratio=4, - qkv_bias=True, - norm_layer=partial(nn.LayerNorm, eps=1e-6), - init_values=1e-5, - **kwargs) - model.default_cfg = _cfg() - return model - -if __name__ == '__main__': - model = BEiT(use_checkpoint=True, use_shared_rel_pos_bias=True) - model = model.to("cuda:0") - input1 = torch.rand(2, 3, 512, 762).to("cuda:0") - input2 = torch.rand(2, 3, 800, 1200).to("cuda:0") - input3 = torch.rand(2, 3, 720, 1000).to("cuda:0") - output1 = model(input1) - output2 = model(input2) - output3 = model(input3) - print("all done") diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/deit.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/deit.py deleted file mode 100644 index 9a13bb0a8514df29fb4b0ec58c3726ba9c221a8a..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/deit.py +++ /dev/null @@ -1,476 +0,0 @@ -""" -Mostly copy-paste from DINO and timm library: -https://github.com/facebookresearch/dino -https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/vision_transformer.py -""" -import warnings - -import math -import torch -import torch.nn as nn -import torch.utils.checkpoint as checkpoint -from timm.models.layers import trunc_normal_, drop_path, to_2tuple -from functools import partial - -def _cfg(url='', **kwargs): - return { - 'url': url, - 'num_classes': 1000, 'input_size': (3, 224, 224), 'pool_size': None, - 'crop_pct': .9, 'interpolation': 'bicubic', - 'mean': (0.5, 0.5, 0.5), 'std': (0.5, 0.5, 0.5), - **kwargs - } - -class DropPath(nn.Module): - """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). - """ - - def __init__(self, drop_prob=None): - super(DropPath, self).__init__() - self.drop_prob = drop_prob - - def forward(self, x): - return drop_path(x, self.drop_prob, self.training) - - def extra_repr(self) -> str: - return 'p={}'.format(self.drop_prob) - - -class Mlp(nn.Module): - def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.): - super().__init__() - out_features = out_features or in_features - hidden_features = hidden_features or in_features - self.fc1 = nn.Linear(in_features, hidden_features) - self.act = act_layer() - self.fc2 = nn.Linear(hidden_features, out_features) - self.drop = nn.Dropout(drop) - - def forward(self, x): - x = self.fc1(x) - x = self.act(x) - x = self.drop(x) - x = self.fc2(x) - x = self.drop(x) - return x - - -class Attention(nn.Module): - def __init__(self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0., proj_drop=0.): - super().__init__() - self.num_heads = num_heads - head_dim = dim // num_heads - # NOTE scale factor was wrong in my original version, can set manually to be compat with prev weights - self.scale = qk_scale or head_dim ** -0.5 - - self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias) - self.attn_drop = nn.Dropout(attn_drop) - self.proj = nn.Linear(dim, dim) - self.proj_drop = nn.Dropout(proj_drop) - - def forward(self, x): - B, N, C = x.shape - q, k, v = self.qkv(x).reshape(B, N, 3, self.num_heads, - C // self.num_heads).permute(2, 0, 3, 1, 4) - - attn = (q @ k.transpose(-2, -1)) * self.scale - attn = attn.softmax(dim=-1) - attn = self.attn_drop(attn) - - x = (attn @ v).transpose(1, 2).reshape(B, N, C) - x = self.proj(x) - x = self.proj_drop(x) - return x - - -class Block(nn.Module): - - def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop=0., attn_drop=0., - drop_path=0., act_layer=nn.GELU, norm_layer=nn.LayerNorm): - super().__init__() - self.norm1 = norm_layer(dim) - self.attn = Attention( - dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop) - # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here - self.drop_path = DropPath( - drop_path) if drop_path > 0. else nn.Identity() - self.norm2 = norm_layer(dim) - mlp_hidden_dim = int(dim * mlp_ratio) - self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, - act_layer=act_layer, drop=drop) - - def forward(self, x): - x = x + self.drop_path(self.attn(self.norm1(x))) - x = x + self.drop_path(self.mlp(self.norm2(x))) - return x - - -class PatchEmbed(nn.Module): - """ Image to Patch Embedding - """ - - def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768): - super().__init__() - img_size = to_2tuple(img_size) - patch_size = to_2tuple(patch_size) - - self.window_size = (img_size[0] // patch_size[0], img_size[1] // patch_size[1]) - - self.num_patches_w, self.num_patches_h = self.window_size - - self.num_patches = self.window_size[0] * self.window_size[1] - self.img_size = img_size - self.patch_size = patch_size - - self.proj = nn.Conv2d(in_chans, embed_dim, - kernel_size=patch_size, stride=patch_size) - - def forward(self, x): - x = self.proj(x) - return x - - -class HybridEmbed(nn.Module): - """ CNN Feature Map Embedding - Extract feature map from CNN, flatten, project to embedding dim. - """ - - def __init__(self, backbone, img_size=224, feature_size=None, in_chans=3, embed_dim=768): - super().__init__() - assert isinstance(backbone, nn.Module) - img_size = to_2tuple(img_size) - self.img_size = img_size - self.backbone = backbone - if feature_size is None: - with torch.no_grad(): - # FIXME this is hacky, but most reliable way of determining the exact dim of the output feature - # map for all networks, the feature metadata has reliable channel and stride info, but using - # stride to calc feature dim requires info about padding of each stage that isn't captured. - training = backbone.training - if training: - backbone.eval() - o = self.backbone(torch.zeros( - 1, in_chans, img_size[0], img_size[1]))[-1] - feature_size = o.shape[-2:] - feature_dim = o.shape[1] - backbone.train(training) - else: - feature_size = to_2tuple(feature_size) - feature_dim = self.backbone.feature_info.channels()[-1] - self.num_patches = feature_size[0] * feature_size[1] - self.proj = nn.Linear(feature_dim, embed_dim) - - def forward(self, x): - x = self.backbone(x)[-1] - x = x.flatten(2).transpose(1, 2) - x = self.proj(x) - return x - - -class ViT(nn.Module): - """ Vision Transformer with support for patch or hybrid CNN input stage - """ - - def __init__(self, - model_name='vit_base_patch16_224', - img_size=384, - patch_size=16, - in_chans=3, - embed_dim=1024, - depth=24, - num_heads=16, - num_classes=19, - mlp_ratio=4., - qkv_bias=True, - qk_scale=None, - drop_rate=0.1, - attn_drop_rate=0., - drop_path_rate=0., - hybrid_backbone=None, - norm_layer=partial(nn.LayerNorm, eps=1e-6), - norm_cfg=None, - pos_embed_interp=False, - random_init=False, - align_corners=False, - use_checkpoint=False, - num_extra_tokens=1, - out_features=None, - **kwargs, - ): - - super(ViT, self).__init__() - self.model_name = model_name - self.img_size = img_size - self.patch_size = patch_size - self.in_chans = in_chans - self.embed_dim = embed_dim - self.depth = depth - self.num_heads = num_heads - self.num_classes = num_classes - self.mlp_ratio = mlp_ratio - self.qkv_bias = qkv_bias - self.qk_scale = qk_scale - self.drop_rate = drop_rate - self.attn_drop_rate = attn_drop_rate - self.drop_path_rate = drop_path_rate - self.hybrid_backbone = hybrid_backbone - self.norm_layer = norm_layer - self.norm_cfg = norm_cfg - self.pos_embed_interp = pos_embed_interp - self.random_init = random_init - self.align_corners = align_corners - self.use_checkpoint = use_checkpoint - self.num_extra_tokens = num_extra_tokens - self.out_features = out_features - self.out_indices = [int(name[5:]) for name in out_features] - - # self.num_stages = self.depth - # self.out_indices = tuple(range(self.num_stages)) - - if self.hybrid_backbone is not None: - self.patch_embed = HybridEmbed( - self.hybrid_backbone, img_size=self.img_size, in_chans=self.in_chans, embed_dim=self.embed_dim) - else: - self.patch_embed = PatchEmbed( - img_size=self.img_size, patch_size=self.patch_size, in_chans=self.in_chans, embed_dim=self.embed_dim) - self.num_patches = self.patch_embed.num_patches - - self.cls_token = nn.Parameter(torch.zeros(1, 1, self.embed_dim)) - - if self.num_extra_tokens == 2: - self.dist_token = nn.Parameter(torch.zeros(1, 1, self.embed_dim)) - - self.pos_embed = nn.Parameter(torch.zeros( - 1, self.num_patches + self.num_extra_tokens, self.embed_dim)) - self.pos_drop = nn.Dropout(p=self.drop_rate) - - # self.num_extra_tokens = self.pos_embed.shape[-2] - self.num_patches - dpr = [x.item() for x in torch.linspace(0, self.drop_path_rate, - self.depth)] # stochastic depth decay rule - self.blocks = nn.ModuleList([ - Block( - dim=self.embed_dim, num_heads=self.num_heads, mlp_ratio=self.mlp_ratio, qkv_bias=self.qkv_bias, - qk_scale=self.qk_scale, - drop=self.drop_rate, attn_drop=self.attn_drop_rate, drop_path=dpr[i], norm_layer=self.norm_layer) - for i in range(self.depth)]) - - # NOTE as per official impl, we could have a pre-logits representation dense layer + tanh here - # self.repr = nn.Linear(embed_dim, representation_size) - # self.repr_act = nn.Tanh() - - if patch_size == 16: - self.fpn1 = nn.Sequential( - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - nn.SyncBatchNorm(embed_dim), - nn.GELU(), - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - ) - - self.fpn2 = nn.Sequential( - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - ) - - self.fpn3 = nn.Identity() - - self.fpn4 = nn.MaxPool2d(kernel_size=2, stride=2) - elif patch_size == 8: - self.fpn1 = nn.Sequential( - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - ) - - self.fpn2 = nn.Identity() - - self.fpn3 = nn.Sequential( - nn.MaxPool2d(kernel_size=2, stride=2), - ) - - self.fpn4 = nn.Sequential( - nn.MaxPool2d(kernel_size=4, stride=4), - ) - - trunc_normal_(self.pos_embed, std=.02) - trunc_normal_(self.cls_token, std=.02) - if self.num_extra_tokens==2: - trunc_normal_(self.dist_token, std=0.2) - self.apply(self._init_weights) - # self.fix_init_weight() - - def fix_init_weight(self): - def rescale(param, layer_id): - param.div_(math.sqrt(2.0 * layer_id)) - - for layer_id, layer in enumerate(self.blocks): - rescale(layer.attn.proj.weight.data, layer_id + 1) - rescale(layer.mlp.fc2.weight.data, layer_id + 1) - - def _init_weights(self, m): - if isinstance(m, nn.Linear): - trunc_normal_(m.weight, std=.02) - if isinstance(m, nn.Linear) and m.bias is not None: - nn.init.constant_(m.bias, 0) - elif isinstance(m, nn.LayerNorm): - nn.init.constant_(m.bias, 0) - nn.init.constant_(m.weight, 1.0) - - ''' - def init_weights(self): - logger = get_root_logger() - - trunc_normal_(self.pos_embed, std=.02) - trunc_normal_(self.cls_token, std=.02) - self.apply(self._init_weights) - - if self.init_cfg is None: - logger.warn(f'No pre-trained weights for ' - f'{self.__class__.__name__}, ' - f'training start from scratch') - else: - assert 'checkpoint' in self.init_cfg, f'Only support ' \ - f'specify `Pretrained` in ' \ - f'`init_cfg` in ' \ - f'{self.__class__.__name__} ' - logger.info(f"Will load ckpt from {self.init_cfg['checkpoint']}") - load_checkpoint(self, filename=self.init_cfg['checkpoint'], strict=False, logger=logger) - ''' - - def get_num_layers(self): - return len(self.blocks) - - @torch.jit.ignore - def no_weight_decay(self): - return {'pos_embed', 'cls_token'} - - def _conv_filter(self, state_dict, patch_size=16): - """ convert patch embedding weight from manual patchify + linear proj to conv""" - out_dict = {} - for k, v in state_dict.items(): - if 'patch_embed.proj.weight' in k: - v = v.reshape((v.shape[0], 3, patch_size, patch_size)) - out_dict[k] = v - return out_dict - - def to_2D(self, x): - n, hw, c = x.shape - h = w = int(math.sqrt(hw)) - x = x.transpose(1, 2).reshape(n, c, h, w) - return x - - def to_1D(self, x): - n, c, h, w = x.shape - x = x.reshape(n, c, -1).transpose(1, 2) - return x - - def interpolate_pos_encoding(self, x, w, h): - npatch = x.shape[1] - self.num_extra_tokens - N = self.pos_embed.shape[1] - self.num_extra_tokens - if npatch == N and w == h: - return self.pos_embed - - class_ORdist_pos_embed = self.pos_embed[:, 0:self.num_extra_tokens] - - patch_pos_embed = self.pos_embed[:, self.num_extra_tokens:] - - dim = x.shape[-1] - w0 = w // self.patch_embed.patch_size[0] - h0 = h // self.patch_embed.patch_size[1] - # we add a small number to avoid floating point error in the interpolation - # see discussion at https://github.com/facebookresearch/dino/issues/8 - w0, h0 = w0 + 0.1, h0 + 0.1 - patch_pos_embed = nn.functional.interpolate( - patch_pos_embed.reshape(1, int(math.sqrt(N)), int(math.sqrt(N)), dim).permute(0, 3, 1, 2), - scale_factor=(w0 / math.sqrt(N), h0 / math.sqrt(N)), - mode='bicubic', - ) - assert int(w0) == patch_pos_embed.shape[-2] and int(h0) == patch_pos_embed.shape[-1] - patch_pos_embed = patch_pos_embed.permute(0, 2, 3, 1).view(1, -1, dim) - - return torch.cat((class_ORdist_pos_embed, patch_pos_embed), dim=1) - - def prepare_tokens(self, x, mask=None): - B, nc, w, h = x.shape - # patch linear embedding - x = self.patch_embed(x) - - # mask image modeling - if mask is not None: - x = self.mask_model(x, mask) - x = x.flatten(2).transpose(1, 2) - - # add the [CLS] token to the embed patch tokens - all_tokens = [self.cls_token.expand(B, -1, -1)] - - if self.num_extra_tokens == 2: - dist_tokens = self.dist_token.expand(B, -1, -1) - all_tokens.append(dist_tokens) - all_tokens.append(x) - - x = torch.cat(all_tokens, dim=1) - - # add positional encoding to each token - x = x + self.interpolate_pos_encoding(x, w, h) - - return self.pos_drop(x) - - def forward_features(self, x): - # print(f"==========shape of x is {x.shape}==========") - B, _, H, W = x.shape - Hp, Wp = H // self.patch_size, W // self.patch_size - x = self.prepare_tokens(x) - - features = [] - for i, blk in enumerate(self.blocks): - if self.use_checkpoint: - x = checkpoint.checkpoint(blk, x) - else: - x = blk(x) - if i in self.out_indices: - xp = x[:, self.num_extra_tokens:, :].permute(0, 2, 1).reshape(B, -1, Hp, Wp) - features.append(xp.contiguous()) - - ops = [self.fpn1, self.fpn2, self.fpn3, self.fpn4] - for i in range(len(features)): - features[i] = ops[i](features[i]) - - feat_out = {} - - for name, value in zip(self.out_features, features): - feat_out[name] = value - - return feat_out - - def forward(self, x): - x = self.forward_features(x) - return x - - -def deit_base_patch16(pretrained=False, **kwargs): - model = ViT( - patch_size=16, - drop_rate=0., - embed_dim=768, - depth=12, - num_heads=12, - num_classes=1000, - mlp_ratio=4., - qkv_bias=True, - use_checkpoint=True, - num_extra_tokens=2, - **kwargs) - model.default_cfg = _cfg() - return model - -def mae_base_patch16(pretrained=False, **kwargs): - model = ViT( - patch_size=16, - drop_rate=0., - embed_dim=768, - depth=12, - num_heads=12, - num_classes=1000, - mlp_ratio=4., - qkv_bias=True, - use_checkpoint=True, - num_extra_tokens=1, - **kwargs) - model.default_cfg = _cfg() - return model \ No newline at end of file diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/__init__.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/__init__.py deleted file mode 100644 index cd997b55f3118a01f5d49ae2f080525c7d7c9534..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from .models import ( - LayoutLMv3Config, - LayoutLMv3ForTokenClassification, - LayoutLMv3ForQuestionAnswering, - LayoutLMv3ForSequenceClassification, - LayoutLMv3Tokenizer, -) diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/__init__.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/__init__.py deleted file mode 100644 index 5bcec6c7c65b7add5c3440f106b8f1049781167a..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# flake8: noqa -from .data_collator import DataCollatorForKeyValueExtraction diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/cord.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/cord.py deleted file mode 100644 index 820dc53a4ea8bc79ddac2d36b57ea2110e8d27d5..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/cord.py +++ /dev/null @@ -1,171 +0,0 @@ -''' -Reference: https://huggingface.co/datasets/pierresi/cord/blob/main/cord.py -''' - - -import json -import os -from pathlib import Path -import datasets -from .image_utils import load_image, normalize_bbox -logger = datasets.logging.get_logger(__name__) -_CITATION = """\ -@article{park2019cord, - title={CORD: A Consolidated Receipt Dataset for Post-OCR Parsing}, - author={Park, Seunghyun and Shin, Seung and Lee, Bado and Lee, Junyeop and Surh, Jaeheung and Seo, Minjoon and Lee, Hwalsuk} - booktitle={Document Intelligence Workshop at Neural Information Processing Systems} - year={2019} -} -""" -_DESCRIPTION = """\ -https://github.com/clovaai/cord/ -""" - -def quad_to_box(quad): - # test 87 is wrongly annotated - box = ( - max(0, quad["x1"]), - max(0, quad["y1"]), - quad["x3"], - quad["y3"] - ) - if box[3] < box[1]: - bbox = list(box) - tmp = bbox[3] - bbox[3] = bbox[1] - bbox[1] = tmp - box = tuple(bbox) - if box[2] < box[0]: - bbox = list(box) - tmp = bbox[2] - bbox[2] = bbox[0] - bbox[0] = tmp - box = tuple(bbox) - return box - -def _get_drive_url(url): - base_url = 'https://drive.google.com/uc?id=' - split_url = url.split('/') - return base_url + split_url[5] - -_URLS = [ - _get_drive_url("https://drive.google.com/file/d/1MqhTbcj-AHXOqYoeoh12aRUwIprzTJYI/"), - _get_drive_url("https://drive.google.com/file/d/1wYdp5nC9LnHQZ2FcmOoC0eClyWvcuARU/") - # If you failed to download the dataset through the automatic downloader, - # you can download it manually and modify the code to get the local dataset. - # Or you can use the following links. Please follow the original LICENSE of CORD for usage. - # "https://layoutlm.blob.core.windows.net/cord/CORD-1k-001.zip", - # "https://layoutlm.blob.core.windows.net/cord/CORD-1k-002.zip" -] - -class CordConfig(datasets.BuilderConfig): - """BuilderConfig for CORD""" - def __init__(self, **kwargs): - """BuilderConfig for CORD. - Args: - **kwargs: keyword arguments forwarded to super. - """ - super(CordConfig, self).__init__(**kwargs) - -class Cord(datasets.GeneratorBasedBuilder): - BUILDER_CONFIGS = [ - CordConfig(name="cord", version=datasets.Version("1.0.0"), description="CORD dataset"), - ] - - def _info(self): - return datasets.DatasetInfo( - description=_DESCRIPTION, - features=datasets.Features( - { - "id": datasets.Value("string"), - "words": datasets.Sequence(datasets.Value("string")), - "bboxes": datasets.Sequence(datasets.Sequence(datasets.Value("int64"))), - "ner_tags": datasets.Sequence( - datasets.features.ClassLabel( - names=["O","B-MENU.NM","B-MENU.NUM","B-MENU.UNITPRICE","B-MENU.CNT","B-MENU.DISCOUNTPRICE","B-MENU.PRICE","B-MENU.ITEMSUBTOTAL","B-MENU.VATYN","B-MENU.ETC","B-MENU.SUB_NM","B-MENU.SUB_UNITPRICE","B-MENU.SUB_CNT","B-MENU.SUB_PRICE","B-MENU.SUB_ETC","B-VOID_MENU.NM","B-VOID_MENU.PRICE","B-SUB_TOTAL.SUBTOTAL_PRICE","B-SUB_TOTAL.DISCOUNT_PRICE","B-SUB_TOTAL.SERVICE_PRICE","B-SUB_TOTAL.OTHERSVC_PRICE","B-SUB_TOTAL.TAX_PRICE","B-SUB_TOTAL.ETC","B-TOTAL.TOTAL_PRICE","B-TOTAL.TOTAL_ETC","B-TOTAL.CASHPRICE","B-TOTAL.CHANGEPRICE","B-TOTAL.CREDITCARDPRICE","B-TOTAL.EMONEYPRICE","B-TOTAL.MENUTYPE_CNT","B-TOTAL.MENUQTY_CNT","I-MENU.NM","I-MENU.NUM","I-MENU.UNITPRICE","I-MENU.CNT","I-MENU.DISCOUNTPRICE","I-MENU.PRICE","I-MENU.ITEMSUBTOTAL","I-MENU.VATYN","I-MENU.ETC","I-MENU.SUB_NM","I-MENU.SUB_UNITPRICE","I-MENU.SUB_CNT","I-MENU.SUB_PRICE","I-MENU.SUB_ETC","I-VOID_MENU.NM","I-VOID_MENU.PRICE","I-SUB_TOTAL.SUBTOTAL_PRICE","I-SUB_TOTAL.DISCOUNT_PRICE","I-SUB_TOTAL.SERVICE_PRICE","I-SUB_TOTAL.OTHERSVC_PRICE","I-SUB_TOTAL.TAX_PRICE","I-SUB_TOTAL.ETC","I-TOTAL.TOTAL_PRICE","I-TOTAL.TOTAL_ETC","I-TOTAL.CASHPRICE","I-TOTAL.CHANGEPRICE","I-TOTAL.CREDITCARDPRICE","I-TOTAL.EMONEYPRICE","I-TOTAL.MENUTYPE_CNT","I-TOTAL.MENUQTY_CNT"] - ) - ), - "image": datasets.Array3D(shape=(3, 224, 224), dtype="uint8"), - "image_path": datasets.Value("string"), - } - ), - supervised_keys=None, - citation=_CITATION, - homepage="https://github.com/clovaai/cord/", - ) - - def _split_generators(self, dl_manager): - """Returns SplitGenerators.""" - """Uses local files located with data_dir""" - downloaded_file = dl_manager.download_and_extract(_URLS) - # move files from the second URL together with files from the first one. - dest = Path(downloaded_file[0])/"CORD" - for split in ["train", "dev", "test"]: - for file_type in ["image", "json"]: - if split == "test" and file_type == "json": - continue - files = (Path(downloaded_file[1])/"CORD"/split/file_type).iterdir() - for f in files: - os.rename(f, dest/split/file_type/f.name) - return [ - datasets.SplitGenerator( - name=datasets.Split.TRAIN, gen_kwargs={"filepath": dest/"train"} - ), - datasets.SplitGenerator( - name=datasets.Split.VALIDATION, gen_kwargs={"filepath": dest/"dev"} - ), - datasets.SplitGenerator( - name=datasets.Split.TEST, gen_kwargs={"filepath": dest/"test"} - ), - ] - - def get_line_bbox(self, bboxs): - x = [bboxs[i][j] for i in range(len(bboxs)) for j in range(0, len(bboxs[i]), 2)] - y = [bboxs[i][j] for i in range(len(bboxs)) for j in range(1, len(bboxs[i]), 2)] - - x0, y0, x1, y1 = min(x), min(y), max(x), max(y) - - assert x1 >= x0 and y1 >= y0 - bbox = [[x0, y0, x1, y1] for _ in range(len(bboxs))] - return bbox - - def _generate_examples(self, filepath): - logger.info("⏳ Generating examples from = %s", filepath) - ann_dir = os.path.join(filepath, "json") - img_dir = os.path.join(filepath, "image") - for guid, file in enumerate(sorted(os.listdir(ann_dir))): - words = [] - bboxes = [] - ner_tags = [] - file_path = os.path.join(ann_dir, file) - with open(file_path, "r", encoding="utf8") as f: - data = json.load(f) - image_path = os.path.join(img_dir, file) - image_path = image_path.replace("json", "png") - image, size = load_image(image_path) - for item in data["valid_line"]: - cur_line_bboxes = [] - line_words, label = item["words"], item["category"] - line_words = [w for w in line_words if w["text"].strip() != ""] - if len(line_words) == 0: - continue - if label == "other": - for w in line_words: - words.append(w["text"]) - ner_tags.append("O") - cur_line_bboxes.append(normalize_bbox(quad_to_box(w["quad"]), size)) - else: - words.append(line_words[0]["text"]) - ner_tags.append("B-" + label.upper()) - cur_line_bboxes.append(normalize_bbox(quad_to_box(line_words[0]["quad"]), size)) - for w in line_words[1:]: - words.append(w["text"]) - ner_tags.append("I-" + label.upper()) - cur_line_bboxes.append(normalize_bbox(quad_to_box(w["quad"]), size)) - # by default: --segment_level_layout 1 - # if do not want to use segment_level_layout, comment the following line - cur_line_bboxes = self.get_line_bbox(cur_line_bboxes) - bboxes.extend(cur_line_bboxes) - # yield guid, {"id": str(guid), "words": words, "bboxes": bboxes, "ner_tags": ner_tags, "image": image} - yield guid, {"id": str(guid), "words": words, "bboxes": bboxes, "ner_tags": ner_tags, - "image": image, "image_path": image_path} diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/data_collator.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/data_collator.py deleted file mode 100644 index 4232a6660ba2678ba20be5479629550419a798b4..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/data_collator.py +++ /dev/null @@ -1,124 +0,0 @@ -import torch -from dataclasses import dataclass -from typing import Any, Dict, List, Optional, Tuple, Union - -from transformers import BatchEncoding, PreTrainedTokenizerBase -from transformers.data.data_collator import ( - DataCollatorMixin, - _torch_collate_batch, -) -from transformers.file_utils import PaddingStrategy - -from typing import NewType -InputDataClass = NewType("InputDataClass", Any) - -def pre_calc_rel_mat(segment_ids): - valid_span = torch.zeros((segment_ids.shape[0], segment_ids.shape[1], segment_ids.shape[1]), - device=segment_ids.device, dtype=torch.bool) - for i in range(segment_ids.shape[0]): - for j in range(segment_ids.shape[1]): - valid_span[i, j, :] = segment_ids[i, :] == segment_ids[i, j] - - return valid_span - -@dataclass -class DataCollatorForKeyValueExtraction(DataCollatorMixin): - """ - Data collator that will dynamically pad the inputs received, as well as the labels. - Args: - tokenizer (:class:`~transformers.PreTrainedTokenizer` or :class:`~transformers.PreTrainedTokenizerFast`): - The tokenizer used for encoding the data. - padding (:obj:`bool`, :obj:`str` or :class:`~transformers.file_utils.PaddingStrategy`, `optional`, defaults to :obj:`True`): - Select a strategy to pad the returned sequences (according to the model's padding side and padding index) - among: - * :obj:`True` or :obj:`'longest'`: Pad to the longest sequence in the batch (or no padding if only a single - sequence if provided). - * :obj:`'max_length'`: Pad to a maximum length specified with the argument :obj:`max_length` or to the - maximum acceptable input length for the model if that argument is not provided. - * :obj:`False` or :obj:`'do_not_pad'` (default): No padding (i.e., can output a batch with sequences of - different lengths). - max_length (:obj:`int`, `optional`): - Maximum length of the returned list and optionally padding length (see above). - pad_to_multiple_of (:obj:`int`, `optional`): - If set will pad the sequence to a multiple of the provided value. - This is especially useful to enable the use of Tensor Cores on NVIDIA hardware with compute capability >= - 7.5 (Volta). - label_pad_token_id (:obj:`int`, `optional`, defaults to -100): - The id to use when padding the labels (-100 will be automatically ignore by PyTorch loss functions). - """ - - tokenizer: PreTrainedTokenizerBase - padding: Union[bool, str, PaddingStrategy] = True - max_length: Optional[int] = None - pad_to_multiple_of: Optional[int] = None - label_pad_token_id: int = -100 - - def __call__(self, features): - label_name = "label" if "label" in features[0].keys() else "labels" - labels = [feature[label_name] for feature in features] if label_name in features[0].keys() else None - - images = None - if "images" in features[0]: - images = torch.stack([torch.tensor(d.pop("images")) for d in features]) - IMAGE_LEN = int(images.shape[-1] / 16) * int(images.shape[-1] / 16) + 1 - - batch = self.tokenizer.pad( - features, - padding=self.padding, - max_length=self.max_length, - pad_to_multiple_of=self.pad_to_multiple_of, - # Conversion to tensors will fail if we have labels as they are not of the same length yet. - return_tensors="pt" if labels is None else None, - ) - - if images is not None: - batch["images"] = images - batch = {k: torch.tensor(v, dtype=torch.int64) if isinstance(v[0], list) and k == 'attention_mask' else v - for k, v in batch.items()} - visual_attention_mask = torch.ones((len(batch['input_ids']), IMAGE_LEN), dtype=torch.long) - batch["attention_mask"] = torch.cat([batch['attention_mask'], visual_attention_mask], dim=1) - - if labels is None: - return batch - - has_bbox_input = "bbox" in features[0] - has_position_input = "position_ids" in features[0] - padding_idx=self.tokenizer.pad_token_id - sequence_length = torch.tensor(batch["input_ids"]).shape[1] - padding_side = self.tokenizer.padding_side - if padding_side == "right": - batch["labels"] = [label + [self.label_pad_token_id] * (sequence_length - len(label)) for label in labels] - if has_bbox_input: - batch["bbox"] = [bbox + [[0, 0, 0, 0]] * (sequence_length - len(bbox)) for bbox in batch["bbox"]] - if has_position_input: - batch["position_ids"] = [position_id + [padding_idx] * (sequence_length - len(position_id)) - for position_id in batch["position_ids"]] - - else: - batch["labels"] = [[self.label_pad_token_id] * (sequence_length - len(label)) + label for label in labels] - if has_bbox_input: - batch["bbox"] = [[[0, 0, 0, 0]] * (sequence_length - len(bbox)) + bbox for bbox in batch["bbox"]] - if has_position_input: - batch["position_ids"] = [[padding_idx] * (sequence_length - len(position_id)) - + position_id for position_id in batch["position_ids"]] - - if 'segment_ids' in batch: - assert 'position_ids' in batch - for i in range(len(batch['segment_ids'])): - batch['segment_ids'][i] = batch['segment_ids'][i] + [batch['segment_ids'][i][-1] + 1] * (sequence_length - len(batch['segment_ids'][i])) + [ - batch['segment_ids'][i][-1] + 2] * IMAGE_LEN - - batch = {k: torch.tensor(v, dtype=torch.int64) if isinstance(v[0], list) else v for k, v in batch.items()} - - if 'segment_ids' in batch: - valid_span = pre_calc_rel_mat( - segment_ids=batch['segment_ids'] - ) - batch['valid_span'] = valid_span - del batch['segment_ids'] - - if images is not None: - visual_labels = torch.ones((len(batch['input_ids']), IMAGE_LEN), dtype=torch.long) * -100 - batch["labels"] = torch.cat([batch['labels'], visual_labels], dim=1) - - return batch diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/funsd.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/funsd.py deleted file mode 100644 index 9f34042023042b10d52906d4ba5ca9c87e65a600..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/funsd.py +++ /dev/null @@ -1,136 +0,0 @@ -# coding=utf-8 -''' -Reference: https://huggingface.co/datasets/nielsr/funsd/blob/main/funsd.py -''' -import json -import os - -import datasets - -from .image_utils import load_image, normalize_bbox - - -logger = datasets.logging.get_logger(__name__) - - -_CITATION = """\ -@article{Jaume2019FUNSDAD, - title={FUNSD: A Dataset for Form Understanding in Noisy Scanned Documents}, - author={Guillaume Jaume and H. K. Ekenel and J. Thiran}, - journal={2019 International Conference on Document Analysis and Recognition Workshops (ICDARW)}, - year={2019}, - volume={2}, - pages={1-6} -} -""" - -_DESCRIPTION = """\ -https://guillaumejaume.github.io/FUNSD/ -""" - - -class FunsdConfig(datasets.BuilderConfig): - """BuilderConfig for FUNSD""" - - def __init__(self, **kwargs): - """BuilderConfig for FUNSD. - - Args: - **kwargs: keyword arguments forwarded to super. - """ - super(FunsdConfig, self).__init__(**kwargs) - - -class Funsd(datasets.GeneratorBasedBuilder): - """Conll2003 dataset.""" - - BUILDER_CONFIGS = [ - FunsdConfig(name="funsd", version=datasets.Version("1.0.0"), description="FUNSD dataset"), - ] - - def _info(self): - return datasets.DatasetInfo( - description=_DESCRIPTION, - features=datasets.Features( - { - "id": datasets.Value("string"), - "tokens": datasets.Sequence(datasets.Value("string")), - "bboxes": datasets.Sequence(datasets.Sequence(datasets.Value("int64"))), - "ner_tags": datasets.Sequence( - datasets.features.ClassLabel( - names=["O", "B-HEADER", "I-HEADER", "B-QUESTION", "I-QUESTION", "B-ANSWER", "I-ANSWER"] - ) - ), - "image": datasets.Array3D(shape=(3, 224, 224), dtype="uint8"), - "image_path": datasets.Value("string"), - } - ), - supervised_keys=None, - homepage="https://guillaumejaume.github.io/FUNSD/", - citation=_CITATION, - ) - - def _split_generators(self, dl_manager): - """Returns SplitGenerators.""" - downloaded_file = dl_manager.download_and_extract("https://guillaumejaume.github.io/FUNSD/dataset.zip") - return [ - datasets.SplitGenerator( - name=datasets.Split.TRAIN, gen_kwargs={"filepath": f"{downloaded_file}/dataset/training_data/"} - ), - datasets.SplitGenerator( - name=datasets.Split.TEST, gen_kwargs={"filepath": f"{downloaded_file}/dataset/testing_data/"} - ), - ] - - def get_line_bbox(self, bboxs): - x = [bboxs[i][j] for i in range(len(bboxs)) for j in range(0, len(bboxs[i]), 2)] - y = [bboxs[i][j] for i in range(len(bboxs)) for j in range(1, len(bboxs[i]), 2)] - - x0, y0, x1, y1 = min(x), min(y), max(x), max(y) - - assert x1 >= x0 and y1 >= y0 - bbox = [[x0, y0, x1, y1] for _ in range(len(bboxs))] - return bbox - - def _generate_examples(self, filepath): - logger.info("⏳ Generating examples from = %s", filepath) - ann_dir = os.path.join(filepath, "annotations") - img_dir = os.path.join(filepath, "images") - for guid, file in enumerate(sorted(os.listdir(ann_dir))): - tokens = [] - bboxes = [] - ner_tags = [] - - file_path = os.path.join(ann_dir, file) - with open(file_path, "r", encoding="utf8") as f: - data = json.load(f) - image_path = os.path.join(img_dir, file) - image_path = image_path.replace("json", "png") - image, size = load_image(image_path) - for item in data["form"]: - cur_line_bboxes = [] - words, label = item["words"], item["label"] - words = [w for w in words if w["text"].strip() != ""] - if len(words) == 0: - continue - if label == "other": - for w in words: - tokens.append(w["text"]) - ner_tags.append("O") - cur_line_bboxes.append(normalize_bbox(w["box"], size)) - else: - tokens.append(words[0]["text"]) - ner_tags.append("B-" + label.upper()) - cur_line_bboxes.append(normalize_bbox(words[0]["box"], size)) - for w in words[1:]: - tokens.append(w["text"]) - ner_tags.append("I-" + label.upper()) - cur_line_bboxes.append(normalize_bbox(w["box"], size)) - # by default: --segment_level_layout 1 - # if do not want to use segment_level_layout, comment the following line - cur_line_bboxes = self.get_line_bbox(cur_line_bboxes) - # box = normalize_bbox(item["box"], size) - # cur_line_bboxes = [box for _ in range(len(words))] - bboxes.extend(cur_line_bboxes) - yield guid, {"id": str(guid), "tokens": tokens, "bboxes": bboxes, "ner_tags": ner_tags, - "image": image, "image_path": image_path} \ No newline at end of file diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/image_utils.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/image_utils.py deleted file mode 100644 index 90a4b34373980246d6397b95b91e84461f3f2580..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/image_utils.py +++ /dev/null @@ -1,284 +0,0 @@ -import torchvision.transforms.functional as F -import warnings -import math -import random -import numpy as np -from PIL import Image -import torch - -from detectron2.data.detection_utils import read_image -from detectron2.data.transforms import ResizeTransform, TransformList - -def normalize_bbox(bbox, size): - return [ - int(1000 * bbox[0] / size[0]), - int(1000 * bbox[1] / size[1]), - int(1000 * bbox[2] / size[0]), - int(1000 * bbox[3] / size[1]), - ] - - -def load_image(image_path): - image = read_image(image_path, format="BGR") - h = image.shape[0] - w = image.shape[1] - img_trans = TransformList([ResizeTransform(h=h, w=w, new_h=224, new_w=224)]) - image = torch.tensor(img_trans.apply_image(image).copy()).permute(2, 0, 1) # copy to make it writeable - return image, (w, h) - - -def crop(image, i, j, h, w, boxes=None): - cropped_image = F.crop(image, i, j, h, w) - - if boxes is not None: - # Currently we cannot use this case since when some boxes is out of the cropped image, - # it may be better to drop out these boxes along with their text input (instead of min or clamp) - # which haven't been implemented here - max_size = torch.as_tensor([w, h], dtype=torch.float32) - cropped_boxes = torch.as_tensor(boxes) - torch.as_tensor([j, i, j, i]) - cropped_boxes = torch.min(cropped_boxes.reshape(-1, 2, 2), max_size) - cropped_boxes = cropped_boxes.clamp(min=0) - boxes = cropped_boxes.reshape(-1, 4) - - return cropped_image, boxes - - -def resize(image, size, interpolation, boxes=None): - # It seems that we do not need to resize boxes here, since the boxes will be resized to 1000x1000 finally, - # which is compatible with a square image size of 224x224 - rescaled_image = F.resize(image, size, interpolation) - - if boxes is None: - return rescaled_image, None - - ratios = tuple(float(s) / float(s_orig) for s, s_orig in zip(rescaled_image.size, image.size)) - ratio_width, ratio_height = ratios - - # boxes = boxes.copy() - scaled_boxes = boxes * torch.as_tensor([ratio_width, ratio_height, ratio_width, ratio_height]) - - return rescaled_image, scaled_boxes - - -def clamp(num, min_value, max_value): - return max(min(num, max_value), min_value) - - -def get_bb(bb, page_size): - bbs = [float(j) for j in bb] - xs, ys = [], [] - for i, b in enumerate(bbs): - if i % 2 == 0: - xs.append(b) - else: - ys.append(b) - (width, height) = page_size - return_bb = [ - clamp(min(xs), 0, width - 1), - clamp(min(ys), 0, height - 1), - clamp(max(xs), 0, width - 1), - clamp(max(ys), 0, height - 1), - ] - return_bb = [ - int(1000 * return_bb[0] / width), - int(1000 * return_bb[1] / height), - int(1000 * return_bb[2] / width), - int(1000 * return_bb[3] / height), - ] - return return_bb - - -class ToNumpy: - - def __call__(self, pil_img): - np_img = np.array(pil_img, dtype=np.uint8) - if np_img.ndim < 3: - np_img = np.expand_dims(np_img, axis=-1) - np_img = np.rollaxis(np_img, 2) # HWC to CHW - return np_img - - -class ToTensor: - - def __init__(self, dtype=torch.float32): - self.dtype = dtype - - def __call__(self, pil_img): - np_img = np.array(pil_img, dtype=np.uint8) - if np_img.ndim < 3: - np_img = np.expand_dims(np_img, axis=-1) - np_img = np.rollaxis(np_img, 2) # HWC to CHW - return torch.from_numpy(np_img).to(dtype=self.dtype) - - -_pil_interpolation_to_str = { - F.InterpolationMode.NEAREST: 'F.InterpolationMode.NEAREST', - F.InterpolationMode.BILINEAR: 'F.InterpolationMode.BILINEAR', - F.InterpolationMode.BICUBIC: 'F.InterpolationMode.BICUBIC', - F.InterpolationMode.LANCZOS: 'F.InterpolationMode.LANCZOS', - F.InterpolationMode.HAMMING: 'F.InterpolationMode.HAMMING', - F.InterpolationMode.BOX: 'F.InterpolationMode.BOX', -} - - -def _pil_interp(method): - if method == 'bicubic': - return F.InterpolationMode.BICUBIC - elif method == 'lanczos': - return F.InterpolationMode.LANCZOS - elif method == 'hamming': - return F.InterpolationMode.HAMMING - else: - # default bilinear, do we want to allow nearest? - return F.InterpolationMode.BILINEAR - - -class Compose: - """Composes several transforms together. This transform does not support torchscript. - Please, see the note below. - - Args: - transforms (list of ``Transform`` objects): list of transforms to compose. - - Example: - >>> transforms.Compose([ - >>> transforms.CenterCrop(10), - >>> transforms.PILToTensor(), - >>> transforms.ConvertImageDtype(torch.float), - >>> ]) - - .. note:: - In order to script the transformations, please use ``torch.nn.Sequential`` as below. - - >>> transforms = torch.nn.Sequential( - >>> transforms.CenterCrop(10), - >>> transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)), - >>> ) - >>> scripted_transforms = torch.jit.script(transforms) - - Make sure to use only scriptable transformations, i.e. that work with ``torch.Tensor``, does not require - `lambda` functions or ``PIL.Image``. - - """ - - def __init__(self, transforms): - self.transforms = transforms - - def __call__(self, img, augmentation=False, box=None): - for t in self.transforms: - img = t(img, augmentation, box) - return img - - -class RandomResizedCropAndInterpolationWithTwoPic: - """Crop the given PIL Image to random size and aspect ratio with random interpolation. - A crop of random size (default: of 0.08 to 1.0) of the original size and a random - aspect ratio (default: of 3/4 to 4/3) of the original aspect ratio is made. This crop - is finally resized to given size. - This is popularly used to train the Inception networks. - Args: - size: expected output size of each edge - scale: range of size of the origin size cropped - ratio: range of aspect ratio of the origin aspect ratio cropped - interpolation: Default: PIL.Image.BILINEAR - """ - - def __init__(self, size, second_size=None, scale=(0.08, 1.0), ratio=(3. / 4., 4. / 3.), - interpolation='bilinear', second_interpolation='lanczos'): - if isinstance(size, tuple): - self.size = size - else: - self.size = (size, size) - if second_size is not None: - if isinstance(second_size, tuple): - self.second_size = second_size - else: - self.second_size = (second_size, second_size) - else: - self.second_size = None - if (scale[0] > scale[1]) or (ratio[0] > ratio[1]): - warnings.warn("range should be of kind (min, max)") - - self.interpolation = _pil_interp(interpolation) - self.second_interpolation = _pil_interp(second_interpolation) - self.scale = scale - self.ratio = ratio - - @staticmethod - def get_params(img, scale, ratio): - """Get parameters for ``crop`` for a random sized crop. - Args: - img (PIL Image): Image to be cropped. - scale (tuple): range of size of the origin size cropped - ratio (tuple): range of aspect ratio of the origin aspect ratio cropped - Returns: - tuple: params (i, j, h, w) to be passed to ``crop`` for a random - sized crop. - """ - area = img.size[0] * img.size[1] - - for attempt in range(10): - target_area = random.uniform(*scale) * area - log_ratio = (math.log(ratio[0]), math.log(ratio[1])) - aspect_ratio = math.exp(random.uniform(*log_ratio)) - - w = int(round(math.sqrt(target_area * aspect_ratio))) - h = int(round(math.sqrt(target_area / aspect_ratio))) - - if w <= img.size[0] and h <= img.size[1]: - i = random.randint(0, img.size[1] - h) - j = random.randint(0, img.size[0] - w) - return i, j, h, w - - # Fallback to central crop - in_ratio = img.size[0] / img.size[1] - if in_ratio < min(ratio): - w = img.size[0] - h = int(round(w / min(ratio))) - elif in_ratio > max(ratio): - h = img.size[1] - w = int(round(h * max(ratio))) - else: # whole image - w = img.size[0] - h = img.size[1] - i = (img.size[1] - h) // 2 - j = (img.size[0] - w) // 2 - return i, j, h, w - - def __call__(self, img, augmentation=False, box=None): - """ - Args: - img (PIL Image): Image to be cropped and resized. - Returns: - PIL Image: Randomly cropped and resized image. - """ - if augmentation: - i, j, h, w = self.get_params(img, self.scale, self.ratio) - img = F.crop(img, i, j, h, w) - # img, box = crop(img, i, j, h, w, box) - img = F.resize(img, self.size, self.interpolation) - second_img = F.resize(img, self.second_size, self.second_interpolation) \ - if self.second_size is not None else None - return img, second_img - - def __repr__(self): - if isinstance(self.interpolation, (tuple, list)): - interpolate_str = ' '.join([_pil_interpolation_to_str[x] for x in self.interpolation]) - else: - interpolate_str = _pil_interpolation_to_str[self.interpolation] - format_string = self.__class__.__name__ + '(size={0}'.format(self.size) - format_string += ', scale={0}'.format(tuple(round(s, 4) for s in self.scale)) - format_string += ', ratio={0}'.format(tuple(round(r, 4) for r in self.ratio)) - format_string += ', interpolation={0}'.format(interpolate_str) - if self.second_size is not None: - format_string += ', second_size={0}'.format(self.second_size) - format_string += ', second_interpolation={0}'.format(_pil_interpolation_to_str[self.second_interpolation]) - format_string += ')' - return format_string - - -def pil_loader(path: str) -> Image.Image: - # open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835) - with open(path, 'rb') as f: - img = Image.open(f) - return img.convert('RGB') diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/xfund.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/xfund.py deleted file mode 100644 index 7749ba5dd1d59a4e0c5baf4f2c27cffaae3e4e12..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/data/xfund.py +++ /dev/null @@ -1,213 +0,0 @@ -import os -import json - -import torch -from torch.utils.data.dataset import Dataset -from torchvision import transforms -from PIL import Image - -from .image_utils import Compose, RandomResizedCropAndInterpolationWithTwoPic - -XFund_label2ids = { - "O":0, - 'B-HEADER':1, - 'I-HEADER':2, - 'B-QUESTION':3, - 'I-QUESTION':4, - 'B-ANSWER':5, - 'I-ANSWER':6, -} - -class xfund_dataset(Dataset): - def box_norm(self, box, width, height): - def clip(min_num, num, max_num): - return min(max(num, min_num), max_num) - - x0, y0, x1, y1 = box - x0 = clip(0, int((x0 / width) * 1000), 1000) - y0 = clip(0, int((y0 / height) * 1000), 1000) - x1 = clip(0, int((x1 / width) * 1000), 1000) - y1 = clip(0, int((y1 / height) * 1000), 1000) - assert x1 >= x0 - assert y1 >= y0 - return [x0, y0, x1, y1] - - def get_segment_ids(self, bboxs): - segment_ids = [] - for i in range(len(bboxs)): - if i == 0: - segment_ids.append(0) - else: - if bboxs[i - 1] == bboxs[i]: - segment_ids.append(segment_ids[-1]) - else: - segment_ids.append(segment_ids[-1] + 1) - return segment_ids - - def get_position_ids(self, segment_ids): - position_ids = [] - for i in range(len(segment_ids)): - if i == 0: - position_ids.append(2) - else: - if segment_ids[i] == segment_ids[i - 1]: - position_ids.append(position_ids[-1] + 1) - else: - position_ids.append(2) - return position_ids - - def load_data( - self, - data_file, - ): - # re-org data format - total_data = {"id": [], "lines": [], "bboxes": [], "ner_tags": [], "image_path": []} - for i in range(len(data_file['documents'])): - width, height = data_file['documents'][i]['img']['width'], data_file['documents'][i]['img'][ - 'height'] - - cur_doc_lines, cur_doc_bboxes, cur_doc_ner_tags, cur_doc_image_path = [], [], [], [] - for j in range(len(data_file['documents'][i]['document'])): - cur_item = data_file['documents'][i]['document'][j] - cur_doc_lines.append(cur_item['text']) - cur_doc_bboxes.append(self.box_norm(cur_item['box'], width=width, height=height)) - cur_doc_ner_tags.append(cur_item['label']) - total_data['id'] += [len(total_data['id'])] - total_data['lines'] += [cur_doc_lines] - total_data['bboxes'] += [cur_doc_bboxes] - total_data['ner_tags'] += [cur_doc_ner_tags] - total_data['image_path'] += [data_file['documents'][i]['img']['fname']] - - # tokenize text and get bbox/label - total_input_ids, total_bboxs, total_label_ids = [], [], [] - for i in range(len(total_data['lines'])): - cur_doc_input_ids, cur_doc_bboxs, cur_doc_labels = [], [], [] - for j in range(len(total_data['lines'][i])): - cur_input_ids = self.tokenizer(total_data['lines'][i][j], truncation=False, add_special_tokens=False, return_attention_mask=False)['input_ids'] - if len(cur_input_ids) == 0: continue - - cur_label = total_data['ner_tags'][i][j].upper() - if cur_label == 'OTHER': - cur_labels = ["O"] * len(cur_input_ids) - for k in range(len(cur_labels)): - cur_labels[k] = self.label2ids[cur_labels[k]] - else: - cur_labels = [cur_label] * len(cur_input_ids) - cur_labels[0] = self.label2ids['B-' + cur_labels[0]] - for k in range(1, len(cur_labels)): - cur_labels[k] = self.label2ids['I-' + cur_labels[k]] - assert len(cur_input_ids) == len([total_data['bboxes'][i][j]] * len(cur_input_ids)) == len(cur_labels) - cur_doc_input_ids += cur_input_ids - cur_doc_bboxs += [total_data['bboxes'][i][j]] * len(cur_input_ids) - cur_doc_labels += cur_labels - assert len(cur_doc_input_ids) == len(cur_doc_bboxs) == len(cur_doc_labels) - assert len(cur_doc_input_ids) > 0 - - total_input_ids.append(cur_doc_input_ids) - total_bboxs.append(cur_doc_bboxs) - total_label_ids.append(cur_doc_labels) - assert len(total_input_ids) == len(total_bboxs) == len(total_label_ids) - - # split text to several slices because of over-length - input_ids, bboxs, labels = [], [], [] - segment_ids, position_ids = [], [] - image_path = [] - for i in range(len(total_input_ids)): - start = 0 - cur_iter = 0 - while start < len(total_input_ids[i]): - end = min(start + 510, len(total_input_ids[i])) - - input_ids.append([self.tokenizer.cls_token_id] + total_input_ids[i][start: end] + [self.tokenizer.sep_token_id]) - bboxs.append([[0, 0, 0, 0]] + total_bboxs[i][start: end] + [[1000, 1000, 1000, 1000]]) - labels.append([-100] + total_label_ids[i][start: end] + [-100]) - - cur_segment_ids = self.get_segment_ids(bboxs[-1]) - cur_position_ids = self.get_position_ids(cur_segment_ids) - segment_ids.append(cur_segment_ids) - position_ids.append(cur_position_ids) - image_path.append(os.path.join(self.args.data_dir, "images", total_data['image_path'][i])) - - start = end - cur_iter += 1 - - assert len(input_ids) == len(bboxs) == len(labels) == len(segment_ids) == len(position_ids) - assert len(segment_ids) == len(image_path) - - res = { - 'input_ids': input_ids, - 'bbox': bboxs, - 'labels': labels, - 'segment_ids': segment_ids, - 'position_ids': position_ids, - 'image_path': image_path, - } - return res - - def __init__( - self, - args, - tokenizer, - mode - ): - self.args = args - self.mode = mode - self.cur_la = args.language - self.tokenizer = tokenizer - self.label2ids = XFund_label2ids - - - self.common_transform = Compose([ - RandomResizedCropAndInterpolationWithTwoPic( - size=args.input_size, interpolation=args.train_interpolation, - ), - ]) - - self.patch_transform = transforms.Compose([ - transforms.ToTensor(), - transforms.Normalize( - mean=torch.tensor((0.5, 0.5, 0.5)), - std=torch.tensor((0.5, 0.5, 0.5))) - ]) - - data_file = json.load( - open(os.path.join(args.data_dir, "{}.{}.json".format(self.cur_la, 'train' if mode == 'train' else 'val')), - 'r')) - - self.feature = self.load_data(data_file) - - def __len__(self): - return len(self.feature['input_ids']) - - def __getitem__(self, index): - input_ids = self.feature["input_ids"][index] - - # attention_mask = self.feature["attention_mask"][index] - attention_mask = [1] * len(input_ids) - labels = self.feature["labels"][index] - bbox = self.feature["bbox"][index] - segment_ids = self.feature['segment_ids'][index] - position_ids = self.feature['position_ids'][index] - - img = pil_loader(self.feature['image_path'][index]) - for_patches, _ = self.common_transform(img, augmentation=False) - patch = self.patch_transform(for_patches) - - assert len(input_ids) == len(attention_mask) == len(labels) == len(bbox) == len(segment_ids) - - res = { - "input_ids": input_ids, - "attention_mask": attention_mask, - "labels": labels, - "bbox": bbox, - "segment_ids": segment_ids, - "position_ids": position_ids, - "images": patch, - } - return res - -def pil_loader(path: str) -> Image.Image: - # open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835) - with open(path, 'rb') as f: - img = Image.open(f) - return img.convert('RGB') \ No newline at end of file diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/__init__.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/__init__.py deleted file mode 100644 index 0b3100effb34547bbaba7503288db34374cad9ca..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from .layoutlmv3 import ( - LayoutLMv3Config, - LayoutLMv3ForTokenClassification, - LayoutLMv3ForQuestionAnswering, - LayoutLMv3ForSequenceClassification, - LayoutLMv3Tokenizer, -) diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/__init__.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/__init__.py deleted file mode 100644 index e06a24b0ca9971cfe99dc9ef60ce8e495ff406bd..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -from transformers import AutoConfig, AutoModel, AutoModelForTokenClassification, \ - AutoModelForQuestionAnswering, AutoModelForSequenceClassification, AutoTokenizer -from transformers.convert_slow_tokenizer import SLOW_TO_FAST_CONVERTERS, RobertaConverter - -from .configuration_layoutlmv3 import LayoutLMv3Config -from .modeling_layoutlmv3 import ( - LayoutLMv3ForTokenClassification, - LayoutLMv3ForQuestionAnswering, - LayoutLMv3ForSequenceClassification, - LayoutLMv3Model, -) -from .tokenization_layoutlmv3 import LayoutLMv3Tokenizer -from .tokenization_layoutlmv3_fast import LayoutLMv3TokenizerFast - - -#AutoConfig.register("layoutlmv3", LayoutLMv3Config) -#AutoModel.register(LayoutLMv3Config, LayoutLMv3Model) -#AutoModelForTokenClassification.register(LayoutLMv3Config, LayoutLMv3ForTokenClassification) -#AutoModelForQuestionAnswering.register(LayoutLMv3Config, LayoutLMv3ForQuestionAnswering) -#AutoModelForSequenceClassification.register(LayoutLMv3Config, LayoutLMv3ForSequenceClassification) -#AutoTokenizer.register( -# LayoutLMv3Config, slow_tokenizer_class=LayoutLMv3Tokenizer, fast_tokenizer_class=LayoutLMv3TokenizerFast -#) -SLOW_TO_FAST_CONVERTERS.update({"LayoutLMv3Tokenizer": RobertaConverter}) diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/configuration_layoutlmv3.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/configuration_layoutlmv3.py deleted file mode 100644 index d2c7b4d71b4d51504dee8bc10e50ea91bac00270..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/configuration_layoutlmv3.py +++ /dev/null @@ -1,60 +0,0 @@ -# coding=utf-8 -from transformers.models.bert.configuration_bert import BertConfig -from transformers.utils import logging - - -logger = logging.get_logger(__name__) - -LAYOUTLMV3_PRETRAINED_CONFIG_ARCHIVE_MAP = { - "layoutlmv3-base": "https://huggingface.co/microsoft/layoutlmv3-base/resolve/main/config.json", - "layoutlmv3-large": "https://huggingface.co/microsoft/layoutlmv3-large/resolve/main/config.json", - # See all LayoutLMv3 models at https://huggingface.co/models?filter=layoutlmv3 -} - - -class LayoutLMv3Config(BertConfig): - model_type = "layoutlmv3" - - def __init__( - self, - pad_token_id=1, - bos_token_id=0, - eos_token_id=2, - max_2d_position_embeddings=1024, - coordinate_size=None, - shape_size=None, - has_relative_attention_bias=False, - rel_pos_bins=32, - max_rel_pos=128, - has_spatial_attention_bias=False, - rel_2d_pos_bins=64, - max_rel_2d_pos=256, - visual_embed=True, - mim=False, - wpa_task=False, - discrete_vae_weight_path='', - discrete_vae_type='dall-e', - input_size=224, - second_input_size=112, - device='cuda', - **kwargs - ): - """Constructs RobertaConfig.""" - super().__init__(pad_token_id=pad_token_id, bos_token_id=bos_token_id, eos_token_id=eos_token_id, **kwargs) - self.max_2d_position_embeddings = max_2d_position_embeddings - self.coordinate_size = coordinate_size - self.shape_size = shape_size - self.has_relative_attention_bias = has_relative_attention_bias - self.rel_pos_bins = rel_pos_bins - self.max_rel_pos = max_rel_pos - self.has_spatial_attention_bias = has_spatial_attention_bias - self.rel_2d_pos_bins = rel_2d_pos_bins - self.max_rel_2d_pos = max_rel_2d_pos - self.visual_embed = visual_embed - self.mim = mim - self.wpa_task = wpa_task - self.discrete_vae_weight_path = discrete_vae_weight_path - self.discrete_vae_type = discrete_vae_type - self.input_size = input_size - self.second_input_size = second_input_size - self.device = device diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/modeling_layoutlmv3.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/modeling_layoutlmv3.py deleted file mode 100644 index 113eb8eb1d123a4985c1894e0caab561b19f64c2..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/modeling_layoutlmv3.py +++ /dev/null @@ -1,1282 +0,0 @@ -# coding=utf-8 -# Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team. -# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""PyTorch LayoutLMv3 model. """ -import math - -import torch -import torch.nn as nn -import torch.nn.functional as F -import torch.utils.checkpoint -from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss - -from transformers import apply_chunking_to_forward -from transformers.modeling_outputs import ( - BaseModelOutputWithPastAndCrossAttentions, - BaseModelOutputWithPoolingAndCrossAttentions, - MaskedLMOutput, - TokenClassifierOutput, - QuestionAnsweringModelOutput, - SequenceClassifierOutput, -) -from transformers.modeling_utils import PreTrainedModel, find_pruneable_heads_and_indices, prune_linear_layer -from transformers.models.roberta.modeling_roberta import ( - RobertaIntermediate, - RobertaLMHead, - RobertaOutput, - RobertaSelfOutput, -) -from transformers.utils import logging - -from .configuration_layoutlmv3 import LayoutLMv3Config -from timm.models.layers import to_2tuple - - -logger = logging.get_logger(__name__) - - -class PatchEmbed(nn.Module): - """ Image to Patch Embedding - """ - def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768): - super().__init__() - img_size = to_2tuple(img_size) - patch_size = to_2tuple(patch_size) - self.patch_shape = (img_size[0] // patch_size[0], img_size[1] // patch_size[1]) - self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size) - # The following variables are used in detection mycheckpointer.py - self.num_patches = (img_size[1] // patch_size[1]) * (img_size[0] // patch_size[0]) - self.num_patches_w = self.patch_shape[0] - self.num_patches_h = self.patch_shape[1] - - def forward(self, x, position_embedding=None): - x = self.proj(x) - - if position_embedding is not None: - # interpolate the position embedding to the corresponding size - position_embedding = position_embedding.view(1, self.patch_shape[0], self.patch_shape[1], -1).permute(0, 3, 1, 2) - Hp, Wp = x.shape[2], x.shape[3] - position_embedding = F.interpolate(position_embedding, size=(Hp, Wp), mode='bicubic') - x = x + position_embedding - - x = x.flatten(2).transpose(1, 2) - return x - -class LayoutLMv3Embeddings(nn.Module): - """ - Same as BertEmbeddings with a tiny tweak for positional embeddings indexing. - """ - - # Copied from transformers.models.bert.modeling_bert.BertEmbeddings.__init__ - def __init__(self, config): - super().__init__() - self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id) - self.token_type_embeddings = nn.Embedding(config.type_vocab_size, config.hidden_size) - - self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps) - self.dropout = nn.Dropout(config.hidden_dropout_prob) - - # position_ids (1, len position emb) is contiguous in memory and exported when serialized - self.register_buffer("position_ids", torch.arange(config.max_position_embeddings).expand((1, -1))) - - # End copy - self.padding_idx = config.pad_token_id - self.position_embeddings = nn.Embedding( - config.max_position_embeddings, config.hidden_size, padding_idx=self.padding_idx - ) - - self.x_position_embeddings = nn.Embedding(config.max_2d_position_embeddings, config.coordinate_size) - self.y_position_embeddings = nn.Embedding(config.max_2d_position_embeddings, config.coordinate_size) - self.h_position_embeddings = nn.Embedding(config.max_2d_position_embeddings, config.shape_size) - self.w_position_embeddings = nn.Embedding(config.max_2d_position_embeddings, config.shape_size) - - def _calc_spatial_position_embeddings(self, bbox): - try: - assert torch.all(0 <= bbox) and torch.all(bbox <= 1023) - left_position_embeddings = self.x_position_embeddings(bbox[:, :, 0]) - upper_position_embeddings = self.y_position_embeddings(bbox[:, :, 1]) - right_position_embeddings = self.x_position_embeddings(bbox[:, :, 2]) - lower_position_embeddings = self.y_position_embeddings(bbox[:, :, 3]) - except IndexError as e: - raise IndexError("The :obj:`bbox` coordinate values should be within 0-1000 range.") from e - - h_position_embeddings = self.h_position_embeddings(torch.clip(bbox[:, :, 3] - bbox[:, :, 1], 0, 1023)) - w_position_embeddings = self.w_position_embeddings(torch.clip(bbox[:, :, 2] - bbox[:, :, 0], 0, 1023)) - - # below is the difference between LayoutLMEmbeddingsV2 (torch.cat) and LayoutLMEmbeddingsV1 (add) - spatial_position_embeddings = torch.cat( - [ - left_position_embeddings, - upper_position_embeddings, - right_position_embeddings, - lower_position_embeddings, - h_position_embeddings, - w_position_embeddings, - ], - dim=-1, - ) - return spatial_position_embeddings - - def create_position_ids_from_input_ids(self, input_ids, padding_idx, past_key_values_length=0): - """ - Replace non-padding symbols with their position numbers. Position numbers begin at padding_idx+1. Padding symbols - are ignored. This is modified from fairseq's `utils.make_positions`. - - Args: - x: torch.Tensor x: - - Returns: torch.Tensor - """ - # The series of casts and type-conversions here are carefully balanced to both work with ONNX export and XLA. - mask = input_ids.ne(padding_idx).int() - incremental_indices = (torch.cumsum(mask, dim=1).type_as(mask) + past_key_values_length) * mask - return incremental_indices.long() + padding_idx - - def forward( - self, - input_ids=None, - bbox=None, - token_type_ids=None, - position_ids=None, - inputs_embeds=None, - past_key_values_length=0, - ): - if position_ids is None: - if input_ids is not None: - # Create the position ids from the input token ids. Any padded tokens remain padded. - position_ids = self.create_position_ids_from_input_ids( - input_ids, self.padding_idx, past_key_values_length).to(input_ids.device) - else: - position_ids = self.create_position_ids_from_inputs_embeds(inputs_embeds) - - if input_ids is not None: - input_shape = input_ids.size() - else: - input_shape = inputs_embeds.size()[:-1] - - if token_type_ids is None: - token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=self.position_ids.device) - - if inputs_embeds is None: - inputs_embeds = self.word_embeddings(input_ids) - token_type_embeddings = self.token_type_embeddings(token_type_ids) - - embeddings = inputs_embeds + token_type_embeddings - position_embeddings = self.position_embeddings(position_ids) - embeddings += position_embeddings - - spatial_position_embeddings = self._calc_spatial_position_embeddings(bbox) - - embeddings = embeddings + spatial_position_embeddings - - embeddings = self.LayerNorm(embeddings) - embeddings = self.dropout(embeddings) - return embeddings - - def create_position_ids_from_inputs_embeds(self, inputs_embeds): - """ - We are provided embeddings directly. We cannot infer which are padded so just generate sequential position ids. - - Args: - inputs_embeds: torch.Tensor≈ - - Returns: torch.Tensor - """ - input_shape = inputs_embeds.size()[:-1] - sequence_length = input_shape[1] - - position_ids = torch.arange( - self.padding_idx + 1, sequence_length + self.padding_idx + 1, dtype=torch.long, device=inputs_embeds.device - ) - return position_ids.unsqueeze(0).expand(input_shape) - - -class LayoutLMv3PreTrainedModel(PreTrainedModel): - """ - An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained - models. - """ - - config_class = LayoutLMv3Config - base_model_prefix = "layoutlmv3" - - # Copied from transformers.models.bert.modeling_bert.BertPreTrainedModel._init_weights - def _init_weights(self, module): - """Initialize the weights""" - if isinstance(module, nn.Linear): - # Slightly different from the TF version which uses truncated_normal for initialization - # cf https://github.com/pytorch/pytorch/pull/5617 - module.weight.data.normal_(mean=0.0, std=self.config.initializer_range) - if module.bias is not None: - module.bias.data.zero_() - elif isinstance(module, nn.Embedding): - module.weight.data.normal_(mean=0.0, std=self.config.initializer_range) - if module.padding_idx is not None: - module.weight.data[module.padding_idx].zero_() - elif isinstance(module, nn.LayerNorm): - module.bias.data.zero_() - module.weight.data.fill_(1.0) - - -class LayoutLMv3SelfAttention(nn.Module): - def __init__(self, config): - super().__init__() - if config.hidden_size % config.num_attention_heads != 0 and not hasattr(config, "embedding_size"): - raise ValueError( - f"The hidden size ({config.hidden_size}) is not a multiple of the number of attention " - f"heads ({config.num_attention_heads})" - ) - - self.num_attention_heads = config.num_attention_heads - self.attention_head_size = int(config.hidden_size / config.num_attention_heads) - self.all_head_size = self.num_attention_heads * self.attention_head_size - - self.query = nn.Linear(config.hidden_size, self.all_head_size) - self.key = nn.Linear(config.hidden_size, self.all_head_size) - self.value = nn.Linear(config.hidden_size, self.all_head_size) - - self.dropout = nn.Dropout(config.attention_probs_dropout_prob) - self.has_relative_attention_bias = config.has_relative_attention_bias - self.has_spatial_attention_bias = config.has_spatial_attention_bias - - def transpose_for_scores(self, x): - new_x_shape = x.size()[:-1] + (self.num_attention_heads, self.attention_head_size) - x = x.view(*new_x_shape) - return x.permute(0, 2, 1, 3) - - def cogview_attn(self, attention_scores, alpha=32): - ''' - https://arxiv.org/pdf/2105.13290.pdf - Section 2.4 Stabilization of training: Precision Bottleneck Relaxation (PB-Relax). - A replacement of the original nn.Softmax(dim=-1)(attention_scores) - Seems the new attention_probs will result in a slower speed and a little bias - Can use torch.allclose(standard_attention_probs, cogview_attention_probs, atol=1e-08) for comparison - The smaller atol (e.g., 1e-08), the better. - ''' - scaled_attention_scores = attention_scores / alpha - max_value = scaled_attention_scores.amax(dim=(-1)).unsqueeze(-1) - # max_value = scaled_attention_scores.amax(dim=(-2, -1)).unsqueeze(-1).unsqueeze(-1) - new_attention_scores = (scaled_attention_scores - max_value) * alpha - return nn.Softmax(dim=-1)(new_attention_scores) - - def forward( - self, - hidden_states, - attention_mask=None, - head_mask=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - past_key_value=None, - output_attentions=False, - rel_pos=None, - rel_2d_pos=None, - ): - mixed_query_layer = self.query(hidden_states) - - # If this is instantiated as a cross-attention module, the keys - # and values come from an encoder; the attention mask needs to be - # such that the encoder's padding tokens are not attended to. - is_cross_attention = encoder_hidden_states is not None - - if is_cross_attention and past_key_value is not None: - # reuse k,v, cross_attentions - key_layer = past_key_value[0] - value_layer = past_key_value[1] - attention_mask = encoder_attention_mask - elif is_cross_attention: - key_layer = self.transpose_for_scores(self.key(encoder_hidden_states)) - value_layer = self.transpose_for_scores(self.value(encoder_hidden_states)) - attention_mask = encoder_attention_mask - elif past_key_value is not None: - key_layer = self.transpose_for_scores(self.key(hidden_states)) - value_layer = self.transpose_for_scores(self.value(hidden_states)) - key_layer = torch.cat([past_key_value[0], key_layer], dim=2) - value_layer = torch.cat([past_key_value[1], value_layer], dim=2) - else: - key_layer = self.transpose_for_scores(self.key(hidden_states)) - value_layer = self.transpose_for_scores(self.value(hidden_states)) - - query_layer = self.transpose_for_scores(mixed_query_layer) - - # Take the dot product between "query" and "key" to get the raw attention scores. - # The attention scores QT K/√d could be significantly larger than input elements, and result in overflow. - # Changing the computational order into QT(K/√d) alleviates the problem. (https://arxiv.org/pdf/2105.13290.pdf) - attention_scores = torch.matmul(query_layer / math.sqrt(self.attention_head_size), key_layer.transpose(-1, -2)) - - if self.has_relative_attention_bias and self.has_spatial_attention_bias: - attention_scores += (rel_pos + rel_2d_pos) / math.sqrt(self.attention_head_size) - elif self.has_relative_attention_bias: - attention_scores += rel_pos / math.sqrt(self.attention_head_size) - - # if self.has_relative_attention_bias: - # attention_scores += rel_pos - # if self.has_spatial_attention_bias: - # attention_scores += rel_2d_pos - - # attention_scores = attention_scores / math.sqrt(self.attention_head_size) - if attention_mask is not None: - # Apply the attention mask is (precomputed for all layers in RobertaModel forward() function) - attention_scores = attention_scores + attention_mask - - # Normalize the attention scores to probabilities. - # attention_probs = nn.Softmax(dim=-1)(attention_scores) # comment the line below and use this line for speedup - attention_probs = self.cogview_attn(attention_scores) # to stablize training - # assert torch.allclose(attention_probs, nn.Softmax(dim=-1)(attention_scores), atol=1e-8) - - # This is actually dropping out entire tokens to attend to, which might - # seem a bit unusual, but is taken from the original Transformer paper. - attention_probs = self.dropout(attention_probs) - - # Mask heads if we want to - if head_mask is not None: - attention_probs = attention_probs * head_mask - - context_layer = torch.matmul(attention_probs, value_layer) - - context_layer = context_layer.permute(0, 2, 1, 3).contiguous() - new_context_layer_shape = context_layer.size()[:-2] + (self.all_head_size,) - context_layer = context_layer.view(*new_context_layer_shape) - - outputs = (context_layer, attention_probs) if output_attentions else (context_layer,) - - return outputs - - -class LayoutLMv3Attention(nn.Module): - def __init__(self, config): - super().__init__() - self.self = LayoutLMv3SelfAttention(config) - self.output = RobertaSelfOutput(config) - self.pruned_heads = set() - - def prune_heads(self, heads): - if len(heads) == 0: - return - heads, index = find_pruneable_heads_and_indices( - heads, self.self.num_attention_heads, self.self.attention_head_size, self.pruned_heads - ) - - # Prune linear layers - self.self.query = prune_linear_layer(self.self.query, index) - self.self.key = prune_linear_layer(self.self.key, index) - self.self.value = prune_linear_layer(self.self.value, index) - self.output.dense = prune_linear_layer(self.output.dense, index, dim=1) - - # Update hyper params and store pruned heads - self.self.num_attention_heads = self.self.num_attention_heads - len(heads) - self.self.all_head_size = self.self.attention_head_size * self.self.num_attention_heads - self.pruned_heads = self.pruned_heads.union(heads) - - def forward( - self, - hidden_states, - attention_mask=None, - head_mask=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - past_key_value=None, - output_attentions=False, - rel_pos=None, - rel_2d_pos=None, - ): - self_outputs = self.self( - hidden_states, - attention_mask, - head_mask, - encoder_hidden_states, - encoder_attention_mask, - past_key_value, - output_attentions, - rel_pos=rel_pos, - rel_2d_pos=rel_2d_pos, - ) - attention_output = self.output(self_outputs[0], hidden_states) - outputs = (attention_output,) + self_outputs[1:] # add attentions if we output them - return outputs - - -class LayoutLMv3Layer(nn.Module): - def __init__(self, config): - super().__init__() - self.chunk_size_feed_forward = config.chunk_size_feed_forward - self.seq_len_dim = 1 - self.attention = LayoutLMv3Attention(config) - assert not config.is_decoder and not config.add_cross_attention, \ - "This version do not support decoder. Please refer to RoBERTa for implementation of is_decoder." - self.intermediate = RobertaIntermediate(config) - self.output = RobertaOutput(config) - - def forward( - self, - hidden_states, - attention_mask=None, - head_mask=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - past_key_value=None, - output_attentions=False, - rel_pos=None, - rel_2d_pos=None, - ): - # decoder uni-directional self-attention cached key/values tuple is at positions 1,2 - self_attn_past_key_value = past_key_value[:2] if past_key_value is not None else None - self_attention_outputs = self.attention( - hidden_states, - attention_mask, - head_mask, - output_attentions=output_attentions, - past_key_value=self_attn_past_key_value, - rel_pos=rel_pos, - rel_2d_pos=rel_2d_pos, - ) - attention_output = self_attention_outputs[0] - - outputs = self_attention_outputs[1:] # add self attentions if we output attention weights - - layer_output = apply_chunking_to_forward( - self.feed_forward_chunk, self.chunk_size_feed_forward, self.seq_len_dim, attention_output - ) - outputs = (layer_output,) + outputs - - return outputs - - def feed_forward_chunk(self, attention_output): - intermediate_output = self.intermediate(attention_output) - layer_output = self.output(intermediate_output, attention_output) - return layer_output - - -class LayoutLMv3Encoder(nn.Module): - def __init__(self, config, detection=False, out_features=None): - super().__init__() - self.config = config - self.detection = detection - self.layer = nn.ModuleList([LayoutLMv3Layer(config) for _ in range(config.num_hidden_layers)]) - self.gradient_checkpointing = False - - self.has_relative_attention_bias = config.has_relative_attention_bias - self.has_spatial_attention_bias = config.has_spatial_attention_bias - - if self.has_relative_attention_bias: - self.rel_pos_bins = config.rel_pos_bins - self.max_rel_pos = config.max_rel_pos - self.rel_pos_onehot_size = config.rel_pos_bins - self.rel_pos_bias = nn.Linear(self.rel_pos_onehot_size, config.num_attention_heads, bias=False) - - if self.has_spatial_attention_bias: - self.max_rel_2d_pos = config.max_rel_2d_pos - self.rel_2d_pos_bins = config.rel_2d_pos_bins - self.rel_2d_pos_onehot_size = config.rel_2d_pos_bins - self.rel_pos_x_bias = nn.Linear(self.rel_2d_pos_onehot_size, config.num_attention_heads, bias=False) - self.rel_pos_y_bias = nn.Linear(self.rel_2d_pos_onehot_size, config.num_attention_heads, bias=False) - - if self.detection: - self.gradient_checkpointing = True - embed_dim = self.config.hidden_size - self.out_features = out_features - self.out_indices = [int(name[5:]) for name in out_features] - self.fpn1 = nn.Sequential( - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - # nn.SyncBatchNorm(embed_dim), - nn.BatchNorm2d(embed_dim), - nn.GELU(), - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - ) - - self.fpn2 = nn.Sequential( - nn.ConvTranspose2d(embed_dim, embed_dim, kernel_size=2, stride=2), - ) - - self.fpn3 = nn.Identity() - - self.fpn4 = nn.MaxPool2d(kernel_size=2, stride=2) - self.ops = [self.fpn1, self.fpn2, self.fpn3, self.fpn4] - - def relative_position_bucket(self, relative_position, bidirectional=True, num_buckets=32, max_distance=128): - ret = 0 - if bidirectional: - num_buckets //= 2 - ret += (relative_position > 0).long() * num_buckets - n = torch.abs(relative_position) - else: - n = torch.max(-relative_position, torch.zeros_like(relative_position)) - # now n is in the range [0, inf) - - # half of the buckets are for exact increments in positions - max_exact = num_buckets // 2 - is_small = n < max_exact - - # The other half of the buckets are for logarithmically bigger bins in positions up to max_distance - val_if_large = max_exact + ( - torch.log(n.float() / max_exact) / math.log(max_distance / max_exact) * (num_buckets - max_exact) - ).to(torch.long) - val_if_large = torch.min(val_if_large, torch.full_like(val_if_large, num_buckets - 1)) - - ret += torch.where(is_small, n, val_if_large) - return ret - - def _cal_1d_pos_emb(self, hidden_states, position_ids, valid_span): - VISUAL_NUM = 196 + 1 - - rel_pos_mat = position_ids.unsqueeze(-2) - position_ids.unsqueeze(-1) - - if valid_span is not None: - # for the text part, if two words are not in the same line, - # set their distance to the max value (position_ids.shape[-1]) - rel_pos_mat[(rel_pos_mat > 0) & (valid_span == False)] = position_ids.shape[1] - rel_pos_mat[(rel_pos_mat < 0) & (valid_span == False)] = -position_ids.shape[1] - - # image-text, minimum distance - rel_pos_mat[:, -VISUAL_NUM:, :-VISUAL_NUM] = 0 - rel_pos_mat[:, :-VISUAL_NUM, -VISUAL_NUM:] = 0 - - rel_pos = self.relative_position_bucket( - rel_pos_mat, - num_buckets=self.rel_pos_bins, - max_distance=self.max_rel_pos, - ) - rel_pos = F.one_hot(rel_pos, num_classes=self.rel_pos_onehot_size).type_as(hidden_states) - rel_pos = self.rel_pos_bias(rel_pos).permute(0, 3, 1, 2) - rel_pos = rel_pos.contiguous() - return rel_pos - - def _cal_2d_pos_emb(self, hidden_states, bbox): - position_coord_x = bbox[:, :, 0] - position_coord_y = bbox[:, :, 3] - rel_pos_x_2d_mat = position_coord_x.unsqueeze(-2) - position_coord_x.unsqueeze(-1) - rel_pos_y_2d_mat = position_coord_y.unsqueeze(-2) - position_coord_y.unsqueeze(-1) - rel_pos_x = self.relative_position_bucket( - rel_pos_x_2d_mat, - num_buckets=self.rel_2d_pos_bins, - max_distance=self.max_rel_2d_pos, - ) - rel_pos_y = self.relative_position_bucket( - rel_pos_y_2d_mat, - num_buckets=self.rel_2d_pos_bins, - max_distance=self.max_rel_2d_pos, - ) - rel_pos_x = F.one_hot(rel_pos_x, num_classes=self.rel_2d_pos_onehot_size).type_as(hidden_states) - rel_pos_y = F.one_hot(rel_pos_y, num_classes=self.rel_2d_pos_onehot_size).type_as(hidden_states) - rel_pos_x = self.rel_pos_x_bias(rel_pos_x).permute(0, 3, 1, 2) - rel_pos_y = self.rel_pos_y_bias(rel_pos_y).permute(0, 3, 1, 2) - rel_pos_x = rel_pos_x.contiguous() - rel_pos_y = rel_pos_y.contiguous() - rel_2d_pos = rel_pos_x + rel_pos_y - return rel_2d_pos - - def forward( - self, - hidden_states, - bbox=None, - attention_mask=None, - head_mask=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - past_key_values=None, - use_cache=None, - output_attentions=False, - output_hidden_states=False, - return_dict=True, - position_ids=None, - Hp=None, - Wp=None, - valid_span=None, - ): - all_hidden_states = () if output_hidden_states else None - all_self_attentions = () if output_attentions else None - all_cross_attentions = () if output_attentions and self.config.add_cross_attention else None - - next_decoder_cache = () if use_cache else None - - rel_pos = self._cal_1d_pos_emb(hidden_states, position_ids, valid_span) if self.has_relative_attention_bias else None - rel_2d_pos = self._cal_2d_pos_emb(hidden_states, bbox) if self.has_spatial_attention_bias else None - - if self.detection: - feat_out = {} - j = 0 - - for i, layer_module in enumerate(self.layer): - if output_hidden_states: - all_hidden_states = all_hidden_states + (hidden_states,) - - layer_head_mask = head_mask[i] if head_mask is not None else None - past_key_value = past_key_values[i] if past_key_values is not None else None - - if self.gradient_checkpointing and self.training: - - if use_cache: - logger.warning( - "`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`..." - ) - use_cache = False - - def create_custom_forward(module): - def custom_forward(*inputs): - return module(*inputs) - # return module(*inputs, past_key_value, output_attentions, rel_pos, rel_2d_pos) - # The above line will cause error: - # RuntimeError: Trying to backward through the graph a second time - # (or directly access saved tensors after they have already been freed). - return custom_forward - - layer_outputs = torch.utils.checkpoint.checkpoint( - create_custom_forward(layer_module), - hidden_states, - attention_mask, - layer_head_mask, - encoder_hidden_states, - encoder_attention_mask, - past_key_value, - output_attentions, - rel_pos, - rel_2d_pos - ) - else: - layer_outputs = layer_module( - hidden_states, - attention_mask, - layer_head_mask, - encoder_hidden_states, - encoder_attention_mask, - past_key_value, - output_attentions, - rel_pos=rel_pos, - rel_2d_pos=rel_2d_pos, - ) - - hidden_states = layer_outputs[0] - if use_cache: - next_decoder_cache += (layer_outputs[-1],) - if output_attentions: - all_self_attentions = all_self_attentions + (layer_outputs[1],) - if self.config.add_cross_attention: - all_cross_attentions = all_cross_attentions + (layer_outputs[2],) - - if self.detection and i in self.out_indices: - xp = hidden_states[:, -Hp*Wp:, :].permute(0, 2, 1).reshape(len(hidden_states), -1, Hp, Wp) - feat_out[self.out_features[j]] = self.ops[j](xp.contiguous()) - j += 1 - - if self.detection: - return feat_out - - if output_hidden_states: - all_hidden_states = all_hidden_states + (hidden_states,) - - if not return_dict: - return tuple( - v - for v in [ - hidden_states, - next_decoder_cache, - all_hidden_states, - all_self_attentions, - all_cross_attentions, - ] - if v is not None - ) - return BaseModelOutputWithPastAndCrossAttentions( - last_hidden_state=hidden_states, - past_key_values=next_decoder_cache, - hidden_states=all_hidden_states, - attentions=all_self_attentions, - cross_attentions=all_cross_attentions, - ) - - -class LayoutLMv3Model(LayoutLMv3PreTrainedModel): - """ - """ - - _keys_to_ignore_on_load_missing = [r"position_ids"] - - # Copied from transformers.models.bert.modeling_bert.BertModel.__init__ with Bert->Roberta - def __init__(self, config, detection=False, out_features=None, image_only=False): - super().__init__(config) - self.config = config - assert not config.is_decoder and not config.add_cross_attention, \ - "This version do not support decoder. Please refer to RoBERTa for implementation of is_decoder." - self.detection = detection - if not self.detection: - self.image_only = False - else: - assert config.visual_embed - self.image_only = image_only - - if not self.image_only: - self.embeddings = LayoutLMv3Embeddings(config) - self.encoder = LayoutLMv3Encoder(config, detection=detection, out_features=out_features) - - if config.visual_embed: - embed_dim = self.config.hidden_size - # use the default pre-training parameters for fine-tuning (e.g., input_size) - # when the input_size is larger in fine-tuning, we will interpolate the position embedding in forward - self.patch_embed = PatchEmbed(embed_dim=embed_dim) - - patch_size = 16 - size = int(self.config.input_size / patch_size) - self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim)) - self.pos_embed = nn.Parameter(torch.zeros(1, size * size + 1, embed_dim)) - self.pos_drop = nn.Dropout(p=0.) - - self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps) - self.dropout = nn.Dropout(config.hidden_dropout_prob) - - if self.config.has_relative_attention_bias or self.config.has_spatial_attention_bias: - self._init_visual_bbox(img_size=(size, size)) - - from functools import partial - norm_layer = partial(nn.LayerNorm, eps=1e-6) - self.norm = norm_layer(embed_dim) - - self.init_weights() - - def get_input_embeddings(self): - return self.embeddings.word_embeddings - - def set_input_embeddings(self, value): - self.embeddings.word_embeddings = value - - def _prune_heads(self, heads_to_prune): - """ - Prunes heads of the model. heads_to_prune: dict of {layer_num: list of heads to prune in this layer} See base - class PreTrainedModel - """ - for layer, heads in heads_to_prune.items(): - self.encoder.layer[layer].attention.prune_heads(heads) - - def _init_visual_bbox(self, img_size=(14, 14), max_len=1000): - visual_bbox_x = torch.div(torch.arange(0, max_len * (img_size[1] + 1), max_len), - img_size[1], rounding_mode='trunc') - visual_bbox_y = torch.div(torch.arange(0, max_len * (img_size[0] + 1), max_len), - img_size[0], rounding_mode='trunc') - visual_bbox = torch.stack( - [ - visual_bbox_x[:-1].repeat(img_size[0], 1), - visual_bbox_y[:-1].repeat(img_size[1], 1).transpose(0, 1), - visual_bbox_x[1:].repeat(img_size[0], 1), - visual_bbox_y[1:].repeat(img_size[1], 1).transpose(0, 1), - ], - dim=-1, - ).view(-1, 4) - - cls_token_box = torch.tensor([[0 + 1, 0 + 1, max_len - 1, max_len - 1]]) - self.visual_bbox = torch.cat([cls_token_box, visual_bbox], dim=0) - - def _calc_visual_bbox(self, device, dtype, bsz): # , img_size=(14, 14), max_len=1000): - visual_bbox = self.visual_bbox.repeat(bsz, 1, 1) - visual_bbox = visual_bbox.to(device).type(dtype) - return visual_bbox - - def forward_image(self, x): - if self.detection: - x = self.patch_embed(x, self.pos_embed[:, 1:, :] if self.pos_embed is not None else None) - else: - x = self.patch_embed(x) - batch_size, seq_len, _ = x.size() - - cls_tokens = self.cls_token.expand(batch_size, -1, -1) # stole cls_tokens impl from Phil Wang, thanks - if self.pos_embed is not None and self.detection: - cls_tokens = cls_tokens + self.pos_embed[:, :1, :] - - x = torch.cat((cls_tokens, x), dim=1) - if self.pos_embed is not None and not self.detection: - x = x + self.pos_embed - x = self.pos_drop(x) - - x = self.norm(x) - return x - - # Copied from transformers.models.bert.modeling_bert.BertModel.forward - def forward( - self, - input_ids=None, - bbox=None, - attention_mask=None, - token_type_ids=None, - valid_span=None, - position_ids=None, - head_mask=None, - inputs_embeds=None, - encoder_hidden_states=None, - encoder_attention_mask=None, - past_key_values=None, - use_cache=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - images=None, - ): - r""" - encoder_hidden_states (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`): - Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention if - the model is configured as a decoder. - encoder_attention_mask (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`): - Mask to avoid performing attention on the padding token indices of the encoder input. This mask is used in - the cross-attention if the model is configured as a decoder. Mask values selected in ``[0, 1]``: - - - 1 for tokens that are **not masked**, - - 0 for tokens that are **masked**. - past_key_values (:obj:`tuple(tuple(torch.FloatTensor))` of length :obj:`config.n_layers` with each tuple having 4 tensors of shape :obj:`(batch_size, num_heads, sequence_length - 1, embed_size_per_head)`): - Contains precomputed key and value hidden states of the attention blocks. Can be used to speed up decoding. - - If :obj:`past_key_values` are used, the user can optionally input only the last :obj:`decoder_input_ids` - (those that don't have their past key value states given to this model) of shape :obj:`(batch_size, 1)` - instead of all :obj:`decoder_input_ids` of shape :obj:`(batch_size, sequence_length)`. - use_cache (:obj:`bool`, `optional`): - If set to :obj:`True`, :obj:`past_key_values` key value states are returned and can be used to speed up - decoding (see :obj:`past_key_values`). - """ - output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions - output_hidden_states = ( - output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states - ) - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - use_cache = False - - # if input_ids is not None and inputs_embeds is not None: - # raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time") - if input_ids is not None: - input_shape = input_ids.size() - batch_size, seq_length = input_shape - device = input_ids.device - elif inputs_embeds is not None: - input_shape = inputs_embeds.size()[:-1] - batch_size, seq_length = input_shape - device = inputs_embeds.device - elif images is not None: - batch_size = len(images) - device = images.device - else: - raise ValueError("You have to specify either input_ids or inputs_embeds or images") - - if not self.image_only: - # past_key_values_length - past_key_values_length = past_key_values[0][0].shape[2] if past_key_values is not None else 0 - - if attention_mask is None: - attention_mask = torch.ones(((batch_size, seq_length + past_key_values_length)), device=device) - if token_type_ids is None: - token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=device) - - # We can provide a self-attention mask of dimensions [batch_size, from_seq_length, to_seq_length] - # ourselves in which case we just need to make it broadcastable to all heads. - # extended_attention_mask: torch.Tensor = self.get_extended_attention_mask(attention_mask, input_shape, device) - - encoder_extended_attention_mask = None - - # Prepare head mask if needed - # 1.0 in head_mask indicate we keep the head - # attention_probs has shape bsz x n_heads x N x N - # input head_mask has shape [num_heads] or [num_hidden_layers x num_heads] - # and head_mask is converted to shape [num_hidden_layers x batch x num_heads x seq_length x seq_length] - head_mask = self.get_head_mask(head_mask, self.config.num_hidden_layers) - - if not self.image_only: - if bbox is None: - bbox = torch.zeros(tuple(list(input_shape) + [4]), dtype=torch.long, device=device) - - embedding_output = self.embeddings( - input_ids=input_ids, - bbox=bbox, - position_ids=position_ids, - token_type_ids=token_type_ids, - inputs_embeds=inputs_embeds, - past_key_values_length=past_key_values_length, - ) - - final_bbox = final_position_ids = None - Hp = Wp = None - if images is not None: - patch_size = 16 - Hp, Wp = int(images.shape[2] / patch_size), int(images.shape[3] / patch_size) - visual_emb = self.forward_image(images) - if self.detection: - visual_attention_mask = torch.ones((batch_size, visual_emb.shape[1]), dtype=torch.long, device=device) - if self.image_only: - attention_mask = visual_attention_mask - else: - attention_mask = torch.cat([attention_mask, visual_attention_mask], dim=1) - elif self.image_only: - attention_mask = torch.ones((batch_size, visual_emb.shape[1]), dtype=torch.long, device=device) - - if self.config.has_relative_attention_bias or self.config.has_spatial_attention_bias: - if self.config.has_spatial_attention_bias: - visual_bbox = self._calc_visual_bbox(device, dtype=torch.long, bsz=batch_size) - if self.image_only: - final_bbox = visual_bbox - else: - final_bbox = torch.cat([bbox, visual_bbox], dim=1) - - visual_position_ids = torch.arange(0, visual_emb.shape[1], dtype=torch.long, device=device).repeat( - batch_size, 1) - if self.image_only: - final_position_ids = visual_position_ids - else: - position_ids = torch.arange(0, input_shape[1], device=device).unsqueeze(0) - position_ids = position_ids.expand_as(input_ids) - final_position_ids = torch.cat([position_ids, visual_position_ids], dim=1) - - if self.image_only: - embedding_output = visual_emb - else: - embedding_output = torch.cat([embedding_output, visual_emb], dim=1) - embedding_output = self.LayerNorm(embedding_output) - embedding_output = self.dropout(embedding_output) - elif self.config.has_relative_attention_bias or self.config.has_spatial_attention_bias: - if self.config.has_spatial_attention_bias: - final_bbox = bbox - if self.config.has_relative_attention_bias: - position_ids = self.embeddings.position_ids[:, :input_shape[1]] - position_ids = position_ids.expand_as(input_ids) - final_position_ids = position_ids - - extended_attention_mask: torch.Tensor = self.get_extended_attention_mask(attention_mask, None, device) - - encoder_outputs = self.encoder( - embedding_output, - bbox=final_bbox, - position_ids=final_position_ids, - attention_mask=extended_attention_mask, - head_mask=head_mask, - encoder_hidden_states=encoder_hidden_states, - encoder_attention_mask=encoder_extended_attention_mask, - past_key_values=past_key_values, - use_cache=use_cache, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - Hp=Hp, - Wp=Wp, - valid_span=valid_span, - ) - - if self.detection: - return encoder_outputs - - sequence_output = encoder_outputs[0] - pooled_output = None - - if not return_dict: - return (sequence_output, pooled_output) + encoder_outputs[1:] - - return BaseModelOutputWithPoolingAndCrossAttentions( - last_hidden_state=sequence_output, - pooler_output=pooled_output, - past_key_values=encoder_outputs.past_key_values, - hidden_states=encoder_outputs.hidden_states, - attentions=encoder_outputs.attentions, - cross_attentions=encoder_outputs.cross_attentions, - ) - - -class LayoutLMv3ClassificationHead(nn.Module): - """ - Head for sentence-level classification tasks. - Reference: RobertaClassificationHead - """ - - def __init__(self, config, pool_feature=False): - super().__init__() - self.pool_feature = pool_feature - if pool_feature: - self.dense = nn.Linear(config.hidden_size*3, config.hidden_size) - else: - self.dense = nn.Linear(config.hidden_size, config.hidden_size) - classifier_dropout = ( - config.classifier_dropout if config.classifier_dropout is not None else config.hidden_dropout_prob - ) - self.dropout = nn.Dropout(classifier_dropout) - self.out_proj = nn.Linear(config.hidden_size, config.num_labels) - - def forward(self, x): - # x = features[:, 0, :] # take token (equiv. to [CLS]) - x = self.dropout(x) - x = self.dense(x) - x = torch.tanh(x) - x = self.dropout(x) - x = self.out_proj(x) - return x - - -class LayoutLMv3ForTokenClassification(LayoutLMv3PreTrainedModel): - _keys_to_ignore_on_load_unexpected = [r"pooler"] - _keys_to_ignore_on_load_missing = [r"position_ids"] - - def __init__(self, config): - super().__init__(config) - self.num_labels = config.num_labels - - self.layoutlmv3 = LayoutLMv3Model(config) - self.dropout = nn.Dropout(config.hidden_dropout_prob) - if config.num_labels < 10: - self.classifier = nn.Linear(config.hidden_size, config.num_labels) - else: - self.classifier = LayoutLMv3ClassificationHead(config, pool_feature=False) - - self.init_weights() - - def forward( - self, - input_ids=None, - bbox=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - valid_span=None, - head_mask=None, - inputs_embeds=None, - labels=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - images=None, - ): - r""" - labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`): - Labels for computing the token classification loss. Indices should be in ``[0, ..., config.num_labels - - 1]``. - """ - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - outputs = self.layoutlmv3( - input_ids, - bbox=bbox, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - images=images, - valid_span=valid_span, - ) - - sequence_output = outputs[0] - - sequence_output = self.dropout(sequence_output) - logits = self.classifier(sequence_output) - - loss = None - if labels is not None: - loss_fct = CrossEntropyLoss() - # Only keep active parts of the loss - if attention_mask is not None: - active_loss = attention_mask.view(-1) == 1 - active_logits = logits.view(-1, self.num_labels) - active_labels = torch.where( - active_loss, labels.view(-1), torch.tensor(loss_fct.ignore_index).type_as(labels) - ) - loss = loss_fct(active_logits, active_labels) - else: - loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1)) - - if not return_dict: - output = (logits,) + outputs[2:] - return ((loss,) + output) if loss is not None else output - - return TokenClassifierOutput( - loss=loss, - logits=logits, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - ) - - -class LayoutLMv3ForQuestionAnswering(LayoutLMv3PreTrainedModel): - _keys_to_ignore_on_load_unexpected = [r"pooler"] - _keys_to_ignore_on_load_missing = [r"position_ids"] - - def __init__(self, config): - super().__init__(config) - self.num_labels = config.num_labels - - self.layoutlmv3 = LayoutLMv3Model(config) - # self.qa_outputs = nn.Linear(config.hidden_size, config.num_labels) - self.qa_outputs = LayoutLMv3ClassificationHead(config, pool_feature=False) - - self.init_weights() - - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - valid_span=None, - head_mask=None, - inputs_embeds=None, - start_positions=None, - end_positions=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - bbox=None, - images=None, - ): - r""" - start_positions (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`): - Labels for position (index) of the start of the labelled span for computing the token classification loss. - Positions are clamped to the length of the sequence (:obj:`sequence_length`). Position outside of the - sequence are not taken into account for computing the loss. - end_positions (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`): - Labels for position (index) of the end of the labelled span for computing the token classification loss. - Positions are clamped to the length of the sequence (:obj:`sequence_length`). Position outside of the - sequence are not taken into account for computing the loss. - """ - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - outputs = self.layoutlmv3( - input_ids, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - bbox=bbox, - images=images, - valid_span=valid_span, - ) - - sequence_output = outputs[0] - - logits = self.qa_outputs(sequence_output) - start_logits, end_logits = logits.split(1, dim=-1) - start_logits = start_logits.squeeze(-1).contiguous() - end_logits = end_logits.squeeze(-1).contiguous() - - total_loss = None - if start_positions is not None and end_positions is not None: - # If we are on multi-GPU, split add a dimension - if len(start_positions.size()) > 1: - start_positions = start_positions.squeeze(-1) - if len(end_positions.size()) > 1: - end_positions = end_positions.squeeze(-1) - # sometimes the start/end positions are outside our model inputs, we ignore these terms - ignored_index = start_logits.size(1) - start_positions = start_positions.clamp(0, ignored_index) - end_positions = end_positions.clamp(0, ignored_index) - - loss_fct = CrossEntropyLoss(ignore_index=ignored_index) - start_loss = loss_fct(start_logits, start_positions) - end_loss = loss_fct(end_logits, end_positions) - total_loss = (start_loss + end_loss) / 2 - - if not return_dict: - output = (start_logits, end_logits) + outputs[2:] - return ((total_loss,) + output) if total_loss is not None else output - - return QuestionAnsweringModelOutput( - loss=total_loss, - start_logits=start_logits, - end_logits=end_logits, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - ) - - -class LayoutLMv3ForSequenceClassification(LayoutLMv3PreTrainedModel): - _keys_to_ignore_on_load_missing = [r"position_ids"] - - def __init__(self, config): - super().__init__(config) - self.num_labels = config.num_labels - self.config = config - self.layoutlmv3 = LayoutLMv3Model(config) - self.classifier = LayoutLMv3ClassificationHead(config, pool_feature=False) - - self.init_weights() - - def forward( - self, - input_ids=None, - attention_mask=None, - token_type_ids=None, - position_ids=None, - valid_span=None, - head_mask=None, - inputs_embeds=None, - labels=None, - output_attentions=None, - output_hidden_states=None, - return_dict=None, - bbox=None, - images=None, - ): - r""" - labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`): - Labels for computing the sequence classification/regression loss. Indices should be in :obj:`[0, ..., - config.num_labels - 1]`. If :obj:`config.num_labels == 1` a regression loss is computed (Mean-Square loss), - If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy). - """ - return_dict = return_dict if return_dict is not None else self.config.use_return_dict - - outputs = self.layoutlmv3( - input_ids, - attention_mask=attention_mask, - token_type_ids=token_type_ids, - position_ids=position_ids, - head_mask=head_mask, - inputs_embeds=inputs_embeds, - output_attentions=output_attentions, - output_hidden_states=output_hidden_states, - return_dict=return_dict, - bbox=bbox, - images=images, - valid_span=valid_span, - ) - - sequence_output = outputs[0][:, 0, :] - logits = self.classifier(sequence_output) - - loss = None - if labels is not None: - if self.config.problem_type is None: - if self.num_labels == 1: - self.config.problem_type = "regression" - elif self.num_labels > 1 and (labels.dtype == torch.long or labels.dtype == torch.int): - self.config.problem_type = "single_label_classification" - else: - self.config.problem_type = "multi_label_classification" - - if self.config.problem_type == "regression": - loss_fct = MSELoss() - if self.num_labels == 1: - loss = loss_fct(logits.squeeze(), labels.squeeze()) - else: - loss = loss_fct(logits, labels) - elif self.config.problem_type == "single_label_classification": - loss_fct = CrossEntropyLoss() - loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1)) - elif self.config.problem_type == "multi_label_classification": - loss_fct = BCEWithLogitsLoss() - loss = loss_fct(logits, labels) - - if not return_dict: - output = (logits,) + outputs[2:] - return ((loss,) + output) if loss is not None else output - - return SequenceClassifierOutput( - loss=loss, - logits=logits, - hidden_states=outputs.hidden_states, - attentions=outputs.attentions, - ) diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/tokenization_layoutlmv3.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/tokenization_layoutlmv3.py deleted file mode 100644 index f340d3c6aca04b6567614e6aa221f7c542239305..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/tokenization_layoutlmv3.py +++ /dev/null @@ -1,32 +0,0 @@ -# coding=utf-8 -# Copyright 2018 The Open AI Team Authors and The HuggingFace Inc. team. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Tokenization classes for LayoutLMv3, refer to RoBERTa.""" - -from transformers.models.roberta import RobertaTokenizer -from transformers.utils import logging - - -logger = logging.get_logger(__name__) - -VOCAB_FILES_NAMES = { - "vocab_file": "vocab.json", - "merges_file": "merges.txt", -} - -class LayoutLMv3Tokenizer(RobertaTokenizer): - vocab_files_names = VOCAB_FILES_NAMES - # pretrained_vocab_files_map = PRETRAINED_VOCAB_FILES_MAP - # max_model_input_sizes = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES - model_input_names = ["input_ids", "attention_mask"] diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/tokenization_layoutlmv3_fast.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/tokenization_layoutlmv3_fast.py deleted file mode 100644 index 9fd75ff1d3bd7725025114e99320afd80823e9d0..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/layoutlmft/models/layoutlmv3/tokenization_layoutlmv3_fast.py +++ /dev/null @@ -1,34 +0,0 @@ -# coding=utf-8 -# Copyright 2018 The Open AI Team Authors and The HuggingFace Inc. team. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Fast Tokenization classes for LayoutLMv3, refer to RoBERTa.""" - - -from transformers.models.roberta.tokenization_roberta_fast import RobertaTokenizerFast -from transformers.utils import logging - -from .tokenization_layoutlmv3 import LayoutLMv3Tokenizer - - -logger = logging.get_logger(__name__) - -VOCAB_FILES_NAMES = {"vocab_file": "vocab.json", "merges_file": "merges.txt", "tokenizer_file": "tokenizer.json"} - - -class LayoutLMv3TokenizerFast(RobertaTokenizerFast): - vocab_files_names = VOCAB_FILES_NAMES - # pretrained_vocab_files_map = PRETRAINED_VOCAB_FILES_MAP - # max_model_input_sizes = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES - model_input_names = ["input_ids", "attention_mask"] - slow_tokenizer_class = LayoutLMv3Tokenizer diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/model_init.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/model_init.py deleted file mode 100644 index a624d60d5a75902f3c44d3dfbe1ef350cddf7427..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/model_init.py +++ /dev/null @@ -1,151 +0,0 @@ -from .visualizer import Visualizer -from .rcnn_vl import * -from .backbone import * - -from detectron2.config import get_cfg -from detectron2.config import CfgNode as CN -from detectron2.data import MetadataCatalog, DatasetCatalog -from detectron2.data.datasets import register_coco_instances -from detectron2.engine import DefaultTrainer, default_argument_parser, default_setup, launch, DefaultPredictor - - -def add_vit_config(cfg): - """ - Add config for VIT. - """ - _C = cfg - - _C.MODEL.VIT = CN() - - # CoaT model name. - _C.MODEL.VIT.NAME = "" - - # Output features from CoaT backbone. - _C.MODEL.VIT.OUT_FEATURES = ["layer3", "layer5", "layer7", "layer11"] - - _C.MODEL.VIT.IMG_SIZE = [224, 224] - - _C.MODEL.VIT.POS_TYPE = "shared_rel" - - _C.MODEL.VIT.DROP_PATH = 0. - - _C.MODEL.VIT.MODEL_KWARGS = "{}" - - _C.SOLVER.OPTIMIZER = "ADAMW" - - _C.SOLVER.BACKBONE_MULTIPLIER = 1.0 - - _C.AUG = CN() - - _C.AUG.DETR = False - - _C.MODEL.IMAGE_ONLY = True - _C.PUBLAYNET_DATA_DIR_TRAIN = "" - _C.PUBLAYNET_DATA_DIR_TEST = "" - _C.FOOTNOTE_DATA_DIR_TRAIN = "" - _C.FOOTNOTE_DATA_DIR_VAL = "" - _C.SCIHUB_DATA_DIR_TRAIN = "" - _C.SCIHUB_DATA_DIR_TEST = "" - _C.JIAOCAI_DATA_DIR_TRAIN = "" - _C.JIAOCAI_DATA_DIR_TEST = "" - _C.ICDAR_DATA_DIR_TRAIN = "" - _C.ICDAR_DATA_DIR_TEST = "" - _C.M6DOC_DATA_DIR_TEST = "" - _C.DOCSTRUCTBENCH_DATA_DIR_TEST = "" - _C.DOCSTRUCTBENCHv2_DATA_DIR_TEST = "" - _C.CACHE_DIR = "" - _C.MODEL.CONFIG_PATH = "" - - # effective update steps would be MAX_ITER/GRADIENT_ACCUMULATION_STEPS - # maybe need to set MAX_ITER *= GRADIENT_ACCUMULATION_STEPS - _C.SOLVER.GRADIENT_ACCUMULATION_STEPS = 1 - - -def setup(args, device): - """ - Create configs and perform basic setups. - """ - cfg = get_cfg() - - # add_coat_config(cfg) - add_vit_config(cfg) - cfg.merge_from_file(args.config_file) - cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.2 # set threshold for this model - cfg.merge_from_list(args.opts) - - # 使用统一的device配置 - cfg.MODEL.DEVICE = device - - cfg.freeze() - default_setup(cfg, args) - - #@todo 可以删掉这块? - # register_coco_instances( - # "scihub_train", - # {}, - # cfg.SCIHUB_DATA_DIR_TRAIN + ".json", - # cfg.SCIHUB_DATA_DIR_TRAIN - # ) - - return cfg - - -class DotDict(dict): - def __init__(self, *args, **kwargs): - super(DotDict, self).__init__(*args, **kwargs) - - def __getattr__(self, key): - if key not in self.keys(): - return None - value = self[key] - if isinstance(value, dict): - value = DotDict(value) - return value - - def __setattr__(self, key, value): - self[key] = value - - -class Layoutlmv3_Predictor(object): - def __init__(self, weights, config_file, device): - layout_args = { - "config_file": config_file, - "resume": False, - "eval_only": False, - "num_gpus": 1, - "num_machines": 1, - "machine_rank": 0, - "dist_url": "tcp://127.0.0.1:57823", - "opts": ["MODEL.WEIGHTS", weights], - } - layout_args = DotDict(layout_args) - - cfg = setup(layout_args, device) - self.mapping = ["title", "plain text", "abandon", "figure", "figure_caption", "table", "table_caption", - "table_footnote", "isolate_formula", "formula_caption"] - MetadataCatalog.get(cfg.DATASETS.TRAIN[0]).thing_classes = self.mapping - self.predictor = DefaultPredictor(cfg) - - def __call__(self, image, ignore_catids=[]): - # page_layout_result = { - # "layout_dets": [] - # } - layout_dets = [] - outputs = self.predictor(image) - boxes = outputs["instances"].to("cpu")._fields["pred_boxes"].tensor.tolist() - labels = outputs["instances"].to("cpu")._fields["pred_classes"].tolist() - scores = outputs["instances"].to("cpu")._fields["scores"].tolist() - for bbox_idx in range(len(boxes)): - if labels[bbox_idx] in ignore_catids: - continue - layout_dets.append({ - "category_id": labels[bbox_idx], - "poly": [ - boxes[bbox_idx][0], boxes[bbox_idx][1], - boxes[bbox_idx][2], boxes[bbox_idx][1], - boxes[bbox_idx][2], boxes[bbox_idx][3], - boxes[bbox_idx][0], boxes[bbox_idx][3], - ], - "score": scores[bbox_idx] - }) - return layout_dets diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/rcnn_vl.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/rcnn_vl.py deleted file mode 100644 index 46b2e16102e8782eb675b518b7d870dc8d007ba8..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/rcnn_vl.py +++ /dev/null @@ -1,163 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import logging -import numpy as np -from typing import Dict, List, Optional, Tuple -import torch -from torch import nn - -from detectron2.config import configurable -from detectron2.structures import ImageList, Instances -from detectron2.utils.events import get_event_storage - -from detectron2.modeling.backbone import Backbone, build_backbone -from detectron2.modeling.meta_arch.build import META_ARCH_REGISTRY - -from detectron2.modeling.meta_arch import GeneralizedRCNN - -from detectron2.modeling.postprocessing import detector_postprocess -from detectron2.modeling.roi_heads.fast_rcnn import fast_rcnn_inference_single_image -from contextlib import contextmanager -from itertools import count - -@META_ARCH_REGISTRY.register() -class VLGeneralizedRCNN(GeneralizedRCNN): - """ - Generalized R-CNN. Any models that contains the following three components: - 1. Per-image feature extraction (aka backbone) - 2. Region proposal generation - 3. Per-region feature extraction and prediction - """ - - def forward(self, batched_inputs: List[Dict[str, torch.Tensor]]): - """ - Args: - batched_inputs: a list, batched outputs of :class:`DatasetMapper` . - Each item in the list contains the inputs for one image. - For now, each item in the list is a dict that contains: - - * image: Tensor, image in (C, H, W) format. - * instances (optional): groundtruth :class:`Instances` - * proposals (optional): :class:`Instances`, precomputed proposals. - - Other information that's included in the original dicts, such as: - - * "height", "width" (int): the output resolution of the model, used in inference. - See :meth:`postprocess` for details. - - Returns: - list[dict]: - Each dict is the output for one input image. - The dict contains one key "instances" whose value is a :class:`Instances`. - The :class:`Instances` object has the following keys: - "pred_boxes", "pred_classes", "scores", "pred_masks", "pred_keypoints" - """ - if not self.training: - return self.inference(batched_inputs) - - images = self.preprocess_image(batched_inputs) - if "instances" in batched_inputs[0]: - gt_instances = [x["instances"].to(self.device) for x in batched_inputs] - else: - gt_instances = None - - # features = self.backbone(images.tensor) - input = self.get_batch(batched_inputs, images) - features = self.backbone(input) - - if self.proposal_generator is not None: - proposals, proposal_losses = self.proposal_generator(images, features, gt_instances) - else: - assert "proposals" in batched_inputs[0] - proposals = [x["proposals"].to(self.device) for x in batched_inputs] - proposal_losses = {} - - _, detector_losses = self.roi_heads(images, features, proposals, gt_instances) - if self.vis_period > 0: - storage = get_event_storage() - if storage.iter % self.vis_period == 0: - self.visualize_training(batched_inputs, proposals) - - losses = {} - losses.update(detector_losses) - losses.update(proposal_losses) - return losses - - def inference( - self, - batched_inputs: List[Dict[str, torch.Tensor]], - detected_instances: Optional[List[Instances]] = None, - do_postprocess: bool = True, - ): - """ - Run inference on the given inputs. - - Args: - batched_inputs (list[dict]): same as in :meth:`forward` - detected_instances (None or list[Instances]): if not None, it - contains an `Instances` object per image. The `Instances` - object contains "pred_boxes" and "pred_classes" which are - known boxes in the image. - The inference will then skip the detection of bounding boxes, - and only predict other per-ROI outputs. - do_postprocess (bool): whether to apply post-processing on the outputs. - - Returns: - When do_postprocess=True, same as in :meth:`forward`. - Otherwise, a list[Instances] containing raw network outputs. - """ - assert not self.training - - images = self.preprocess_image(batched_inputs) - # features = self.backbone(images.tensor) - input = self.get_batch(batched_inputs, images) - features = self.backbone(input) - - if detected_instances is None: - if self.proposal_generator is not None: - proposals, _ = self.proposal_generator(images, features, None) - else: - assert "proposals" in batched_inputs[0] - proposals = [x["proposals"].to(self.device) for x in batched_inputs] - - results, _ = self.roi_heads(images, features, proposals, None) - else: - detected_instances = [x.to(self.device) for x in detected_instances] - results = self.roi_heads.forward_with_given_boxes(features, detected_instances) - - if do_postprocess: - assert not torch.jit.is_scripting(), "Scripting is not supported for postprocess." - return GeneralizedRCNN._postprocess(results, batched_inputs, images.image_sizes) - else: - return results - - def get_batch(self, examples, images): - if len(examples) >= 1 and "bbox" not in examples[0]: # image_only - return {"images": images.tensor} - - return input - - def _batch_inference(self, batched_inputs, detected_instances=None): - """ - Execute inference on a list of inputs, - using batch size = self.batch_size (e.g., 2), instead of the length of the list. - - Inputs & outputs have the same format as :meth:`GeneralizedRCNN.inference` - """ - if detected_instances is None: - detected_instances = [None] * len(batched_inputs) - - outputs = [] - inputs, instances = [], [] - for idx, input, instance in zip(count(), batched_inputs, detected_instances): - inputs.append(input) - instances.append(instance) - if len(inputs) == 2 or idx == len(batched_inputs) - 1: - outputs.extend( - self.inference( - inputs, - instances if instances[0] is not None else None, - do_postprocess=True, # False - ) - ) - inputs, instances = [], [] - return outputs diff --git a/magic_pdf/model/sub_modules/layout/layoutlmv3/visualizer.py b/magic_pdf/model/sub_modules/layout/layoutlmv3/visualizer.py deleted file mode 100644 index 8185984e66f0267be6368317c60dc543dcb69e87..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/layout/layoutlmv3/visualizer.py +++ /dev/null @@ -1,1236 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -import colorsys -import logging -import math -import numpy as np -from enum import Enum, unique -import cv2 -import matplotlib as mpl -import matplotlib.colors as mplc -import matplotlib.figure as mplfigure -import pycocotools.mask as mask_util -import torch -from matplotlib.backends.backend_agg import FigureCanvasAgg -from PIL import Image - -from detectron2.data import MetadataCatalog -from detectron2.structures import BitMasks, Boxes, BoxMode, Keypoints, PolygonMasks, RotatedBoxes -from detectron2.utils.file_io import PathManager - -from detectron2.utils.colormap import random_color - -import pdb - -logger = logging.getLogger(__name__) - -__all__ = ["ColorMode", "VisImage", "Visualizer"] - - -_SMALL_OBJECT_AREA_THRESH = 1000 -_LARGE_MASK_AREA_THRESH = 120000 -_OFF_WHITE = (1.0, 1.0, 240.0 / 255) -_BLACK = (0, 0, 0) -_RED = (1.0, 0, 0) - -_KEYPOINT_THRESHOLD = 0.05 - -#CLASS_NAMES = ["footnote", "footer", "header"] - -@unique -class ColorMode(Enum): - """ - Enum of different color modes to use for instance visualizations. - """ - - IMAGE = 0 - """ - Picks a random color for every instance and overlay segmentations with low opacity. - """ - SEGMENTATION = 1 - """ - Let instances of the same category have similar colors - (from metadata.thing_colors), and overlay them with - high opacity. This provides more attention on the quality of segmentation. - """ - IMAGE_BW = 2 - """ - Same as IMAGE, but convert all areas without masks to gray-scale. - Only available for drawing per-instance mask predictions. - """ - - -class GenericMask: - """ - Attribute: - polygons (list[ndarray]): list[ndarray]: polygons for this mask. - Each ndarray has format [x, y, x, y, ...] - mask (ndarray): a binary mask - """ - - def __init__(self, mask_or_polygons, height, width): - self._mask = self._polygons = self._has_holes = None - self.height = height - self.width = width - - m = mask_or_polygons - if isinstance(m, dict): - # RLEs - assert "counts" in m and "size" in m - if isinstance(m["counts"], list): # uncompressed RLEs - h, w = m["size"] - assert h == height and w == width - m = mask_util.frPyObjects(m, h, w) - self._mask = mask_util.decode(m)[:, :] - return - - if isinstance(m, list): # list[ndarray] - self._polygons = [np.asarray(x).reshape(-1) for x in m] - return - - if isinstance(m, np.ndarray): # assumed to be a binary mask - assert m.shape[1] != 2, m.shape - assert m.shape == ( - height, - width, - ), f"mask shape: {m.shape}, target dims: {height}, {width}" - self._mask = m.astype("uint8") - return - - raise ValueError("GenericMask cannot handle object {} of type '{}'".format(m, type(m))) - - @property - def mask(self): - if self._mask is None: - self._mask = self.polygons_to_mask(self._polygons) - return self._mask - - @property - def polygons(self): - if self._polygons is None: - self._polygons, self._has_holes = self.mask_to_polygons(self._mask) - return self._polygons - - @property - def has_holes(self): - if self._has_holes is None: - if self._mask is not None: - self._polygons, self._has_holes = self.mask_to_polygons(self._mask) - else: - self._has_holes = False # if original format is polygon, does not have holes - return self._has_holes - - def mask_to_polygons(self, mask): - # cv2.RETR_CCOMP flag retrieves all the contours and arranges them to a 2-level - # hierarchy. External contours (boundary) of the object are placed in hierarchy-1. - # Internal contours (holes) are placed in hierarchy-2. - # cv2.CHAIN_APPROX_NONE flag gets vertices of polygons from contours. - mask = np.ascontiguousarray(mask) # some versions of cv2 does not support incontiguous arr - res = cv2.findContours(mask.astype("uint8"), cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE) - hierarchy = res[-1] - if hierarchy is None: # empty mask - return [], False - has_holes = (hierarchy.reshape(-1, 4)[:, 3] >= 0).sum() > 0 - res = res[-2] - res = [x.flatten() for x in res] - # These coordinates from OpenCV are integers in range [0, W-1 or H-1]. - # We add 0.5 to turn them into real-value coordinate space. A better solution - # would be to first +0.5 and then dilate the returned polygon by 0.5. - res = [x + 0.5 for x in res if len(x) >= 6] - return res, has_holes - - def polygons_to_mask(self, polygons): - rle = mask_util.frPyObjects(polygons, self.height, self.width) - rle = mask_util.merge(rle) - return mask_util.decode(rle)[:, :] - - def area(self): - return self.mask.sum() - - def bbox(self): - p = mask_util.frPyObjects(self.polygons, self.height, self.width) - p = mask_util.merge(p) - bbox = mask_util.toBbox(p) - bbox[2] += bbox[0] - bbox[3] += bbox[1] - return bbox - - -class _PanopticPrediction: - """ - Unify different panoptic annotation/prediction formats - """ - - def __init__(self, panoptic_seg, segments_info, metadata=None): - if segments_info is None: - assert metadata is not None - # If "segments_info" is None, we assume "panoptic_img" is a - # H*W int32 image storing the panoptic_id in the format of - # category_id * label_divisor + instance_id. We reserve -1 for - # VOID label. - label_divisor = metadata.label_divisor - segments_info = [] - for panoptic_label in np.unique(panoptic_seg.numpy()): - if panoptic_label == -1: - # VOID region. - continue - pred_class = panoptic_label // label_divisor - isthing = pred_class in metadata.thing_dataset_id_to_contiguous_id.values() - segments_info.append( - { - "id": int(panoptic_label), - "category_id": int(pred_class), - "isthing": bool(isthing), - } - ) - del metadata - - self._seg = panoptic_seg - - self._sinfo = {s["id"]: s for s in segments_info} # seg id -> seg info - segment_ids, areas = torch.unique(panoptic_seg, sorted=True, return_counts=True) - areas = areas.numpy() - sorted_idxs = np.argsort(-areas) - self._seg_ids, self._seg_areas = segment_ids[sorted_idxs], areas[sorted_idxs] - self._seg_ids = self._seg_ids.tolist() - for sid, area in zip(self._seg_ids, self._seg_areas): - if sid in self._sinfo: - self._sinfo[sid]["area"] = float(area) - - def non_empty_mask(self): - """ - Returns: - (H, W) array, a mask for all pixels that have a prediction - """ - empty_ids = [] - for id in self._seg_ids: - if id not in self._sinfo: - empty_ids.append(id) - if len(empty_ids) == 0: - return np.zeros(self._seg.shape, dtype=np.uint8) - assert ( - len(empty_ids) == 1 - ), ">1 ids corresponds to no labels. This is currently not supported" - return (self._seg != empty_ids[0]).numpy().astype(np.bool) - - def semantic_masks(self): - for sid in self._seg_ids: - sinfo = self._sinfo.get(sid) - if sinfo is None or sinfo["isthing"]: - # Some pixels (e.g. id 0 in PanopticFPN) have no instance or semantic predictions. - continue - yield (self._seg == sid).numpy().astype(np.bool), sinfo - - def instance_masks(self): - for sid in self._seg_ids: - sinfo = self._sinfo.get(sid) - if sinfo is None or not sinfo["isthing"]: - continue - mask = (self._seg == sid).numpy().astype(np.bool) - if mask.sum() > 0: - yield mask, sinfo - - -def _create_text_labels(classes, scores, class_names, is_crowd=None): - """ - Args: - classes (list[int] or None): - scores (list[float] or None): - class_names (list[str] or None): - is_crowd (list[bool] or None): - - Returns: - list[str] or None - """ - #class_names = CLASS_NAMES - labels = None - if classes is not None: - if class_names is not None and len(class_names) > 0: - labels = [class_names[i] for i in classes] - else: - labels = [str(i) for i in classes] - - if scores is not None: - if labels is None: - labels = ["{:.0f}%".format(s * 100) for s in scores] - else: - labels = ["{} {:.0f}%".format(l, s * 100) for l, s in zip(labels, scores)] - if labels is not None and is_crowd is not None: - labels = [l + ("|crowd" if crowd else "") for l, crowd in zip(labels, is_crowd)] - return labels - - -class VisImage: - def __init__(self, img, scale=1.0): - """ - Args: - img (ndarray): an RGB image of shape (H, W, 3) in range [0, 255]. - scale (float): scale the input image - """ - self.img = img - self.scale = scale - self.width, self.height = img.shape[1], img.shape[0] - self._setup_figure(img) - - def _setup_figure(self, img): - """ - Args: - Same as in :meth:`__init__()`. - - Returns: - fig (matplotlib.pyplot.figure): top level container for all the image plot elements. - ax (matplotlib.pyplot.Axes): contains figure elements and sets the coordinate system. - """ - fig = mplfigure.Figure(frameon=False) - self.dpi = fig.get_dpi() - # add a small 1e-2 to avoid precision lost due to matplotlib's truncation - # (https://github.com/matplotlib/matplotlib/issues/15363) - fig.set_size_inches( - (self.width * self.scale + 1e-2) / self.dpi, - (self.height * self.scale + 1e-2) / self.dpi, - ) - self.canvas = FigureCanvasAgg(fig) - # self.canvas = mpl.backends.backend_cairo.FigureCanvasCairo(fig) - ax = fig.add_axes([0.0, 0.0, 1.0, 1.0]) - ax.axis("off") - self.fig = fig - self.ax = ax - self.reset_image(img) - - def reset_image(self, img): - """ - Args: - img: same as in __init__ - """ - img = img.astype("uint8") - self.ax.imshow(img, extent=(0, self.width, self.height, 0), interpolation="nearest") - - def save(self, filepath): - """ - Args: - filepath (str): a string that contains the absolute path, including the file name, where - the visualized image will be saved. - """ - self.fig.savefig(filepath) - - def get_image(self): - """ - Returns: - ndarray: - the visualized image of shape (H, W, 3) (RGB) in uint8 type. - The shape is scaled w.r.t the input image using the given `scale` argument. - """ - canvas = self.canvas - s, (width, height) = canvas.print_to_buffer() - # buf = io.BytesIO() # works for cairo backend - # canvas.print_rgba(buf) - # width, height = self.width, self.height - # s = buf.getvalue() - - buffer = np.frombuffer(s, dtype="uint8") - - img_rgba = buffer.reshape(height, width, 4) - rgb, alpha = np.split(img_rgba, [3], axis=2) - return rgb.astype("uint8") - - -class Visualizer: - """ - Visualizer that draws data about detection/segmentation on images. - - It contains methods like `draw_{text,box,circle,line,binary_mask,polygon}` - that draw primitive objects to images, as well as high-level wrappers like - `draw_{instance_predictions,sem_seg,panoptic_seg_predictions,dataset_dict}` - that draw composite data in some pre-defined style. - - Note that the exact visualization style for the high-level wrappers are subject to change. - Style such as color, opacity, label contents, visibility of labels, or even the visibility - of objects themselves (e.g. when the object is too small) may change according - to different heuristics, as long as the results still look visually reasonable. - - To obtain a consistent style, you can implement custom drawing functions with the - abovementioned primitive methods instead. If you need more customized visualization - styles, you can process the data yourself following their format documented in - tutorials (:doc:`/tutorials/models`, :doc:`/tutorials/datasets`). This class does not - intend to satisfy everyone's preference on drawing styles. - - This visualizer focuses on high rendering quality rather than performance. It is not - designed to be used for real-time applications. - """ - - # TODO implement a fast, rasterized version using OpenCV - - def __init__(self, img_rgb, metadata=None, scale=1.0, instance_mode=ColorMode.IMAGE): - """ - Args: - img_rgb: a numpy array of shape (H, W, C), where H and W correspond to - the height and width of the image respectively. C is the number of - color channels. The image is required to be in RGB format since that - is a requirement of the Matplotlib library. The image is also expected - to be in the range [0, 255]. - metadata (Metadata): dataset metadata (e.g. class names and colors) - instance_mode (ColorMode): defines one of the pre-defined style for drawing - instances on an image. - """ - self.img = np.asarray(img_rgb).clip(0, 255).astype(np.uint8) - if metadata is None: - metadata = MetadataCatalog.get("__nonexist__") - self.metadata = metadata - self.output = VisImage(self.img, scale=scale) - self.cpu_device = torch.device("cpu") - - # too small texts are useless, therefore clamp to 9 - self._default_font_size = max( - np.sqrt(self.output.height * self.output.width) // 90, 10 // scale - ) - self._instance_mode = instance_mode - self.keypoint_threshold = _KEYPOINT_THRESHOLD - - def draw_instance_predictions(self, predictions): - """ - Draw instance-level prediction results on an image. - - Args: - predictions (Instances): the output of an instance detection/segmentation - model. Following fields will be used to draw: - "pred_boxes", "pred_classes", "scores", "pred_masks" (or "pred_masks_rle"). - - Returns: - output (VisImage): image object with visualizations. - """ - boxes = predictions.pred_boxes if predictions.has("pred_boxes") else None - scores = predictions.scores if predictions.has("scores") else None - classes = predictions.pred_classes.tolist() if predictions.has("pred_classes") else None - labels = _create_text_labels(classes, scores, self.metadata.get("thing_classes", None)) - keypoints = predictions.pred_keypoints if predictions.has("pred_keypoints") else None - - if predictions.has("pred_masks"): - masks = np.asarray(predictions.pred_masks) - masks = [GenericMask(x, self.output.height, self.output.width) for x in masks] - else: - masks = None - - if self._instance_mode == ColorMode.SEGMENTATION and self.metadata.get("thing_colors"): - colors = [ - self._jitter([x / 255 for x in self.metadata.thing_colors[c]]) for c in classes - ] - alpha = 0.8 - else: - colors = None - alpha = 0.5 - - if self._instance_mode == ColorMode.IMAGE_BW: - self.output.reset_image( - self._create_grayscale_image( - (predictions.pred_masks.any(dim=0) > 0).numpy() - if predictions.has("pred_masks") - else None - ) - ) - alpha = 0.3 - - self.overlay_instances( - masks=masks, - boxes=boxes, - labels=labels, - keypoints=keypoints, - assigned_colors=colors, - alpha=alpha, - ) - return self.output - - def draw_sem_seg(self, sem_seg, area_threshold=None, alpha=0.8): - """ - Draw semantic segmentation predictions/labels. - - Args: - sem_seg (Tensor or ndarray): the segmentation of shape (H, W). - Each value is the integer label of the pixel. - area_threshold (int): segments with less than `area_threshold` are not drawn. - alpha (float): the larger it is, the more opaque the segmentations are. - - Returns: - output (VisImage): image object with visualizations. - """ - if isinstance(sem_seg, torch.Tensor): - sem_seg = sem_seg.numpy() - labels, areas = np.unique(sem_seg, return_counts=True) - sorted_idxs = np.argsort(-areas).tolist() - labels = labels[sorted_idxs] - for label in filter(lambda l: l < len(self.metadata.stuff_classes), labels): - try: - mask_color = [x / 255 for x in self.metadata.stuff_colors[label]] - except (AttributeError, IndexError): - mask_color = None - - binary_mask = (sem_seg == label).astype(np.uint8) - text = self.metadata.stuff_classes[label] - self.draw_binary_mask( - binary_mask, - color=mask_color, - edge_color=_OFF_WHITE, - text=text, - alpha=alpha, - area_threshold=area_threshold, - ) - return self.output - - def draw_panoptic_seg(self, panoptic_seg, segments_info, area_threshold=None, alpha=0.7): - """ - Draw panoptic prediction annotations or results. - - Args: - panoptic_seg (Tensor): of shape (height, width) where the values are ids for each - segment. - segments_info (list[dict] or None): Describe each segment in `panoptic_seg`. - If it is a ``list[dict]``, each dict contains keys "id", "category_id". - If None, category id of each pixel is computed by - ``pixel // metadata.label_divisor``. - area_threshold (int): stuff segments with less than `area_threshold` are not drawn. - - Returns: - output (VisImage): image object with visualizations. - """ - pred = _PanopticPrediction(panoptic_seg, segments_info, self.metadata) - - if self._instance_mode == ColorMode.IMAGE_BW: - self.output.reset_image(self._create_grayscale_image(pred.non_empty_mask())) - - # draw mask for all semantic segments first i.e. "stuff" - for mask, sinfo in pred.semantic_masks(): - category_idx = sinfo["category_id"] - try: - mask_color = [x / 255 for x in self.metadata.stuff_colors[category_idx]] - except AttributeError: - mask_color = None - - text = self.metadata.stuff_classes[category_idx] - self.draw_binary_mask( - mask, - color=mask_color, - edge_color=_OFF_WHITE, - text=text, - alpha=alpha, - area_threshold=area_threshold, - ) - - # draw mask for all instances second - all_instances = list(pred.instance_masks()) - if len(all_instances) == 0: - return self.output - masks, sinfo = list(zip(*all_instances)) - category_ids = [x["category_id"] for x in sinfo] - - try: - scores = [x["score"] for x in sinfo] - except KeyError: - scores = None - labels = _create_text_labels( - category_ids, scores, self.metadata.thing_classes, [x.get("iscrowd", 0) for x in sinfo] - ) - - try: - colors = [ - self._jitter([x / 255 for x in self.metadata.thing_colors[c]]) for c in category_ids - ] - except AttributeError: - colors = None - self.overlay_instances(masks=masks, labels=labels, assigned_colors=colors, alpha=alpha) - - return self.output - - draw_panoptic_seg_predictions = draw_panoptic_seg # backward compatibility - - def draw_dataset_dict(self, dic): - """ - Draw annotations/segmentaions in Detectron2 Dataset format. - - Args: - dic (dict): annotation/segmentation data of one image, in Detectron2 Dataset format. - - Returns: - output (VisImage): image object with visualizations. - """ - annos = dic.get("annotations", None) - if annos: - if "segmentation" in annos[0]: - masks = [x["segmentation"] for x in annos] - else: - masks = None - if "keypoints" in annos[0]: - keypts = [x["keypoints"] for x in annos] - keypts = np.array(keypts).reshape(len(annos), -1, 3) - else: - keypts = None - - boxes = [ - BoxMode.convert(x["bbox"], x["bbox_mode"], BoxMode.XYXY_ABS) - if len(x["bbox"]) == 4 - else x["bbox"] - for x in annos - ] - - colors = None - category_ids = [x["category_id"] for x in annos] - if self._instance_mode == ColorMode.SEGMENTATION and self.metadata.get("thing_colors"): - colors = [ - self._jitter([x / 255 for x in self.metadata.thing_colors[c]]) - for c in category_ids - ] - names = self.metadata.get("thing_classes", None) - labels = _create_text_labels( - category_ids, - scores=None, - class_names=names, - is_crowd=[x.get("iscrowd", 0) for x in annos], - ) - self.overlay_instances( - labels=labels, boxes=boxes, masks=masks, keypoints=keypts, assigned_colors=colors - ) - - sem_seg = dic.get("sem_seg", None) - if sem_seg is None and "sem_seg_file_name" in dic: - with PathManager.open(dic["sem_seg_file_name"], "rb") as f: - sem_seg = Image.open(f) - sem_seg = np.asarray(sem_seg, dtype="uint8") - if sem_seg is not None: - self.draw_sem_seg(sem_seg, area_threshold=0, alpha=0.5) - - pan_seg = dic.get("pan_seg", None) - if pan_seg is None and "pan_seg_file_name" in dic: - with PathManager.open(dic["pan_seg_file_name"], "rb") as f: - pan_seg = Image.open(f) - pan_seg = np.asarray(pan_seg) - from panopticapi.utils import rgb2id - - pan_seg = rgb2id(pan_seg) - if pan_seg is not None: - segments_info = dic["segments_info"] - pan_seg = torch.tensor(pan_seg) - self.draw_panoptic_seg(pan_seg, segments_info, area_threshold=0, alpha=0.5) - return self.output - - def overlay_instances( - self, - *, - boxes=None, - labels=None, - masks=None, - keypoints=None, - assigned_colors=None, - alpha=0.5, - ): - """ - Args: - boxes (Boxes, RotatedBoxes or ndarray): either a :class:`Boxes`, - or an Nx4 numpy array of XYXY_ABS format for the N objects in a single image, - or a :class:`RotatedBoxes`, - or an Nx5 numpy array of (x_center, y_center, width, height, angle_degrees) format - for the N objects in a single image, - labels (list[str]): the text to be displayed for each instance. - masks (masks-like object): Supported types are: - - * :class:`detectron2.structures.PolygonMasks`, - :class:`detectron2.structures.BitMasks`. - * list[list[ndarray]]: contains the segmentation masks for all objects in one image. - The first level of the list corresponds to individual instances. The second - level to all the polygon that compose the instance, and the third level - to the polygon coordinates. The third level should have the format of - [x0, y0, x1, y1, ..., xn, yn] (n >= 3). - * list[ndarray]: each ndarray is a binary mask of shape (H, W). - * list[dict]: each dict is a COCO-style RLE. - keypoints (Keypoint or array like): an array-like object of shape (N, K, 3), - where the N is the number of instances and K is the number of keypoints. - The last dimension corresponds to (x, y, visibility or score). - assigned_colors (list[matplotlib.colors]): a list of colors, where each color - corresponds to each mask or box in the image. Refer to 'matplotlib.colors' - for full list of formats that the colors are accepted in. - - Returns: - output (VisImage): image object with visualizations. - """ - num_instances = 0 - if boxes is not None: - boxes = self._convert_boxes(boxes) - num_instances = len(boxes) - if masks is not None: - masks = self._convert_masks(masks) - if num_instances: - assert len(masks) == num_instances - else: - num_instances = len(masks) - if keypoints is not None: - if num_instances: - assert len(keypoints) == num_instances - else: - num_instances = len(keypoints) - keypoints = self._convert_keypoints(keypoints) - if labels is not None: - assert len(labels) == num_instances - if assigned_colors is None: - assigned_colors = [random_color(rgb=True, maximum=1) for _ in range(num_instances)] - if num_instances == 0: - return self.output - if boxes is not None and boxes.shape[1] == 5: - return self.overlay_rotated_instances( - boxes=boxes, labels=labels, assigned_colors=assigned_colors - ) - - # Display in largest to smallest order to reduce occlusion. - areas = None - if boxes is not None: - areas = np.prod(boxes[:, 2:] - boxes[:, :2], axis=1) - elif masks is not None: - areas = np.asarray([x.area() for x in masks]) - - if areas is not None: - sorted_idxs = np.argsort(-areas).tolist() - # Re-order overlapped instances in descending order. - boxes = boxes[sorted_idxs] if boxes is not None else None - labels = [labels[k] for k in sorted_idxs] if labels is not None else None - masks = [masks[idx] for idx in sorted_idxs] if masks is not None else None - assigned_colors = [assigned_colors[idx] for idx in sorted_idxs] - keypoints = keypoints[sorted_idxs] if keypoints is not None else None - - for i in range(num_instances): - color = assigned_colors[i] - if boxes is not None: - self.draw_box(boxes[i], edge_color=color) - - if masks is not None: - for segment in masks[i].polygons: - self.draw_polygon(segment.reshape(-1, 2), color, alpha=alpha) - - if labels is not None: - # first get a box - if boxes is not None: - x0, y0, x1, y1 = boxes[i] - text_pos = (x0, y0) # if drawing boxes, put text on the box corner. - horiz_align = "left" - elif masks is not None: - # skip small mask without polygon - if len(masks[i].polygons) == 0: - continue - - x0, y0, x1, y1 = masks[i].bbox() - - # draw text in the center (defined by median) when box is not drawn - # median is less sensitive to outliers. - text_pos = np.median(masks[i].mask.nonzero(), axis=1)[::-1] - horiz_align = "center" - else: - continue # drawing the box confidence for keypoints isn't very useful. - # for small objects, draw text at the side to avoid occlusion - instance_area = (y1 - y0) * (x1 - x0) - if ( - instance_area < _SMALL_OBJECT_AREA_THRESH * self.output.scale - or y1 - y0 < 40 * self.output.scale - ): - if y1 >= self.output.height - 5: - text_pos = (x1, y0) - else: - text_pos = (x0, y1) - - height_ratio = (y1 - y0) / np.sqrt(self.output.height * self.output.width) - lighter_color = self._change_color_brightness(color, brightness_factor=0.7) - font_size = ( - np.clip((height_ratio - 0.02) / 0.08 + 1, 1.2, 2) - * 0.5 - * self._default_font_size - ) - self.draw_text( - labels[i], - text_pos, - color=lighter_color, - horizontal_alignment=horiz_align, - font_size=font_size, - ) - - # draw keypoints - if keypoints is not None: - for keypoints_per_instance in keypoints: - self.draw_and_connect_keypoints(keypoints_per_instance) - - return self.output - - def overlay_rotated_instances(self, boxes=None, labels=None, assigned_colors=None): - """ - Args: - boxes (ndarray): an Nx5 numpy array of - (x_center, y_center, width, height, angle_degrees) format - for the N objects in a single image. - labels (list[str]): the text to be displayed for each instance. - assigned_colors (list[matplotlib.colors]): a list of colors, where each color - corresponds to each mask or box in the image. Refer to 'matplotlib.colors' - for full list of formats that the colors are accepted in. - - Returns: - output (VisImage): image object with visualizations. - """ - num_instances = len(boxes) - - if assigned_colors is None: - assigned_colors = [random_color(rgb=True, maximum=1) for _ in range(num_instances)] - if num_instances == 0: - return self.output - - # Display in largest to smallest order to reduce occlusion. - if boxes is not None: - areas = boxes[:, 2] * boxes[:, 3] - - sorted_idxs = np.argsort(-areas).tolist() - # Re-order overlapped instances in descending order. - boxes = boxes[sorted_idxs] - labels = [labels[k] for k in sorted_idxs] if labels is not None else None - colors = [assigned_colors[idx] for idx in sorted_idxs] - - for i in range(num_instances): - self.draw_rotated_box_with_label( - boxes[i], edge_color=colors[i], label=labels[i] if labels is not None else None - ) - - return self.output - - def draw_and_connect_keypoints(self, keypoints): - """ - Draws keypoints of an instance and follows the rules for keypoint connections - to draw lines between appropriate keypoints. This follows color heuristics for - line color. - - Args: - keypoints (Tensor): a tensor of shape (K, 3), where K is the number of keypoints - and the last dimension corresponds to (x, y, probability). - - Returns: - output (VisImage): image object with visualizations. - """ - visible = {} - keypoint_names = self.metadata.get("keypoint_names") - for idx, keypoint in enumerate(keypoints): - # draw keypoint - x, y, prob = keypoint - if prob > self.keypoint_threshold: - self.draw_circle((x, y), color=_RED) - if keypoint_names: - keypoint_name = keypoint_names[idx] - visible[keypoint_name] = (x, y) - - if self.metadata.get("keypoint_connection_rules"): - for kp0, kp1, color in self.metadata.keypoint_connection_rules: - if kp0 in visible and kp1 in visible: - x0, y0 = visible[kp0] - x1, y1 = visible[kp1] - color = tuple(x / 255.0 for x in color) - self.draw_line([x0, x1], [y0, y1], color=color) - - # draw lines from nose to mid-shoulder and mid-shoulder to mid-hip - # Note that this strategy is specific to person keypoints. - # For other keypoints, it should just do nothing - try: - ls_x, ls_y = visible["left_shoulder"] - rs_x, rs_y = visible["right_shoulder"] - mid_shoulder_x, mid_shoulder_y = (ls_x + rs_x) / 2, (ls_y + rs_y) / 2 - except KeyError: - pass - else: - # draw line from nose to mid-shoulder - nose_x, nose_y = visible.get("nose", (None, None)) - if nose_x is not None: - self.draw_line([nose_x, mid_shoulder_x], [nose_y, mid_shoulder_y], color=_RED) - - try: - # draw line from mid-shoulder to mid-hip - lh_x, lh_y = visible["left_hip"] - rh_x, rh_y = visible["right_hip"] - except KeyError: - pass - else: - mid_hip_x, mid_hip_y = (lh_x + rh_x) / 2, (lh_y + rh_y) / 2 - self.draw_line([mid_hip_x, mid_shoulder_x], [mid_hip_y, mid_shoulder_y], color=_RED) - return self.output - - """ - Primitive drawing functions: - """ - - def draw_text( - self, - text, - position, - *, - font_size=None, - color="g", - horizontal_alignment="center", - rotation=0, - ): - """ - Args: - text (str): class label - position (tuple): a tuple of the x and y coordinates to place text on image. - font_size (int, optional): font of the text. If not provided, a font size - proportional to the image width is calculated and used. - color: color of the text. Refer to `matplotlib.colors` for full list - of formats that are accepted. - horizontal_alignment (str): see `matplotlib.text.Text` - rotation: rotation angle in degrees CCW - - Returns: - output (VisImage): image object with text drawn. - """ - if not font_size: - font_size = self._default_font_size - - # since the text background is dark, we don't want the text to be dark - color = np.maximum(list(mplc.to_rgb(color)), 0.2) - color[np.argmax(color)] = max(0.8, np.max(color)) - - x, y = position - self.output.ax.text( - x, - y, - text, - size=font_size * self.output.scale, - family="sans-serif", - bbox={"facecolor": "black", "alpha": 0.8, "pad": 0.7, "edgecolor": "none"}, - verticalalignment="top", - horizontalalignment=horizontal_alignment, - color=color, - zorder=10, - rotation=rotation, - ) - return self.output - - def draw_box(self, box_coord, alpha=0.5, edge_color="g", line_style="-"): - """ - Args: - box_coord (tuple): a tuple containing x0, y0, x1, y1 coordinates, where x0 and y0 - are the coordinates of the image's top left corner. x1 and y1 are the - coordinates of the image's bottom right corner. - alpha (float): blending efficient. Smaller values lead to more transparent masks. - edge_color: color of the outline of the box. Refer to `matplotlib.colors` - for full list of formats that are accepted. - line_style (string): the string to use to create the outline of the boxes. - - Returns: - output (VisImage): image object with box drawn. - """ - x0, y0, x1, y1 = box_coord - width = x1 - x0 - height = y1 - y0 - - linewidth = max(self._default_font_size / 4, 1) - - self.output.ax.add_patch( - mpl.patches.Rectangle( - (x0, y0), - width, - height, - fill=False, - edgecolor=edge_color, - linewidth=linewidth * self.output.scale, - alpha=alpha, - linestyle=line_style, - ) - ) - return self.output - - def draw_rotated_box_with_label( - self, rotated_box, alpha=0.5, edge_color="g", line_style="-", label=None - ): - """ - Draw a rotated box with label on its top-left corner. - - Args: - rotated_box (tuple): a tuple containing (cnt_x, cnt_y, w, h, angle), - where cnt_x and cnt_y are the center coordinates of the box. - w and h are the width and height of the box. angle represents how - many degrees the box is rotated CCW with regard to the 0-degree box. - alpha (float): blending efficient. Smaller values lead to more transparent masks. - edge_color: color of the outline of the box. Refer to `matplotlib.colors` - for full list of formats that are accepted. - line_style (string): the string to use to create the outline of the boxes. - label (string): label for rotated box. It will not be rendered when set to None. - - Returns: - output (VisImage): image object with box drawn. - """ - cnt_x, cnt_y, w, h, angle = rotated_box - area = w * h - # use thinner lines when the box is small - linewidth = self._default_font_size / ( - 6 if area < _SMALL_OBJECT_AREA_THRESH * self.output.scale else 3 - ) - - theta = angle * math.pi / 180.0 - c = math.cos(theta) - s = math.sin(theta) - rect = [(-w / 2, h / 2), (-w / 2, -h / 2), (w / 2, -h / 2), (w / 2, h / 2)] - # x: left->right ; y: top->down - rotated_rect = [(s * yy + c * xx + cnt_x, c * yy - s * xx + cnt_y) for (xx, yy) in rect] - for k in range(4): - j = (k + 1) % 4 - self.draw_line( - [rotated_rect[k][0], rotated_rect[j][0]], - [rotated_rect[k][1], rotated_rect[j][1]], - color=edge_color, - linestyle="--" if k == 1 else line_style, - linewidth=linewidth, - ) - - if label is not None: - text_pos = rotated_rect[1] # topleft corner - - height_ratio = h / np.sqrt(self.output.height * self.output.width) - label_color = self._change_color_brightness(edge_color, brightness_factor=0.7) - font_size = ( - np.clip((height_ratio - 0.02) / 0.08 + 1, 1.2, 2) * 0.5 * self._default_font_size - ) - self.draw_text(label, text_pos, color=label_color, font_size=font_size, rotation=angle) - - return self.output - - def draw_circle(self, circle_coord, color, radius=3): - """ - Args: - circle_coord (list(int) or tuple(int)): contains the x and y coordinates - of the center of the circle. - color: color of the polygon. Refer to `matplotlib.colors` for a full list of - formats that are accepted. - radius (int): radius of the circle. - - Returns: - output (VisImage): image object with box drawn. - """ - x, y = circle_coord - self.output.ax.add_patch( - mpl.patches.Circle(circle_coord, radius=radius, fill=True, color=color) - ) - return self.output - - def draw_line(self, x_data, y_data, color, linestyle="-", linewidth=None): - """ - Args: - x_data (list[int]): a list containing x values of all the points being drawn. - Length of list should match the length of y_data. - y_data (list[int]): a list containing y values of all the points being drawn. - Length of list should match the length of x_data. - color: color of the line. Refer to `matplotlib.colors` for a full list of - formats that are accepted. - linestyle: style of the line. Refer to `matplotlib.lines.Line2D` - for a full list of formats that are accepted. - linewidth (float or None): width of the line. When it's None, - a default value will be computed and used. - - Returns: - output (VisImage): image object with line drawn. - """ - if linewidth is None: - linewidth = self._default_font_size / 3 - linewidth = max(linewidth, 1) - self.output.ax.add_line( - mpl.lines.Line2D( - x_data, - y_data, - linewidth=linewidth * self.output.scale, - color=color, - linestyle=linestyle, - ) - ) - return self.output - - def draw_binary_mask( - self, binary_mask, color=None, *, edge_color=None, text=None, alpha=0.5, area_threshold=0 - ): - """ - Args: - binary_mask (ndarray): numpy array of shape (H, W), where H is the image height and - W is the image width. Each value in the array is either a 0 or 1 value of uint8 - type. - color: color of the mask. Refer to `matplotlib.colors` for a full list of - formats that are accepted. If None, will pick a random color. - edge_color: color of the polygon edges. Refer to `matplotlib.colors` for a - full list of formats that are accepted. - text (str): if None, will be drawn in the object's center of mass. - alpha (float): blending efficient. Smaller values lead to more transparent masks. - area_threshold (float): a connected component small than this will not be shown. - - Returns: - output (VisImage): image object with mask drawn. - """ - if color is None: - color = random_color(rgb=True, maximum=1) - color = mplc.to_rgb(color) - - has_valid_segment = False - binary_mask = binary_mask.astype("uint8") # opencv needs uint8 - mask = GenericMask(binary_mask, self.output.height, self.output.width) - shape2d = (binary_mask.shape[0], binary_mask.shape[1]) - - if not mask.has_holes: - # draw polygons for regular masks - for segment in mask.polygons: - area = mask_util.area(mask_util.frPyObjects([segment], shape2d[0], shape2d[1])) - if area < (area_threshold or 0): - continue - has_valid_segment = True - segment = segment.reshape(-1, 2) - self.draw_polygon(segment, color=color, edge_color=edge_color, alpha=alpha) - else: - # TODO: Use Path/PathPatch to draw vector graphics: - # https://stackoverflow.com/questions/8919719/how-to-plot-a-complex-polygon - rgba = np.zeros(shape2d + (4,), dtype="float32") - rgba[:, :, :3] = color - rgba[:, :, 3] = (mask.mask == 1).astype("float32") * alpha - has_valid_segment = True - self.output.ax.imshow(rgba, extent=(0, self.output.width, self.output.height, 0)) - - if text is not None and has_valid_segment: - # TODO sometimes drawn on wrong objects. the heuristics here can improve. - lighter_color = self._change_color_brightness(color, brightness_factor=0.7) - _num_cc, cc_labels, stats, centroids = cv2.connectedComponentsWithStats(binary_mask, 8) - largest_component_id = np.argmax(stats[1:, -1]) + 1 - - # draw text on the largest component, as well as other very large components. - for cid in range(1, _num_cc): - if cid == largest_component_id or stats[cid, -1] > _LARGE_MASK_AREA_THRESH: - # median is more stable than centroid - # center = centroids[largest_component_id] - center = np.median((cc_labels == cid).nonzero(), axis=1)[::-1] - self.draw_text(text, center, color=lighter_color) - return self.output - - def draw_polygon(self, segment, color, edge_color=None, alpha=0.5): - """ - Args: - segment: numpy array of shape Nx2, containing all the points in the polygon. - color: color of the polygon. Refer to `matplotlib.colors` for a full list of - formats that are accepted. - edge_color: color of the polygon edges. Refer to `matplotlib.colors` for a - full list of formats that are accepted. If not provided, a darker shade - of the polygon color will be used instead. - alpha (float): blending efficient. Smaller values lead to more transparent masks. - - Returns: - output (VisImage): image object with polygon drawn. - """ - if edge_color is None: - # make edge color darker than the polygon color - if alpha > 0.8: - edge_color = self._change_color_brightness(color, brightness_factor=-0.7) - else: - edge_color = color - edge_color = mplc.to_rgb(edge_color) + (1,) - - polygon = mpl.patches.Polygon( - segment, - fill=True, - facecolor=mplc.to_rgb(color) + (alpha,), - edgecolor=edge_color, - linewidth=max(self._default_font_size // 15 * self.output.scale, 1), - ) - self.output.ax.add_patch(polygon) - return self.output - - """ - Internal methods: - """ - - def _jitter(self, color): - """ - Randomly modifies given color to produce a slightly different color than the color given. - - Args: - color (tuple[double]): a tuple of 3 elements, containing the RGB values of the color - picked. The values in the list are in the [0.0, 1.0] range. - - Returns: - jittered_color (tuple[double]): a tuple of 3 elements, containing the RGB values of the - color after being jittered. The values in the list are in the [0.0, 1.0] range. - """ - color = mplc.to_rgb(color) - vec = np.random.rand(3) - # better to do it in another color space - vec = vec / np.linalg.norm(vec) * 0.5 - res = np.clip(vec + color, 0, 1) - return tuple(res) - - def _create_grayscale_image(self, mask=None): - """ - Create a grayscale version of the original image. - The colors in masked area, if given, will be kept. - """ - img_bw = self.img.astype("f4").mean(axis=2) - img_bw = np.stack([img_bw] * 3, axis=2) - if mask is not None: - img_bw[mask] = self.img[mask] - return img_bw - - def _change_color_brightness(self, color, brightness_factor): - """ - Depending on the brightness_factor, gives a lighter or darker color i.e. a color with - less or more saturation than the original color. - - Args: - color: color of the polygon. Refer to `matplotlib.colors` for a full list of - formats that are accepted. - brightness_factor (float): a value in [-1.0, 1.0] range. A lightness factor of - 0 will correspond to no change, a factor in [-1.0, 0) range will result in - a darker color and a factor in (0, 1.0] range will result in a lighter color. - - Returns: - modified_color (tuple[double]): a tuple containing the RGB values of the - modified color. Each value in the tuple is in the [0.0, 1.0] range. - """ - assert brightness_factor >= -1.0 and brightness_factor <= 1.0 - color = mplc.to_rgb(color) - polygon_color = colorsys.rgb_to_hls(*mplc.to_rgb(color)) - modified_lightness = polygon_color[1] + (brightness_factor * polygon_color[1]) - modified_lightness = 0.0 if modified_lightness < 0.0 else modified_lightness - modified_lightness = 1.0 if modified_lightness > 1.0 else modified_lightness - modified_color = colorsys.hls_to_rgb(polygon_color[0], modified_lightness, polygon_color[2]) - return modified_color - - def _convert_boxes(self, boxes): - """ - Convert different format of boxes to an NxB array, where B = 4 or 5 is the box dimension. - """ - if isinstance(boxes, Boxes) or isinstance(boxes, RotatedBoxes): - return boxes.tensor.detach().numpy() - else: - return np.asarray(boxes) - - def _convert_masks(self, masks_or_polygons): - """ - Convert different format of masks or polygons to a tuple of masks and polygons. - - Returns: - list[GenericMask]: - """ - - m = masks_or_polygons - if isinstance(m, PolygonMasks): - m = m.polygons - if isinstance(m, BitMasks): - m = m.tensor.numpy() - if isinstance(m, torch.Tensor): - m = m.numpy() - ret = [] - for x in m: - if isinstance(x, GenericMask): - ret.append(x) - else: - ret.append(GenericMask(x, self.output.height, self.output.width)) - return ret - - def _convert_keypoints(self, keypoints): - if isinstance(keypoints, Keypoints): - keypoints = keypoints.tensor - keypoints = np.asarray(keypoints) - return keypoints - - def get_output(self): - """ - Returns: - output (VisImage): the image output containing the visualizations added - to the image. - """ - return self.output diff --git a/magic_pdf/model/sub_modules/mfd/__init__.py b/magic_pdf/model/sub_modules/mfd/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/mfd/yolov8/__init__.py b/magic_pdf/model/sub_modules/mfd/yolov8/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/mfr/__init__.py b/magic_pdf/model/sub_modules/mfr/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/__init__.py b/magic_pdf/model/sub_modules/mfr/unimernet/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/model_init.py b/magic_pdf/model/sub_modules/model_init.py deleted file mode 100644 index b885606dd64599897c29d41acfca3f6a843beacc..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/model_init.py +++ /dev/null @@ -1,213 +0,0 @@ -import torch -from loguru import logger - -from magic_pdf.config.constants import MODEL_NAME -from magic_pdf.model.model_list import AtomicModel -from magic_pdf.model.sub_modules.language_detection.yolov11.YOLOv11 import YOLOv11LangDetModel -from magic_pdf.model.sub_modules.layout.doclayout_yolo.DocLayoutYOLO import DocLayoutYOLOModel -from magic_pdf.model.sub_modules.mfd.yolov8.YOLOv8 import YOLOv8MFDModel -from magic_pdf.model.sub_modules.mfr.unimernet.Unimernet import UnimernetModel -from magic_pdf.model.sub_modules.ocr.paddleocr2pytorch.pytorch_paddle import PytorchPaddleOCR -from magic_pdf.model.sub_modules.table.rapidtable.rapid_table import RapidTableModel -# try: -# from magic_pdf_ascend_plugin.libs.license_verifier import ( -# LicenseExpiredError, LicenseFormatError, LicenseSignatureError, -# load_license) -# from magic_pdf_ascend_plugin.model_plugin.ocr.paddleocr.ppocr_273_npu import ModifiedPaddleOCR -# from magic_pdf_ascend_plugin.model_plugin.table.rapidtable.rapid_table_npu import RapidTableModel -# license_key = load_license() -# logger.info(f'Using Ascend Plugin Success, License id is {license_key["payload"]["id"]},' -# f' License expired at {license_key["payload"]["date"]["end_date"]}') -# except Exception as e: -# if isinstance(e, ImportError): -# pass -# elif isinstance(e, LicenseFormatError): -# logger.error('Ascend Plugin: Invalid license format. Please check the license file.') -# elif isinstance(e, LicenseSignatureError): -# logger.error('Ascend Plugin: Invalid signature. The license may be tampered with.') -# elif isinstance(e, LicenseExpiredError): -# logger.error('Ascend Plugin: License has expired. Please renew your license.') -# elif isinstance(e, FileNotFoundError): -# logger.error('Ascend Plugin: Not found License file.') -# else: -# logger.error(f'Ascend Plugin: {e}') -# from magic_pdf.model.sub_modules.ocr.paddleocr.ppocr_273_mod import ModifiedPaddleOCR -# # from magic_pdf.model.sub_modules.ocr.paddleocr.ppocr_291_mod import ModifiedPaddleOCR -# from magic_pdf.model.sub_modules.table.rapidtable.rapid_table import RapidTableModel - - -def table_model_init(table_model_type, model_path, max_time, _device_='cpu', lang=None, table_sub_model_name=None): - if table_model_type == MODEL_NAME.STRUCT_EQTABLE: - from magic_pdf.model.sub_modules.table.structeqtable.struct_eqtable import StructTableModel - table_model = StructTableModel(model_path, max_new_tokens=2048, max_time=max_time) - elif table_model_type == MODEL_NAME.TABLE_MASTER: - from magic_pdf.model.sub_modules.table.tablemaster.tablemaster_paddle import TableMasterPaddleModel - config = { - 'model_dir': model_path, - 'device': _device_ - } - table_model = TableMasterPaddleModel(config) - elif table_model_type == MODEL_NAME.RAPID_TABLE: - atom_model_manager = AtomModelSingleton() - ocr_engine = atom_model_manager.get_atom_model( - atom_model_name='ocr', - ocr_show_log=False, - det_db_box_thresh=0.5, - det_db_unclip_ratio=1.6, - lang=lang - ) - table_model = RapidTableModel(ocr_engine, table_sub_model_name) - else: - logger.error('table model type not allow') - exit(1) - - return table_model - - -def mfd_model_init(weight, device='cpu'): - if str(device).startswith('npu'): - device = torch.device(device) - mfd_model = YOLOv8MFDModel(weight, device) - return mfd_model - - -def mfr_model_init(weight_dir, cfg_path, device='cpu'): - mfr_model = UnimernetModel(weight_dir, cfg_path, device) - return mfr_model - - -def layout_model_init(weight, config_file, device): - from magic_pdf.model.sub_modules.layout.layoutlmv3.model_init import Layoutlmv3_Predictor - model = Layoutlmv3_Predictor(weight, config_file, device) - return model - - -def doclayout_yolo_model_init(weight, device='cpu'): - if str(device).startswith('npu'): - device = torch.device(device) - model = DocLayoutYOLOModel(weight, device) - return model - - -def langdetect_model_init(langdetect_model_weight, device='cpu'): - if str(device).startswith('npu'): - device = torch.device(device) - model = YOLOv11LangDetModel(langdetect_model_weight, device) - return model - - -def ocr_model_init(show_log: bool = False, - det_db_box_thresh=0.3, - lang=None, - use_dilation=True, - det_db_unclip_ratio=1.8, - ): - if lang is not None and lang != '': - # model = ModifiedPaddleOCR( - model = PytorchPaddleOCR( - show_log=show_log, - det_db_box_thresh=det_db_box_thresh, - lang=lang, - use_dilation=use_dilation, - det_db_unclip_ratio=det_db_unclip_ratio, - ) - else: - # model = ModifiedPaddleOCR( - model = PytorchPaddleOCR( - show_log=show_log, - det_db_box_thresh=det_db_box_thresh, - use_dilation=use_dilation, - det_db_unclip_ratio=det_db_unclip_ratio, - ) - return model - - -class AtomModelSingleton: - _instance = None - _models = {} - - def __new__(cls, *args, **kwargs): - if cls._instance is None: - cls._instance = super().__new__(cls) - return cls._instance - - def get_atom_model(self, atom_model_name: str, **kwargs): - - lang = kwargs.get('lang', None) - layout_model_name = kwargs.get('layout_model_name', None) - table_model_name = kwargs.get('table_model_name', None) - - if atom_model_name in [AtomicModel.OCR]: - key = (atom_model_name, lang) - elif atom_model_name in [AtomicModel.Layout]: - key = (atom_model_name, layout_model_name) - elif atom_model_name in [AtomicModel.Table]: - key = (atom_model_name, table_model_name, lang) - else: - key = atom_model_name - - if key not in self._models: - self._models[key] = atom_model_init(model_name=atom_model_name, **kwargs) - return self._models[key] - -def atom_model_init(model_name: str, **kwargs): - atom_model = None - if model_name == AtomicModel.Layout: - if kwargs.get('layout_model_name') == MODEL_NAME.LAYOUTLMv3: - atom_model = layout_model_init( - kwargs.get('layout_weights'), - kwargs.get('layout_config_file'), - kwargs.get('device') - ) - elif kwargs.get('layout_model_name') == MODEL_NAME.DocLayout_YOLO: - atom_model = doclayout_yolo_model_init( - kwargs.get('doclayout_yolo_weights'), - kwargs.get('device') - ) - else: - logger.error('layout model name not allow') - exit(1) - elif model_name == AtomicModel.MFD: - atom_model = mfd_model_init( - kwargs.get('mfd_weights'), - kwargs.get('device') - ) - elif model_name == AtomicModel.MFR: - atom_model = mfr_model_init( - kwargs.get('mfr_weight_dir'), - kwargs.get('mfr_cfg_path'), - kwargs.get('device') - ) - elif model_name == AtomicModel.OCR: - atom_model = ocr_model_init( - kwargs.get('ocr_show_log'), - kwargs.get('det_db_box_thresh'), - kwargs.get('lang'), - ) - elif model_name == AtomicModel.Table: - atom_model = table_model_init( - kwargs.get('table_model_name'), - kwargs.get('table_model_path'), - kwargs.get('table_max_time'), - kwargs.get('device'), - kwargs.get('lang'), - kwargs.get('table_sub_model_name') - ) - elif model_name == AtomicModel.LangDetect: - if kwargs.get('langdetect_model_name') == MODEL_NAME.YOLO_V11_LangDetect: - atom_model = langdetect_model_init( - kwargs.get('langdetect_model_weight'), - kwargs.get('device') - ) - else: - logger.error('langdetect model name not allow') - exit(1) - else: - logger.error('model name not allow') - exit(1) - - if atom_model is None: - logger.error('model init failed') - exit(1) - else: - return atom_model diff --git a/magic_pdf/model/sub_modules/ocr/__init__.py b/magic_pdf/model/sub_modules/ocr/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/__init__.py b/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/__init__.py deleted file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/__init__.py b/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_pphgnetv2.py b/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_pphgnetv2.py deleted file mode 100644 index 390ca4c61b4b7fd1635d5229d5ef3d79fc3509fe..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_pphgnetv2.py +++ /dev/null @@ -1,810 +0,0 @@ -import math -import torch -import torch.nn as nn -import torch.nn.functional as F - - -class AdaptiveAvgPool2D(nn.AdaptiveAvgPool2d): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - if isinstance(self.output_size, int) and self.output_size == 1: - self._gap = True - elif ( - isinstance(self.output_size, tuple) - and self.output_size[0] == 1 - and self.output_size[1] == 1 - ): - self._gap = True - else: - self._gap = False - - def forward(self, x): - if self._gap: - # Global Average Pooling - N, C, _, _ = x.shape - x_mean = torch.mean(x, dim=[2, 3]) - x_mean = torch.reshape(x_mean, [N, C, 1, 1]) - return x_mean - else: - return F.adaptive_avg_pool2d( - x, - output_size=self.output_size - ) - -class LearnableAffineBlock(nn.Module): - """ - Create a learnable affine block module. This module can significantly improve accuracy on smaller models. - - Args: - scale_value (float): The initial value of the scale parameter, default is 1.0. - bias_value (float): The initial value of the bias parameter, default is 0.0. - lr_mult (float): The learning rate multiplier, default is 1.0. - lab_lr (float): The learning rate, default is 0.01. - """ - - def __init__(self, scale_value=1.0, bias_value=0.0, lr_mult=1.0, lab_lr=0.01): - super().__init__() - self.scale = nn.Parameter(torch.Tensor([scale_value])) - self.bias = nn.Parameter(torch.Tensor([bias_value])) - - def forward(self, x): - return self.scale * x + self.bias - - -class ConvBNAct(nn.Module): - """ - ConvBNAct is a combination of convolution and batchnorm layers. - - Args: - in_channels (int): Number of input channels. - out_channels (int): Number of output channels. - kernel_size (int): Size of the convolution kernel. Defaults to 3. - stride (int): Stride of the convolution. Defaults to 1. - padding (int/str): Padding or padding type for the convolution. Defaults to 1. - groups (int): Number of groups for the convolution. Defaults to 1. - use_act: (bool): Whether to use activation function. Defaults to True. - use_lab (bool): Whether to use the LAB operation. Defaults to False. - lr_mult (float): Learning rate multiplier for the layer. Defaults to 1.0. - """ - - def __init__( - self, - in_channels, - out_channels, - kernel_size=3, - stride=1, - padding=1, - groups=1, - use_act=True, - use_lab=False, - lr_mult=1.0, - ): - super().__init__() - self.use_act = use_act - self.use_lab = use_lab - - self.conv = nn.Conv2d( - in_channels, - out_channels, - kernel_size, - stride, - padding=padding if isinstance(padding, str) else (kernel_size - 1) // 2, - # padding=(kernel_size - 1) // 2, - groups=groups, - bias=False, - ) - self.bn = nn.BatchNorm2d( - out_channels, - ) - if self.use_act: - self.act = nn.ReLU() - if self.use_lab: - self.lab = LearnableAffineBlock(lr_mult=lr_mult) - - def forward(self, x): - x = self.conv(x) - x = self.bn(x) - if self.use_act: - x = self.act(x) - if self.use_lab: - x = self.lab(x) - return x - - -class LightConvBNAct(nn.Module): - """ - LightConvBNAct is a combination of pw and dw layers. - - Args: - in_channels (int): Number of input channels. - out_channels (int): Number of output channels. - kernel_size (int): Size of the depth-wise convolution kernel. - use_lab (bool): Whether to use the LAB operation. Defaults to False. - lr_mult (float): Learning rate multiplier for the layer. Defaults to 1.0. - """ - - def __init__( - self, - in_channels, - out_channels, - kernel_size, - use_lab=False, - lr_mult=1.0, - **kwargs, - ): - super().__init__() - self.conv1 = ConvBNAct( - in_channels=in_channels, - out_channels=out_channels, - kernel_size=1, - use_act=False, - use_lab=use_lab, - lr_mult=lr_mult, - ) - self.conv2 = ConvBNAct( - in_channels=out_channels, - out_channels=out_channels, - kernel_size=kernel_size, - groups=out_channels, - use_act=True, - use_lab=use_lab, - lr_mult=lr_mult, - ) - - def forward(self, x): - x = self.conv1(x) - x = self.conv2(x) - return x - - -class CustomMaxPool2d(nn.Module): - def __init__( - self, - kernel_size, - stride=None, - padding=0, - dilation=1, - return_indices=False, - ceil_mode=False, - data_format="NCHW", - ): - super(CustomMaxPool2d, self).__init__() - self.kernel_size = kernel_size if isinstance(kernel_size, (tuple, list)) else (kernel_size, kernel_size) - self.stride = stride if stride is not None else self.kernel_size - self.stride = self.stride if isinstance(self.stride, (tuple, list)) else (self.stride, self.stride) - self.dilation = dilation if isinstance(dilation, (tuple, list)) else (dilation, dilation) - self.return_indices = return_indices - self.ceil_mode = ceil_mode - self.padding_mode = padding - - # 当padding不是"same"时使用标准MaxPool2d - if padding != "same": - self.padding = padding if isinstance(padding, (tuple, list)) else (padding, padding) - self.pool = nn.MaxPool2d( - kernel_size=self.kernel_size, - stride=self.stride, - padding=self.padding, - dilation=self.dilation, - return_indices=self.return_indices, - ceil_mode=self.ceil_mode - ) - - def forward(self, x): - # 处理same padding - if self.padding_mode == "same": - input_height, input_width = x.size(2), x.size(3) - - # 计算期望的输出尺寸 - out_height = math.ceil(input_height / self.stride[0]) - out_width = math.ceil(input_width / self.stride[1]) - - # 计算需要的padding - pad_height = max((out_height - 1) * self.stride[0] + self.kernel_size[0] - input_height, 0) - pad_width = max((out_width - 1) * self.stride[1] + self.kernel_size[1] - input_width, 0) - - # 将padding分配到两边 - pad_top = pad_height // 2 - pad_bottom = pad_height - pad_top - pad_left = pad_width // 2 - pad_right = pad_width - pad_left - - # 应用padding - x = F.pad(x, (pad_left, pad_right, pad_top, pad_bottom)) - - # 使用标准max_pool2d函数 - if self.return_indices: - return F.max_pool2d_with_indices( - x, - kernel_size=self.kernel_size, - stride=self.stride, - padding=0, # 已经手动pad过了 - dilation=self.dilation, - ceil_mode=self.ceil_mode - ) - else: - return F.max_pool2d( - x, - kernel_size=self.kernel_size, - stride=self.stride, - padding=0, # 已经手动pad过了 - dilation=self.dilation, - ceil_mode=self.ceil_mode - ) - else: - # 使用预定义的MaxPool2d - return self.pool(x) - -class StemBlock(nn.Module): - """ - StemBlock for PP-HGNetV2. - - Args: - in_channels (int): Number of input channels. - mid_channels (int): Number of middle channels. - out_channels (int): Number of output channels. - use_lab (bool): Whether to use the LAB operation. Defaults to False. - lr_mult (float): Learning rate multiplier for the layer. Defaults to 1.0. - """ - - def __init__( - self, - in_channels, - mid_channels, - out_channels, - use_lab=False, - lr_mult=1.0, - text_rec=False, - ): - super().__init__() - self.stem1 = ConvBNAct( - in_channels=in_channels, - out_channels=mid_channels, - kernel_size=3, - stride=2, - use_lab=use_lab, - lr_mult=lr_mult, - ) - self.stem2a = ConvBNAct( - in_channels=mid_channels, - out_channels=mid_channels // 2, - kernel_size=2, - stride=1, - padding="same", - use_lab=use_lab, - lr_mult=lr_mult, - ) - self.stem2b = ConvBNAct( - in_channels=mid_channels // 2, - out_channels=mid_channels, - kernel_size=2, - stride=1, - padding="same", - use_lab=use_lab, - lr_mult=lr_mult, - ) - self.stem3 = ConvBNAct( - in_channels=mid_channels * 2, - out_channels=mid_channels, - kernel_size=3, - stride=1 if text_rec else 2, - use_lab=use_lab, - lr_mult=lr_mult, - ) - self.stem4 = ConvBNAct( - in_channels=mid_channels, - out_channels=out_channels, - kernel_size=1, - stride=1, - use_lab=use_lab, - lr_mult=lr_mult, - ) - self.pool = CustomMaxPool2d( - kernel_size=2, stride=1, ceil_mode=True, padding="same" - ) - # self.pool = nn.MaxPool2d( - # kernel_size=2, stride=1, ceil_mode=True, padding=1 - # ) - - def forward(self, x): - x = self.stem1(x) - x2 = self.stem2a(x) - x2 = self.stem2b(x2) - x1 = self.pool(x) - - # if x1.shape[2:] != x2.shape[2:]: - # x1 = F.interpolate(x1, size=x2.shape[2:], mode='bilinear', align_corners=False) - - x = torch.cat([x1, x2], 1) - x = self.stem3(x) - x = self.stem4(x) - - return x - - -class HGV2_Block(nn.Module): - """ - HGV2_Block, the basic unit that constitutes the HGV2_Stage. - - Args: - in_channels (int): Number of input channels. - mid_channels (int): Number of middle channels. - out_channels (int): Number of output channels. - kernel_size (int): Size of the convolution kernel. Defaults to 3. - layer_num (int): Number of layers in the HGV2 block. Defaults to 6. - stride (int): Stride of the convolution. Defaults to 1. - padding (int/str): Padding or padding type for the convolution. Defaults to 1. - groups (int): Number of groups for the convolution. Defaults to 1. - use_act (bool): Whether to use activation function. Defaults to True. - use_lab (bool): Whether to use the LAB operation. Defaults to False. - lr_mult (float): Learning rate multiplier for the layer. Defaults to 1.0. - """ - - def __init__( - self, - in_channels, - mid_channels, - out_channels, - kernel_size=3, - layer_num=6, - identity=False, - light_block=True, - use_lab=False, - lr_mult=1.0, - ): - super().__init__() - self.identity = identity - - self.layers = nn.ModuleList() - block_type = "LightConvBNAct" if light_block else "ConvBNAct" - for i in range(layer_num): - self.layers.append( - eval(block_type)( - in_channels=in_channels if i == 0 else mid_channels, - out_channels=mid_channels, - stride=1, - kernel_size=kernel_size, - use_lab=use_lab, - lr_mult=lr_mult, - ) - ) - # feature aggregation - total_channels = in_channels + layer_num * mid_channels - self.aggregation_squeeze_conv = ConvBNAct( - in_channels=total_channels, - out_channels=out_channels // 2, - kernel_size=1, - stride=1, - use_lab=use_lab, - lr_mult=lr_mult, - ) - self.aggregation_excitation_conv = ConvBNAct( - in_channels=out_channels // 2, - out_channels=out_channels, - kernel_size=1, - stride=1, - use_lab=use_lab, - lr_mult=lr_mult, - ) - - def forward(self, x): - identity = x - output = [] - output.append(x) - for layer in self.layers: - x = layer(x) - output.append(x) - x = torch.cat(output, dim=1) - x = self.aggregation_squeeze_conv(x) - x = self.aggregation_excitation_conv(x) - if self.identity: - x += identity - return x - - -class HGV2_Stage(nn.Module): - """ - HGV2_Stage, the basic unit that constitutes the PPHGNetV2. - - Args: - in_channels (int): Number of input channels. - mid_channels (int): Number of middle channels. - out_channels (int): Number of output channels. - block_num (int): Number of blocks in the HGV2 stage. - layer_num (int): Number of layers in the HGV2 block. Defaults to 6. - is_downsample (bool): Whether to use downsampling operation. Defaults to False. - light_block (bool): Whether to use light block. Defaults to True. - kernel_size (int): Size of the convolution kernel. Defaults to 3. - use_lab (bool, optional): Whether to use the LAB operation. Defaults to False. - lr_mult (float, optional): Learning rate multiplier for the layer. Defaults to 1.0. - """ - - def __init__( - self, - in_channels, - mid_channels, - out_channels, - block_num, - layer_num=6, - is_downsample=True, - light_block=True, - kernel_size=3, - use_lab=False, - stride=2, - lr_mult=1.0, - ): - - super().__init__() - self.is_downsample = is_downsample - if self.is_downsample: - self.downsample = ConvBNAct( - in_channels=in_channels, - out_channels=in_channels, - kernel_size=3, - stride=stride, - groups=in_channels, - use_act=False, - use_lab=use_lab, - lr_mult=lr_mult, - ) - - blocks_list = [] - for i in range(block_num): - blocks_list.append( - HGV2_Block( - in_channels=in_channels if i == 0 else out_channels, - mid_channels=mid_channels, - out_channels=out_channels, - kernel_size=kernel_size, - layer_num=layer_num, - identity=False if i == 0 else True, - light_block=light_block, - use_lab=use_lab, - lr_mult=lr_mult, - ) - ) - self.blocks = nn.Sequential(*blocks_list) - - def forward(self, x): - if self.is_downsample: - x = self.downsample(x) - x = self.blocks(x) - return x - - -class DropoutInferDownscale(nn.Module): - """ - 实现与Paddle的mode="downscale_in_infer"等效的Dropout - 训练模式:out = input * mask(直接应用掩码,不进行放大) - 推理模式:out = input * (1.0 - p)(在推理时按概率缩小) - """ - - def __init__(self, p=0.5): - super().__init__() - self.p = p - - def forward(self, x): - if self.training: - # 训练时:应用随机mask但不放大 - return F.dropout(x, self.p, training=True) * (1.0 - self.p) - else: - # 推理时:按照dropout概率缩小输出 - return x * (1.0 - self.p) - -class PPHGNetV2(nn.Module): - """ - PPHGNetV2 - - Args: - stage_config (dict): Config for PPHGNetV2 stages. such as the number of channels, stride, etc. - stem_channels: (list): Number of channels of the stem of the PPHGNetV2. - use_lab (bool): Whether to use the LAB operation. Defaults to False. - use_last_conv (bool): Whether to use the last conv layer as the output channel. Defaults to True. - class_expand (int): Number of channels for the last 1x1 convolutional layer. - drop_prob (float): Dropout probability for the last 1x1 convolutional layer. Defaults to 0.0. - class_num (int): The number of classes for the classification layer. Defaults to 1000. - lr_mult_list (list): Learning rate multiplier for the stages. Defaults to [1.0, 1.0, 1.0, 1.0, 1.0]. - Returns: - model: nn.Layer. Specific PPHGNetV2 model depends on args. - """ - - def __init__( - self, - stage_config, - stem_channels=[3, 32, 64], - use_lab=False, - use_last_conv=True, - class_expand=2048, - dropout_prob=0.0, - class_num=1000, - lr_mult_list=[1.0, 1.0, 1.0, 1.0, 1.0], - det=False, - text_rec=False, - out_indices=None, - **kwargs, - ): - super().__init__() - self.det = det - self.text_rec = text_rec - self.use_lab = use_lab - self.use_last_conv = use_last_conv - self.class_expand = class_expand - self.class_num = class_num - self.out_indices = out_indices if out_indices is not None else [0, 1, 2, 3] - self.out_channels = [] - - # stem - self.stem = StemBlock( - in_channels=stem_channels[0], - mid_channels=stem_channels[1], - out_channels=stem_channels[2], - use_lab=use_lab, - lr_mult=lr_mult_list[0], - text_rec=text_rec, - ) - - # stages - self.stages = nn.ModuleList() - for i, k in enumerate(stage_config): - ( - in_channels, - mid_channels, - out_channels, - block_num, - is_downsample, - light_block, - kernel_size, - layer_num, - stride, - ) = stage_config[k] - self.stages.append( - HGV2_Stage( - in_channels, - mid_channels, - out_channels, - block_num, - layer_num, - is_downsample, - light_block, - kernel_size, - use_lab, - stride, - lr_mult=lr_mult_list[i + 1], - ) - ) - if i in self.out_indices: - self.out_channels.append(out_channels) - if not self.det: - self.out_channels = stage_config["stage4"][2] - - self.avg_pool = AdaptiveAvgPool2D(1) - - if self.use_last_conv: - self.last_conv = nn.Conv2d( - in_channels=out_channels, - out_channels=self.class_expand, - kernel_size=1, - stride=1, - padding=0, - bias=False, - ) - self.act = nn.ReLU() - if self.use_lab: - self.lab = LearnableAffineBlock() - self.dropout = DropoutInferDownscale(p=dropout_prob) - - self.flatten = nn.Flatten(start_dim=1, end_dim=-1) - if not self.det: - self.fc = nn.Linear( - self.class_expand if self.use_last_conv else out_channels, - self.class_num, - ) - - self._init_weights() - - def _init_weights(self): - for m in self.modules(): - if isinstance(m, nn.Conv2d): - nn.init.kaiming_normal_(m.weight) - elif isinstance(m, nn.BatchNorm2d): - nn.init.ones_(m.weight) - nn.init.zeros_(m.bias) - elif isinstance(m, nn.Linear): - nn.init.zeros_(m.bias) - - def forward(self, x): - x = self.stem(x) - out = [] - for i, stage in enumerate(self.stages): - x = stage(x) - if self.det and i in self.out_indices: - out.append(x) - if self.det: - return out - - if self.text_rec: - if self.training: - x = F.adaptive_avg_pool2d(x, [1, 40]) - else: - x = F.avg_pool2d(x, [3, 2]) - return x - - -def PPHGNetV2_B0(pretrained=False, use_ssld=False, **kwargs): - """ - PPHGNetV2_B0 - Args: - pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. - If str, means the path of the pretrained model. - use_ssld (bool) Whether using ssld pretrained model when pretrained is True. - Returns: - model: nn.Layer. Specific `PPHGNetV2_B0` model depends on args. - """ - stage_config = { - # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num - "stage1": [16, 16, 64, 1, False, False, 3, 3], - "stage2": [64, 32, 256, 1, True, False, 3, 3], - "stage3": [256, 64, 512, 2, True, True, 5, 3], - "stage4": [512, 128, 1024, 1, True, True, 5, 3], - } - - model = PPHGNetV2( - stem_channels=[3, 16, 16], stage_config=stage_config, use_lab=True, **kwargs - ) - return model - - -def PPHGNetV2_B1(pretrained=False, use_ssld=False, **kwargs): - """ - PPHGNetV2_B1 - Args: - pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. - If str, means the path of the pretrained model. - use_ssld (bool) Whether using ssld pretrained model when pretrained is True. - Returns: - model: nn.Layer. Specific `PPHGNetV2_B1` model depends on args. - """ - stage_config = { - # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num - "stage1": [32, 32, 64, 1, False, False, 3, 3], - "stage2": [64, 48, 256, 1, True, False, 3, 3], - "stage3": [256, 96, 512, 2, True, True, 5, 3], - "stage4": [512, 192, 1024, 1, True, True, 5, 3], - } - - model = PPHGNetV2( - stem_channels=[3, 24, 32], stage_config=stage_config, use_lab=True, **kwargs - ) - return model - - -def PPHGNetV2_B2(pretrained=False, use_ssld=False, **kwargs): - """ - PPHGNetV2_B2 - Args: - pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. - If str, means the path of the pretrained model. - use_ssld (bool) Whether using ssld pretrained model when pretrained is True. - Returns: - model: nn.Layer. Specific `PPHGNetV2_B2` model depends on args. - """ - stage_config = { - # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num - "stage1": [32, 32, 96, 1, False, False, 3, 4], - "stage2": [96, 64, 384, 1, True, False, 3, 4], - "stage3": [384, 128, 768, 3, True, True, 5, 4], - "stage4": [768, 256, 1536, 1, True, True, 5, 4], - } - - model = PPHGNetV2( - stem_channels=[3, 24, 32], stage_config=stage_config, use_lab=True, **kwargs - ) - return model - - -def PPHGNetV2_B3(pretrained=False, use_ssld=False, **kwargs): - """ - PPHGNetV2_B3 - Args: - pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. - If str, means the path of the pretrained model. - use_ssld (bool) Whether using ssld pretrained model when pretrained is True. - Returns: - model: nn.Layer. Specific `PPHGNetV2_B3` model depends on args. - """ - stage_config = { - # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num - "stage1": [32, 32, 128, 1, False, False, 3, 5], - "stage2": [128, 64, 512, 1, True, False, 3, 5], - "stage3": [512, 128, 1024, 3, True, True, 5, 5], - "stage4": [1024, 256, 2048, 1, True, True, 5, 5], - } - - model = PPHGNetV2( - stem_channels=[3, 24, 32], stage_config=stage_config, use_lab=True, **kwargs - ) - return model - - -def PPHGNetV2_B4(pretrained=False, use_ssld=False, det=False, text_rec=False, **kwargs): - """ - PPHGNetV2_B4 - Args: - pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. - If str, means the path of the pretrained model. - use_ssld (bool) Whether using ssld pretrained model when pretrained is True. - Returns: - model: nn.Layer. Specific `PPHGNetV2_B4` model depends on args. - """ - stage_config_rec = { - # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num, stride - "stage1": [48, 48, 128, 1, True, False, 3, 6, [2, 1]], - "stage2": [128, 96, 512, 1, True, False, 3, 6, [1, 2]], - "stage3": [512, 192, 1024, 3, True, True, 5, 6, [2, 1]], - "stage4": [1024, 384, 2048, 1, True, True, 5, 6, [2, 1]], - } - - stage_config_det = { - # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num - "stage1": [48, 48, 128, 1, False, False, 3, 6, 2], - "stage2": [128, 96, 512, 1, True, False, 3, 6, 2], - "stage3": [512, 192, 1024, 3, True, True, 5, 6, 2], - "stage4": [1024, 384, 2048, 1, True, True, 5, 6, 2], - } - model = PPHGNetV2( - stem_channels=[3, 32, 48], - stage_config=stage_config_det if det else stage_config_rec, - use_lab=False, - det=det, - text_rec=text_rec, - **kwargs, - ) - return model - - -def PPHGNetV2_B5(pretrained=False, use_ssld=False, **kwargs): - """ - PPHGNetV2_B5 - Args: - pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. - If str, means the path of the pretrained model. - use_ssld (bool) Whether using ssld pretrained model when pretrained is True. - Returns: - model: nn.Layer. Specific `PPHGNetV2_B5` model depends on args. - """ - stage_config = { - # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num - "stage1": [64, 64, 128, 1, False, False, 3, 6], - "stage2": [128, 128, 512, 2, True, False, 3, 6], - "stage3": [512, 256, 1024, 5, True, True, 5, 6], - "stage4": [1024, 512, 2048, 2, True, True, 5, 6], - } - - model = PPHGNetV2( - stem_channels=[3, 32, 64], stage_config=stage_config, use_lab=False, **kwargs - ) - return model - - -def PPHGNetV2_B6(pretrained=False, use_ssld=False, **kwargs): - """ - PPHGNetV2_B6 - Args: - pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. - If str, means the path of the pretrained model. - use_ssld (bool) Whether using ssld pretrained model when pretrained is True. - Returns: - model: nn.Layer. Specific `PPHGNetV2_B6` model depends on args. - """ - stage_config = { - # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num - "stage1": [96, 96, 192, 2, False, False, 3, 6], - "stage2": [192, 192, 512, 3, True, False, 3, 6], - "stage3": [512, 384, 1024, 6, True, True, 5, 6], - "stage4": [1024, 768, 2048, 3, True, True, 5, 6], - } - - model = PPHGNetV2( - stem_channels=[3, 48, 96], stage_config=stage_config, use_lab=False, **kwargs - ) - return model diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/__init__.py b/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/__init__.py deleted file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/reading_oreder/__init__.py b/magic_pdf/model/sub_modules/reading_oreder/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/reading_oreder/layoutreader/__init__.py b/magic_pdf/model/sub_modules/reading_oreder/layoutreader/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/table/__init__.py b/magic_pdf/model/sub_modules/table/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/table/rapidtable/__init__.py b/magic_pdf/model/sub_modules/table/rapidtable/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/model/sub_modules/table/table_utils.py b/magic_pdf/model/sub_modules/table/table_utils.py deleted file mode 100644 index f04bf98d5d14c6bd69184eac94a54a88b3ad50e7..0000000000000000000000000000000000000000 --- a/magic_pdf/model/sub_modules/table/table_utils.py +++ /dev/null @@ -1,11 +0,0 @@ -import re - - -def minify_html(html): - # 移除多余的空白字符 - html = re.sub(r'\s+', ' ', html) - # 移除行尾的空白字符 - html = re.sub(r'\s*>\s*', '>', html) - # 移除标签前的空白字符 - html = re.sub(r'\s*<\s*', '<', html) - return html.strip() \ No newline at end of file diff --git a/magic_pdf/operators/__init__.py b/magic_pdf/operators/__init__.py deleted file mode 100644 index 84ae24aefa4153ff32b5cc540da1b730ad927c6a..0000000000000000000000000000000000000000 --- a/magic_pdf/operators/__init__.py +++ /dev/null @@ -1,94 +0,0 @@ -from abc import ABC, abstractmethod -from typing import Callable - -from magic_pdf.data.data_reader_writer import DataWriter -from magic_pdf.data.dataset import Dataset -from magic_pdf.operators.pipes import PipeResult - - -class InferenceResultBase(ABC): - - @abstractmethod - def __init__(self, inference_results: list, dataset: Dataset): - """Initialized method. - - Args: - inference_results (list): the inference result generated by model - dataset (Dataset): the dataset related with model inference result - """ - pass - - @abstractmethod - def draw_model(self, file_path: str) -> None: - """Draw model inference result. - - Args: - file_path (str): the output file path - """ - pass - - @abstractmethod - def dump_model(self, writer: DataWriter, file_path: str): - """Dump model inference result to file. - - Args: - writer (DataWriter): writer handle - file_path (str): the location of target file - """ - pass - - @abstractmethod - def get_infer_res(self): - """Get the inference result. - - Returns: - list: the inference result generated by model - """ - pass - - @abstractmethod - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(inference_result, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - pass - - def pipe_txt_mode( - self, - imageWriter: DataWriter, - start_page_id=0, - end_page_id=None, - debug_mode=False, - lang=None, - ) -> PipeResult: - """Post-proc the model inference result, Extract the text using the - third library, such as `pymupdf` - - Args: - imageWriter (DataWriter): the image writer handle - start_page_id (int, optional): Defaults to 0. Let user select some pages He/She want to process - end_page_id (int, optional): Defaults to the last page index of dataset. Let user select some pages He/She want to process - debug_mode (bool, optional): Defaults to False. will dump more log if enabled - lang (str, optional): Defaults to None. - - Returns: - PipeResult: the result - """ - pass - - @abstractmethod - def pipe_ocr_mode( - self, - imageWriter: DataWriter, - start_page_id=0, - end_page_id=None, - debug_mode=False, - lang=None, - ) -> PipeResult: - pass diff --git a/magic_pdf/operators/models.py b/magic_pdf/operators/models.py deleted file mode 100644 index 34cbfe4bd1c804c4e9ecc3888cc6805948d2f164..0000000000000000000000000000000000000000 --- a/magic_pdf/operators/models.py +++ /dev/null @@ -1,154 +0,0 @@ -import copy -import json -import os -from typing import Callable - -from magic_pdf.config.constants import PARSE_TYPE_OCR, PARSE_TYPE_TXT -from magic_pdf.config.enums import SupportedPdfParseMethod -from magic_pdf.data.data_reader_writer import DataWriter -from magic_pdf.data.dataset import Dataset -from magic_pdf.libs.draw_bbox import draw_model_bbox -from magic_pdf.libs.version import __version__ -from magic_pdf.operators.pipes import PipeResult -from magic_pdf.pdf_parse_union_core_v2 import pdf_parse_union -from magic_pdf.operators import InferenceResultBase - -class InferenceResult(InferenceResultBase): - def __init__(self, inference_results: list, dataset: Dataset): - """Initialized method. - - Args: - inference_results (list): the inference result generated by model - dataset (Dataset): the dataset related with model inference result - """ - self._infer_res = inference_results - self._dataset = dataset - - def draw_model(self, file_path: str) -> None: - """Draw model inference result. - - Args: - file_path (str): the output file path - """ - dir_name = os.path.dirname(file_path) - base_name = os.path.basename(file_path) - if not os.path.exists(dir_name): - os.makedirs(dir_name, exist_ok=True) - draw_model_bbox( - copy.deepcopy(self._infer_res), self._dataset, dir_name, base_name - ) - - def dump_model(self, writer: DataWriter, file_path: str): - """Dump model inference result to file. - - Args: - writer (DataWriter): writer handle - file_path (str): the location of target file - """ - writer.write_string( - file_path, json.dumps(self._infer_res, ensure_ascii=False, indent=4) - ) - - def get_infer_res(self): - """Get the inference result. - - Returns: - list: the inference result generated by model - """ - return self._infer_res - - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(inference_result, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - return proc(copy.deepcopy(self._infer_res), *args, **kwargs) - - def pipe_txt_mode( - self, - imageWriter: DataWriter, - start_page_id=0, - end_page_id=None, - debug_mode=False, - lang=None, - ) -> PipeResult: - """Post-proc the model inference result, Extract the text using the - third library, such as `pymupdf` - - Args: - imageWriter (DataWriter): the image writer handle - start_page_id (int, optional): Defaults to 0. Let user select some pages He/She want to process - end_page_id (int, optional): Defaults to the last page index of dataset. Let user select some pages He/She want to process - debug_mode (bool, optional): Defaults to False. will dump more log if enabled - lang (str, optional): Defaults to None. - - Returns: - PipeResult: the result - """ - - def proc(*args, **kwargs) -> PipeResult: - res = pdf_parse_union(*args, **kwargs) - res['_parse_type'] = PARSE_TYPE_TXT - res['_version_name'] = __version__ - if 'lang' in kwargs and kwargs['lang'] is not None: - res['lang'] = kwargs['lang'] - return PipeResult(res, self._dataset) - - res = self.apply( - proc, - self._dataset, - imageWriter, - SupportedPdfParseMethod.TXT, - start_page_id=start_page_id, - end_page_id=end_page_id, - debug_mode=debug_mode, - lang=lang, - ) - return res - - def pipe_ocr_mode( - self, - imageWriter: DataWriter, - start_page_id=0, - end_page_id=None, - debug_mode=False, - lang=None, - ) -> PipeResult: - """Post-proc the model inference result, Extract the text using `OCR` - technical. - - Args: - imageWriter (DataWriter): the image writer handle - start_page_id (int, optional): Defaults to 0. Let user select some pages He/She want to process - end_page_id (int, optional): Defaults to the last page index of dataset. Let user select some pages He/She want to process - debug_mode (bool, optional): Defaults to False. will dump more log if enabled - lang (str, optional): Defaults to None. - - Returns: - PipeResult: the result - """ - - def proc(*args, **kwargs) -> PipeResult: - res = pdf_parse_union(*args, **kwargs) - res['_parse_type'] = PARSE_TYPE_OCR - res['_version_name'] = __version__ - if 'lang' in kwargs and kwargs['lang'] is not None: - res['lang'] = kwargs['lang'] - return PipeResult(res, self._dataset) - - res = self.apply( - proc, - self._dataset, - imageWriter, - SupportedPdfParseMethod.OCR, - start_page_id=start_page_id, - end_page_id=end_page_id, - debug_mode=debug_mode, - lang=lang, - ) - return res diff --git a/magic_pdf/operators/pipes.py b/magic_pdf/operators/pipes.py deleted file mode 100644 index 8a9f7a563682d5271017550d4753ec3d045e6d43..0000000000000000000000000000000000000000 --- a/magic_pdf/operators/pipes.py +++ /dev/null @@ -1,191 +0,0 @@ -import copy -import json -import os -from typing import Callable - -from magic_pdf.config.make_content_config import DropMode, MakeMode -from magic_pdf.data.data_reader_writer import DataWriter -from magic_pdf.data.dataset import Dataset -from magic_pdf.dict2md.ocr_mkcontent import union_make -from magic_pdf.libs.draw_bbox import (draw_layout_bbox, draw_line_sort_bbox, - draw_span_bbox) -from magic_pdf.libs.json_compressor import JsonCompressor - - -class PipeResult: - def __init__(self, pipe_res, dataset: Dataset): - """Initialized. - - Args: - pipe_res (list[dict]): the pipeline processed result of model inference result - dataset (Dataset): the dataset associated with pipe_res - """ - self._pipe_res = pipe_res - self._dataset = dataset - - def get_markdown( - self, - img_dir_or_bucket_prefix: str, - drop_mode=DropMode.NONE, - md_make_mode=MakeMode.MM_MD, - ) -> str: - """Get markdown content. - - Args: - img_dir_or_bucket_prefix (str): The s3 bucket prefix or local file directory which used to store the figure - drop_mode (str, optional): Drop strategy when some page which is corrupted or inappropriate. Defaults to DropMode.NONE. - md_make_mode (str, optional): The content Type of Markdown be made. Defaults to MakeMode.MM_MD. - - Returns: - str: return markdown content - """ - pdf_info_list = self._pipe_res['pdf_info'] - md_content = union_make( - pdf_info_list, md_make_mode, drop_mode, img_dir_or_bucket_prefix - ) - return md_content - - def dump_md( - self, - writer: DataWriter, - file_path: str, - img_dir_or_bucket_prefix: str, - drop_mode=DropMode.NONE, - md_make_mode=MakeMode.MM_MD, - ): - """Dump The Markdown. - - Args: - writer (DataWriter): File writer handle - file_path (str): The file location of markdown - img_dir_or_bucket_prefix (str): The s3 bucket prefix or local file directory which used to store the figure - drop_mode (str, optional): Drop strategy when some page which is corrupted or inappropriate. Defaults to DropMode.NONE. - md_make_mode (str, optional): The content Type of Markdown be made. Defaults to MakeMode.MM_MD. - """ - - md_content = self.get_markdown( - img_dir_or_bucket_prefix, drop_mode=drop_mode, md_make_mode=md_make_mode - ) - writer.write_string(file_path, md_content) - - def get_content_list( - self, - image_dir_or_bucket_prefix: str, - drop_mode=DropMode.NONE, - ) -> str: - """Get Content List. - - Args: - image_dir_or_bucket_prefix (str): The s3 bucket prefix or local file directory which used to store the figure - drop_mode (str, optional): Drop strategy when some page which is corrupted or inappropriate. Defaults to DropMode.NONE. - - Returns: - str: content list content - """ - pdf_info_list = self._pipe_res['pdf_info'] - content_list = union_make( - pdf_info_list, - MakeMode.STANDARD_FORMAT, - drop_mode, - image_dir_or_bucket_prefix, - ) - return content_list - - def dump_content_list( - self, - writer: DataWriter, - file_path: str, - image_dir_or_bucket_prefix: str, - drop_mode=DropMode.NONE, - ): - """Dump Content List. - - Args: - writer (DataWriter): File writer handle - file_path (str): The file location of content list - image_dir_or_bucket_prefix (str): The s3 bucket prefix or local file directory which used to store the figure - drop_mode (str, optional): Drop strategy when some page which is corrupted or inappropriate. Defaults to DropMode.NONE. - """ - content_list = self.get_content_list( - image_dir_or_bucket_prefix, drop_mode=drop_mode, - ) - writer.write_string( - file_path, json.dumps(content_list, ensure_ascii=False, indent=4) - ) - - def get_middle_json(self) -> str: - """Get middle json. - - Returns: - str: The content of middle json - """ - return json.dumps(self._pipe_res, ensure_ascii=False, indent=4) - - def dump_middle_json(self, writer: DataWriter, file_path: str): - """Dump the result of pipeline. - - Args: - writer (DataWriter): File writer handler - file_path (str): The file location of middle json - """ - middle_json = self.get_middle_json() - writer.write_string(file_path, middle_json) - - def draw_layout(self, file_path: str) -> None: - """Draw the layout. - - Args: - file_path (str): The file location of layout result file - """ - dir_name = os.path.dirname(file_path) - base_name = os.path.basename(file_path) - if not os.path.exists(dir_name): - os.makedirs(dir_name, exist_ok=True) - pdf_info = self._pipe_res['pdf_info'] - draw_layout_bbox(pdf_info, self._dataset.data_bits(), dir_name, base_name) - - def draw_span(self, file_path: str): - """Draw the Span. - - Args: - file_path (str): The file location of span result file - """ - dir_name = os.path.dirname(file_path) - base_name = os.path.basename(file_path) - if not os.path.exists(dir_name): - os.makedirs(dir_name, exist_ok=True) - pdf_info = self._pipe_res['pdf_info'] - draw_span_bbox(pdf_info, self._dataset.data_bits(), dir_name, base_name) - - def draw_line_sort(self, file_path: str): - """Draw line sort. - - Args: - file_path (str): The file location of line sort result file - """ - dir_name = os.path.dirname(file_path) - base_name = os.path.basename(file_path) - if not os.path.exists(dir_name): - os.makedirs(dir_name, exist_ok=True) - pdf_info = self._pipe_res['pdf_info'] - draw_line_sort_bbox(pdf_info, self._dataset.data_bits(), dir_name, base_name) - - def get_compress_pdf_mid_data(self): - """Compress the pipeline result. - - Returns: - str: compress the pipeline result and return - """ - return JsonCompressor.compress_json(self._pipe_res) - - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(pipeline_result, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - return proc(copy.deepcopy(self._pipe_res), *args, **kwargs) diff --git a/magic_pdf/pdf_parse_union_core_v2.py b/magic_pdf/pdf_parse_union_core_v2.py deleted file mode 100644 index 2ca8fa11f8bb54712be1647a048090dc79257a35..0000000000000000000000000000000000000000 --- a/magic_pdf/pdf_parse_union_core_v2.py +++ /dev/null @@ -1,1049 +0,0 @@ -import copy -import math -import os -import re -import statistics -import time -import warnings -from typing import List - -import cv2 -import fitz -import torch -import numpy as np -from loguru import logger -from tqdm import tqdm - -from magic_pdf.config.enums import SupportedPdfParseMethod -from magic_pdf.config.ocr_content_type import BlockType, ContentType -from magic_pdf.data.dataset import Dataset, PageableData -from magic_pdf.libs.boxbase import calculate_overlap_area_in_bbox1_area_ratio, __is_overlaps_y_exceeds_threshold -from magic_pdf.libs.clean_memory import clean_memory -from magic_pdf.libs.config_reader import get_local_layoutreader_model_dir, get_llm_aided_config, get_device -from magic_pdf.libs.convert_utils import dict_to_list -from magic_pdf.libs.hash_utils import compute_md5 -from magic_pdf.libs.pdf_image_tools import cut_image_to_pil_image -from magic_pdf.model.magic_model import MagicModel -from magic_pdf.post_proc.llm_aided import llm_aided_formula, llm_aided_text, llm_aided_title - -from magic_pdf.model.sub_modules.model_init import AtomModelSingleton -from magic_pdf.post_proc.para_split_v3 import para_split -from magic_pdf.pre_proc.construct_page_dict import ocr_construct_page_component_v2 -from magic_pdf.pre_proc.cut_image import ocr_cut_image_and_table -from magic_pdf.pre_proc.ocr_detect_all_bboxes import ocr_prepare_bboxes_for_layout_split_v2 -from magic_pdf.pre_proc.ocr_dict_merge import fill_spans_in_blocks, fix_block_spans_v2, fix_discarded_block -from magic_pdf.pre_proc.ocr_span_list_modify import get_qa_need_list_v2, remove_overlaps_low_confidence_spans, \ - remove_overlaps_min_spans, remove_x_overlapping_chars - -os.environ['NO_ALBUMENTATIONS_UPDATE'] = '1' # 禁止albumentations检查更新 - - -def __replace_STX_ETX(text_str: str): - """Replace \u0002 and \u0003, as these characters become garbled when extracted using pymupdf. In fact, they were originally quotation marks. - Drawback: This issue is only observed in English text; it has not been found in Chinese text so far. - - Args: - text_str (str): raw text - - Returns: - _type_: replaced text - """ # noqa: E501 - if text_str: - s = text_str.replace('\u0002', "'") - s = s.replace('\u0003', "'") - return s - return text_str - - -# 连写字符拆分 -def __replace_ligatures(text: str): - ligatures = { - 'fi': 'fi', 'fl': 'fl', 'ff': 'ff', 'ffi': 'ffi', 'ffl': 'ffl', 'ſt': 'ft', 'st': 'st' - } - return re.sub('|'.join(map(re.escape, ligatures.keys())), lambda m: ligatures[m.group()], text) - - -def chars_to_content(span): - # 检查span中的char是否为空 - if len(span['chars']) == 0: - pass - else: - # 先给chars按char['bbox']的中心点的x坐标排序 - span['chars'] = sorted(span['chars'], key=lambda x: (x['bbox'][0] + x['bbox'][2]) / 2) - - # Calculate the width of each character - char_widths = [char['bbox'][2] - char['bbox'][0] for char in span['chars']] - # Calculate the median width - median_width = statistics.median(char_widths) - - # 通过x轴重叠比率移除一部分char - span = remove_x_overlapping_chars(span, median_width) - - content = '' - for char in span['chars']: - - # 如果下一个char的x0和上一个char的x1距离超过0.25个字符宽度,则需要在中间插入一个空格 - char1 = char - char2 = span['chars'][span['chars'].index(char) + 1] if span['chars'].index(char) + 1 < len(span['chars']) else None - if char2 and char2['bbox'][0] - char1['bbox'][2] > median_width * 0.25 and char['c'] != ' ' and char2['c'] != ' ': - content += f"{char['c']} " - else: - content += char['c'] - - span['content'] = __replace_ligatures(content) - - del span['chars'] - - -LINE_STOP_FLAG = ('.', '!', '?', '。', '!', '?', ')', ')', '"', '”', ':', ':', ';', ';', ']', '】', '}', '}', '>', '》', '、', ',', ',', '-', '—', '–',) -LINE_START_FLAG = ('(', '(', '"', '“', '【', '{', '《', '<', '「', '『', '【', '[',) - - -def fill_char_in_spans(spans, all_chars): - - # 简单从上到下排一下序 - spans = sorted(spans, key=lambda x: x['bbox'][1]) - - for char in all_chars: - - for span in spans: - if calculate_char_in_span(char['bbox'], span['bbox'], char['c']): - span['chars'].append(char) - break - - need_ocr_spans = [] - for span in spans: - chars_to_content(span) - # 有的span中虽然没有字但有一两个空的占位符,用宽高和content长度过滤 - if len(span['content']) * span['height'] < span['width'] * 0.5: - # logger.info(f"maybe empty span: {len(span['content'])}, {span['height']}, {span['width']}") - need_ocr_spans.append(span) - del span['height'], span['width'] - return need_ocr_spans - - -# 使用鲁棒性更强的中心点坐标判断 -def calculate_char_in_span(char_bbox, span_bbox, char, span_height_radio=0.33): - char_center_x = (char_bbox[0] + char_bbox[2]) / 2 - char_center_y = (char_bbox[1] + char_bbox[3]) / 2 - span_center_y = (span_bbox[1] + span_bbox[3]) / 2 - span_height = span_bbox[3] - span_bbox[1] - - if ( - span_bbox[0] < char_center_x < span_bbox[2] - and span_bbox[1] < char_center_y < span_bbox[3] - and abs(char_center_y - span_center_y) < span_height * span_height_radio # 字符的中轴和span的中轴高度差不能超过1/4span高度 - ): - return True - else: - # 如果char是LINE_STOP_FLAG,就不用中心点判定,换一种方案(左边界在span区域内,高度判定和之前逻辑一致) - # 主要是给结尾符号一个进入span的机会,这个char还应该离span右边界较近 - if char in LINE_STOP_FLAG: - if ( - (span_bbox[2] - span_height) < char_bbox[0] < span_bbox[2] - and char_center_x > span_bbox[0] - and span_bbox[1] < char_center_y < span_bbox[3] - and abs(char_center_y - span_center_y) < span_height * span_height_radio - ): - return True - elif char in LINE_START_FLAG: - if ( - span_bbox[0] < char_bbox[2] < (span_bbox[0] + span_height) - and char_center_x < span_bbox[2] - and span_bbox[1] < char_center_y < span_bbox[3] - and abs(char_center_y - span_center_y) < span_height * span_height_radio - ): - return True - else: - return False - - -def remove_tilted_line(text_blocks): - for block in text_blocks: - remove_lines = [] - for line in block['lines']: - cosine, sine = line['dir'] - # 计算弧度值 - angle_radians = math.atan2(sine, cosine) - # 将弧度值转换为角度值 - angle_degrees = math.degrees(angle_radians) - if 2 < abs(angle_degrees) < 88: - remove_lines.append(line) - for line in remove_lines: - block['lines'].remove(line) - - -def calculate_contrast(img, img_mode) -> float: - """ - 计算给定图像的对比度。 - :param img: 图像,类型为numpy.ndarray - :Param img_mode = 图像的色彩通道,'rgb' 或 'bgr' - :return: 图像的对比度值 - """ - if img_mode == 'rgb': - # 将RGB图像转换为灰度图 - gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) - elif img_mode == 'bgr': - # 将BGR图像转换为灰度图 - gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - else: - raise ValueError("Invalid image mode. Please provide 'rgb' or 'bgr'.") - - # 计算均值和标准差 - mean_value = np.mean(gray_img) - std_dev = np.std(gray_img) - # 对比度定义为标准差除以平均值(加上小常数避免除零错误) - contrast = std_dev / (mean_value + 1e-6) - # logger.debug(f"contrast: {contrast}") - return round(contrast, 2) - -# @measure_time -def txt_spans_extract_v2(pdf_page, spans, all_bboxes, all_discarded_blocks, lang): - # cid用0xfffd表示,连字符拆开 - # text_blocks_raw = pdf_page.get_text('rawdict', flags=fitz.TEXT_PRESERVE_WHITESPACE | fitz.TEXT_MEDIABOX_CLIP)['blocks'] - - # cid用0xfffd表示,连字符不拆开 - #text_blocks_raw = pdf_page.get_text('rawdict', flags=fitz.TEXT_PRESERVE_LIGATURES | fitz.TEXT_PRESERVE_WHITESPACE | fitz.TEXT_MEDIABOX_CLIP)['blocks'] - - # 自定义flags出现较多0xfffd,可能是pymupdf可以自行处理内置字典的pdf,不再使用 - text_blocks_raw = pdf_page.get_text('rawdict', flags=fitz.TEXTFLAGS_TEXT)['blocks'] - # text_blocks = pdf_page.get_text('dict', flags=fitz.TEXTFLAGS_TEXT)['blocks'] - - # 移除所有角度不为0或90的line - remove_tilted_line(text_blocks_raw) - - all_pymu_chars = [] - for block in text_blocks_raw: - for line in block['lines']: - cosine, sine = line['dir'] - if abs(cosine) < 0.9 or abs(sine) > 0.1: - continue - for span in line['spans']: - all_pymu_chars.extend(span['chars']) - - # 计算所有sapn的高度的中位数 - span_height_list = [] - for span in spans: - if span['type'] in [ContentType.InterlineEquation, ContentType.Image, ContentType.Table]: - continue - span_height = span['bbox'][3] - span['bbox'][1] - span['height'] = span_height - span['width'] = span['bbox'][2] - span['bbox'][0] - span_height_list.append(span_height) - if len(span_height_list) == 0: - return spans - else: - median_span_height = statistics.median(span_height_list) - - useful_spans = [] - unuseful_spans = [] - # 纵向span的两个特征:1. 高度超过多个line 2. 高宽比超过某个值 - vertical_spans = [] - for span in spans: - if span['type'] in [ContentType.InterlineEquation, ContentType.Image, ContentType.Table]: - continue - for block in all_bboxes + all_discarded_blocks: - if block[7] in [BlockType.ImageBody, BlockType.TableBody, BlockType.InterlineEquation]: - continue - if calculate_overlap_area_in_bbox1_area_ratio(span['bbox'], block[0:4]) > 0.5: - if span['height'] > median_span_height * 3 and span['height'] > span['width'] * 3: - vertical_spans.append(span) - elif block in all_bboxes: - useful_spans.append(span) - else: - unuseful_spans.append(span) - - break - - """垂直的span框直接用pymu的line进行填充""" - if len(vertical_spans) > 0: - text_blocks = pdf_page.get_text('dict', flags=fitz.TEXTFLAGS_TEXT)['blocks'] - all_pymu_lines = [] - for block in text_blocks: - for line in block['lines']: - all_pymu_lines.append(line) - - for pymu_line in all_pymu_lines: - for span in vertical_spans: - if calculate_overlap_area_in_bbox1_area_ratio(pymu_line['bbox'], span['bbox']) > 0.5: - for pymu_span in pymu_line['spans']: - span['content'] += pymu_span['text'] - break - - for span in vertical_spans: - if len(span['content']) == 0: - spans.remove(span) - - """水平的span框如果没有char则用ocr进行填充""" - new_spans = [] - - for span in useful_spans + unuseful_spans: - if span['type'] in [ContentType.Text]: - span['chars'] = [] - new_spans.append(span) - - need_ocr_spans = fill_char_in_spans(new_spans, all_pymu_chars) - - if len(need_ocr_spans) > 0: - - # 初始化ocr模型 - # atom_model_manager = AtomModelSingleton() - # ocr_model = atom_model_manager.get_atom_model( - # atom_model_name='ocr', - # ocr_show_log=False, - # det_db_box_thresh=0.3, - # lang=lang - # ) - - for span in need_ocr_spans: - # 对span的bbox截图再ocr - span_img = cut_image_to_pil_image(span['bbox'], pdf_page, mode='cv2') - - # 计算span的对比度,低于0.20的span不进行ocr - if calculate_contrast(span_img, img_mode='bgr') <= 0.17: - spans.remove(span) - continue - # pass - - span['content'] = '' - span['score'] = 1 - span['np_img'] = span_img - - - # ocr_res = ocr_model.ocr(span_img, det=False) - # if ocr_res and len(ocr_res) > 0: - # if len(ocr_res[0]) > 0: - # ocr_text, ocr_score = ocr_res[0][0] - # # logger.info(f"ocr_text: {ocr_text}, ocr_score: {ocr_score}") - # if ocr_score > 0.5 and len(ocr_text) > 0: - # span['content'] = ocr_text - # span['score'] = float(round(ocr_score, 2)) - # else: - # spans.remove(span) - - return spans - - -def model_init(model_name: str): - from transformers import LayoutLMv3ForTokenClassification - device_name = get_device() - bf_16_support = False - if device_name.startswith("cuda"): - bf_16_support = torch.cuda.is_bf16_supported() - elif device_name.startswith("mps"): - bf_16_support = True - - device = torch.device(device_name) - if model_name == 'layoutreader': - # 检测modelscope的缓存目录是否存在 - layoutreader_model_dir = get_local_layoutreader_model_dir() - if os.path.exists(layoutreader_model_dir): - model = LayoutLMv3ForTokenClassification.from_pretrained( - layoutreader_model_dir - ) - else: - logger.warning( - 'local layoutreader model not exists, use online model from huggingface' - ) - model = LayoutLMv3ForTokenClassification.from_pretrained( - 'hantian/layoutreader' - ) - if bf_16_support: - model.to(device).eval().bfloat16() - else: - model.to(device).eval() - else: - logger.error('model name not allow') - exit(1) - return model - - -class ModelSingleton: - _instance = None - _models = {} - - def __new__(cls, *args, **kwargs): - if cls._instance is None: - cls._instance = super().__new__(cls) - return cls._instance - - def get_model(self, model_name: str): - if model_name not in self._models: - self._models[model_name] = model_init(model_name=model_name) - return self._models[model_name] - - -def do_predict(boxes: List[List[int]], model) -> List[int]: - from magic_pdf.model.sub_modules.reading_oreder.layoutreader.helpers import ( - boxes2inputs, parse_logits, prepare_inputs) - - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=FutureWarning, module="transformers") - - inputs = boxes2inputs(boxes) - inputs = prepare_inputs(inputs, model) - logits = model(**inputs).logits.cpu().squeeze(0) - return parse_logits(logits, len(boxes)) - - -def cal_block_index(fix_blocks, sorted_bboxes): - - if sorted_bboxes is not None: - # 使用layoutreader排序 - for block in fix_blocks: - line_index_list = [] - if len(block['lines']) == 0: - block['index'] = sorted_bboxes.index(block['bbox']) - else: - for line in block['lines']: - line['index'] = sorted_bboxes.index(line['bbox']) - line_index_list.append(line['index']) - median_value = statistics.median(line_index_list) - block['index'] = median_value - - # 删除图表body block中的虚拟line信息, 并用real_lines信息回填 - if block['type'] in [BlockType.ImageBody, BlockType.TableBody, BlockType.Title, BlockType.InterlineEquation]: - if 'real_lines' in block: - block['virtual_lines'] = copy.deepcopy(block['lines']) - block['lines'] = copy.deepcopy(block['real_lines']) - del block['real_lines'] - else: - # 使用xycut排序 - block_bboxes = [] - for block in fix_blocks: - # 如果block['bbox']任意值小于0,将其置为0 - block['bbox'] = [max(0, x) for x in block['bbox']] - block_bboxes.append(block['bbox']) - - # 删除图表body block中的虚拟line信息, 并用real_lines信息回填 - if block['type'] in [BlockType.ImageBody, BlockType.TableBody, BlockType.Title, BlockType.InterlineEquation]: - if 'real_lines' in block: - block['virtual_lines'] = copy.deepcopy(block['lines']) - block['lines'] = copy.deepcopy(block['real_lines']) - del block['real_lines'] - - import numpy as np - - from magic_pdf.model.sub_modules.reading_oreder.layoutreader.xycut import \ - recursive_xy_cut - - random_boxes = np.array(block_bboxes) - np.random.shuffle(random_boxes) - res = [] - recursive_xy_cut(np.asarray(random_boxes).astype(int), np.arange(len(block_bboxes)), res) - assert len(res) == len(block_bboxes) - sorted_boxes = random_boxes[np.array(res)].tolist() - - for i, block in enumerate(fix_blocks): - block['index'] = sorted_boxes.index(block['bbox']) - - # 生成line index - sorted_blocks = sorted(fix_blocks, key=lambda b: b['index']) - line_inedx = 1 - for block in sorted_blocks: - for line in block['lines']: - line['index'] = line_inedx - line_inedx += 1 - - return fix_blocks - - -def insert_lines_into_block(block_bbox, line_height, page_w, page_h): - # block_bbox是一个元组(x0, y0, x1, y1),其中(x0, y0)是左下角坐标,(x1, y1)是右上角坐标 - x0, y0, x1, y1 = block_bbox - - block_height = y1 - y0 - block_weight = x1 - x0 - - # 如果block高度小于n行正文,则直接返回block的bbox - if line_height * 2 < block_height: - if ( - block_height > page_h * 0.25 and page_w * 0.5 > block_weight > page_w * 0.25 - ): # 可能是双列结构,可以切细点 - lines = int(block_height / line_height) - else: - # 如果block的宽度超过0.4页面宽度,则将block分成3行(是一种复杂布局,图不能切的太细) - if block_weight > page_w * 0.4: - lines = 3 - elif block_weight > page_w * 0.25: # (可能是三列结构,也切细点) - lines = int(block_height / line_height) - else: # 判断长宽比 - if block_height / block_weight > 1.2: # 细长的不分 - return [[x0, y0, x1, y1]] - else: # 不细长的还是分成两行 - lines = 2 - - line_height = (y1 - y0) / lines - - # 确定从哪个y位置开始绘制线条 - current_y = y0 - - # 用于存储线条的位置信息[(x0, y), ...] - lines_positions = [] - - for i in range(lines): - lines_positions.append([x0, current_y, x1, current_y + line_height]) - current_y += line_height - return lines_positions - - else: - return [[x0, y0, x1, y1]] - - -def sort_lines_by_model(fix_blocks, page_w, page_h, line_height, footnote_blocks): - page_line_list = [] - - def add_lines_to_block(b): - line_bboxes = insert_lines_into_block(b['bbox'], line_height, page_w, page_h) - b['lines'] = [] - for line_bbox in line_bboxes: - b['lines'].append({'bbox': line_bbox, 'spans': []}) - page_line_list.extend(line_bboxes) - - for block in fix_blocks: - if block['type'] in [ - BlockType.Text, BlockType.Title, - BlockType.ImageCaption, BlockType.ImageFootnote, - BlockType.TableCaption, BlockType.TableFootnote - ]: - if len(block['lines']) == 0: - add_lines_to_block(block) - elif block['type'] in [BlockType.Title] and len(block['lines']) == 1 and (block['bbox'][3] - block['bbox'][1]) > line_height * 2: - block['real_lines'] = copy.deepcopy(block['lines']) - add_lines_to_block(block) - else: - for line in block['lines']: - bbox = line['bbox'] - page_line_list.append(bbox) - elif block['type'] in [BlockType.ImageBody, BlockType.TableBody, BlockType.InterlineEquation]: - block['real_lines'] = copy.deepcopy(block['lines']) - add_lines_to_block(block) - - for block in footnote_blocks: - footnote_block = {'bbox': block[:4]} - add_lines_to_block(footnote_block) - - if len(page_line_list) > 200: # layoutreader最高支持512line - return None - - # 使用layoutreader排序 - x_scale = 1000.0 / page_w - y_scale = 1000.0 / page_h - boxes = [] - # logger.info(f"Scale: {x_scale}, {y_scale}, Boxes len: {len(page_line_list)}") - for left, top, right, bottom in page_line_list: - if left < 0: - logger.warning( - f'left < 0, left: {left}, right: {right}, top: {top}, bottom: {bottom}, page_w: {page_w}, page_h: {page_h}' - ) # noqa: E501 - left = 0 - if right > page_w: - logger.warning( - f'right > page_w, left: {left}, right: {right}, top: {top}, bottom: {bottom}, page_w: {page_w}, page_h: {page_h}' - ) # noqa: E501 - right = page_w - if top < 0: - logger.warning( - f'top < 0, left: {left}, right: {right}, top: {top}, bottom: {bottom}, page_w: {page_w}, page_h: {page_h}' - ) # noqa: E501 - top = 0 - if bottom > page_h: - logger.warning( - f'bottom > page_h, left: {left}, right: {right}, top: {top}, bottom: {bottom}, page_w: {page_w}, page_h: {page_h}' - ) # noqa: E501 - bottom = page_h - - left = round(left * x_scale) - top = round(top * y_scale) - right = round(right * x_scale) - bottom = round(bottom * y_scale) - assert ( - 1000 >= right >= left >= 0 and 1000 >= bottom >= top >= 0 - ), f'Invalid box. right: {right}, left: {left}, bottom: {bottom}, top: {top}' # noqa: E126, E121 - boxes.append([left, top, right, bottom]) - model_manager = ModelSingleton() - model = model_manager.get_model('layoutreader') - with torch.no_grad(): - orders = do_predict(boxes, model) - sorted_bboxes = [page_line_list[i] for i in orders] - - return sorted_bboxes - - -def get_line_height(blocks): - page_line_height_list = [] - for block in blocks: - if block['type'] in [ - BlockType.Text, BlockType.Title, - BlockType.ImageCaption, BlockType.ImageFootnote, - BlockType.TableCaption, BlockType.TableFootnote - ]: - for line in block['lines']: - bbox = line['bbox'] - page_line_height_list.append(int(bbox[3] - bbox[1])) - if len(page_line_height_list) > 0: - return statistics.median(page_line_height_list) - else: - return 10 - - -def process_groups(groups, body_key, caption_key, footnote_key): - body_blocks = [] - caption_blocks = [] - footnote_blocks = [] - for i, group in enumerate(groups): - group[body_key]['group_id'] = i - body_blocks.append(group[body_key]) - for caption_block in group[caption_key]: - caption_block['group_id'] = i - caption_blocks.append(caption_block) - for footnote_block in group[footnote_key]: - footnote_block['group_id'] = i - footnote_blocks.append(footnote_block) - return body_blocks, caption_blocks, footnote_blocks - - -def process_block_list(blocks, body_type, block_type): - indices = [block['index'] for block in blocks] - median_index = statistics.median(indices) - - body_bbox = next((block['bbox'] for block in blocks if block.get('type') == body_type), []) - - return { - 'type': block_type, - 'bbox': body_bbox, - 'blocks': blocks, - 'index': median_index, - } - - -def revert_group_blocks(blocks): - image_groups = {} - table_groups = {} - new_blocks = [] - for block in blocks: - if block['type'] in [BlockType.ImageBody, BlockType.ImageCaption, BlockType.ImageFootnote]: - group_id = block['group_id'] - if group_id not in image_groups: - image_groups[group_id] = [] - image_groups[group_id].append(block) - elif block['type'] in [BlockType.TableBody, BlockType.TableCaption, BlockType.TableFootnote]: - group_id = block['group_id'] - if group_id not in table_groups: - table_groups[group_id] = [] - table_groups[group_id].append(block) - else: - new_blocks.append(block) - - for group_id, blocks in image_groups.items(): - new_blocks.append(process_block_list(blocks, BlockType.ImageBody, BlockType.Image)) - - for group_id, blocks in table_groups.items(): - new_blocks.append(process_block_list(blocks, BlockType.TableBody, BlockType.Table)) - - return new_blocks - - -def remove_outside_spans(spans, all_bboxes, all_discarded_blocks): - def get_block_bboxes(blocks, block_type_list): - return [block[0:4] for block in blocks if block[7] in block_type_list] - - image_bboxes = get_block_bboxes(all_bboxes, [BlockType.ImageBody]) - table_bboxes = get_block_bboxes(all_bboxes, [BlockType.TableBody]) - other_block_type = [] - for block_type in BlockType.__dict__.values(): - if not isinstance(block_type, str): - continue - if block_type not in [BlockType.ImageBody, BlockType.TableBody]: - other_block_type.append(block_type) - other_block_bboxes = get_block_bboxes(all_bboxes, other_block_type) - discarded_block_bboxes = get_block_bboxes(all_discarded_blocks, [BlockType.Discarded]) - - new_spans = [] - - for span in spans: - span_bbox = span['bbox'] - span_type = span['type'] - - if any(calculate_overlap_area_in_bbox1_area_ratio(span_bbox, block_bbox) > 0.4 for block_bbox in - discarded_block_bboxes): - new_spans.append(span) - continue - - if span_type == ContentType.Image: - if any(calculate_overlap_area_in_bbox1_area_ratio(span_bbox, block_bbox) > 0.5 for block_bbox in - image_bboxes): - new_spans.append(span) - elif span_type == ContentType.Table: - if any(calculate_overlap_area_in_bbox1_area_ratio(span_bbox, block_bbox) > 0.5 for block_bbox in - table_bboxes): - new_spans.append(span) - else: - if any(calculate_overlap_area_in_bbox1_area_ratio(span_bbox, block_bbox) > 0.5 for block_bbox in - other_block_bboxes): - new_spans.append(span) - - return new_spans - - -def parse_page_core( - page_doc: PageableData, magic_model, page_id, pdf_bytes_md5, imageWriter, parse_mode, lang -): - need_drop = False - drop_reason = [] - - """从magic_model对象中获取后面会用到的区块信息""" - img_groups = magic_model.get_imgs_v2(page_id) - table_groups = magic_model.get_tables_v2(page_id) - - """对image和table的区块分组""" - img_body_blocks, img_caption_blocks, img_footnote_blocks = process_groups( - img_groups, 'image_body', 'image_caption_list', 'image_footnote_list' - ) - - table_body_blocks, table_caption_blocks, table_footnote_blocks = process_groups( - table_groups, 'table_body', 'table_caption_list', 'table_footnote_list' - ) - - discarded_blocks = magic_model.get_discarded(page_id) - text_blocks = magic_model.get_text_blocks(page_id) - title_blocks = magic_model.get_title_blocks(page_id) - inline_equations, interline_equations, interline_equation_blocks = magic_model.get_equations(page_id) - page_w, page_h = magic_model.get_page_size(page_id) - - def merge_title_blocks(blocks, x_distance_threshold=0.1*page_w): - def merge_two_bbox(b1, b2): - x_min = min(b1['bbox'][0], b2['bbox'][0]) - y_min = min(b1['bbox'][1], b2['bbox'][1]) - x_max = max(b1['bbox'][2], b2['bbox'][2]) - y_max = max(b1['bbox'][3], b2['bbox'][3]) - return x_min, y_min, x_max, y_max - - def merge_two_blocks(b1, b2): - # 合并两个标题块的边界框 - b1['bbox'] = merge_two_bbox(b1, b2) - - # 合并两个标题块的文本内容 - line1 = b1['lines'][0] - line2 = b2['lines'][0] - line1['bbox'] = merge_two_bbox(line1, line2) - line1['spans'].extend(line2['spans']) - - return b1, b2 - - # 按 y 轴重叠度聚集标题块 - y_overlapping_blocks = [] - title_bs = [b for b in blocks if b['type'] == BlockType.Title] - while title_bs: - block1 = title_bs.pop(0) - current_row = [block1] - to_remove = [] - for block2 in title_bs: - if ( - __is_overlaps_y_exceeds_threshold(block1['bbox'], block2['bbox'], 0.9) - and len(block1['lines']) == 1 - and len(block2['lines']) == 1 - ): - current_row.append(block2) - to_remove.append(block2) - for b in to_remove: - title_bs.remove(b) - y_overlapping_blocks.append(current_row) - - # 按x轴坐标排序并合并标题块 - to_remove_blocks = [] - for row in y_overlapping_blocks: - if len(row) == 1: - continue - - # 按x轴坐标排序 - row.sort(key=lambda x: x['bbox'][0]) - - merged_block = row[0] - for i in range(1, len(row)): - left_block = merged_block - right_block = row[i] - - left_height = left_block['bbox'][3] - left_block['bbox'][1] - right_height = right_block['bbox'][3] - right_block['bbox'][1] - - if ( - right_block['bbox'][0] - left_block['bbox'][2] < x_distance_threshold - and left_height * 0.95 < right_height < left_height * 1.05 - ): - merged_block, to_remove_block = merge_two_blocks(merged_block, right_block) - to_remove_blocks.append(to_remove_block) - else: - merged_block = right_block - - for b in to_remove_blocks: - blocks.remove(b) - - """将所有区块的bbox整理到一起""" - # interline_equation_blocks参数不够准,后面切换到interline_equations上 - interline_equation_blocks = [] - if len(interline_equation_blocks) > 0: - all_bboxes, all_discarded_blocks, footnote_blocks = ocr_prepare_bboxes_for_layout_split_v2( - img_body_blocks, img_caption_blocks, img_footnote_blocks, - table_body_blocks, table_caption_blocks, table_footnote_blocks, - discarded_blocks, - text_blocks, - title_blocks, - interline_equation_blocks, - page_w, - page_h, - ) - else: - all_bboxes, all_discarded_blocks, footnote_blocks = ocr_prepare_bboxes_for_layout_split_v2( - img_body_blocks, img_caption_blocks, img_footnote_blocks, - table_body_blocks, table_caption_blocks, table_footnote_blocks, - discarded_blocks, - text_blocks, - title_blocks, - interline_equations, - page_w, - page_h, - ) - - """获取所有的spans信息""" - spans = magic_model.get_all_spans(page_id) - - """在删除重复span之前,应该通过image_body和table_body的block过滤一下image和table的span""" - """顺便删除大水印并保留abandon的span""" - spans = remove_outside_spans(spans, all_bboxes, all_discarded_blocks) - - """删除重叠spans中置信度较低的那些""" - spans, dropped_spans_by_confidence = remove_overlaps_low_confidence_spans(spans) - """删除重叠spans中较小的那些""" - spans, dropped_spans_by_span_overlap = remove_overlaps_min_spans(spans) - - """根据parse_mode,构造spans,主要是文本类的字符填充""" - if parse_mode == SupportedPdfParseMethod.TXT: - - """使用新版本的混合ocr方案.""" - spans = txt_spans_extract_v2(page_doc, spans, all_bboxes, all_discarded_blocks, lang) - - elif parse_mode == SupportedPdfParseMethod.OCR: - pass - else: - raise Exception('parse_mode must be txt or ocr') - - """先处理不需要排版的discarded_blocks""" - discarded_block_with_spans, spans = fill_spans_in_blocks( - all_discarded_blocks, spans, 0.4 - ) - fix_discarded_blocks = fix_discarded_block(discarded_block_with_spans) - - """如果当前页面没有有效的bbox则跳过""" - if len(all_bboxes) == 0: - logger.warning(f'skip this page, not found useful bbox, page_id: {page_id}') - return ocr_construct_page_component_v2( - [], - [], - page_id, - page_w, - page_h, - [], - [], - [], - interline_equations, - fix_discarded_blocks, - need_drop, - drop_reason, - ) - - """对image和table截图""" - spans = ocr_cut_image_and_table( - spans, page_doc, page_id, pdf_bytes_md5, imageWriter - ) - - """span填充进block""" - block_with_spans, spans = fill_spans_in_blocks(all_bboxes, spans, 0.5) - - """对block进行fix操作""" - fix_blocks = fix_block_spans_v2(block_with_spans) - - """同一行被断开的titile合并""" - merge_title_blocks(fix_blocks) - - """获取所有line并计算正文line的高度""" - line_height = get_line_height(fix_blocks) - - """获取所有line并对line排序""" - sorted_bboxes = sort_lines_by_model(fix_blocks, page_w, page_h, line_height, footnote_blocks) - - """根据line的中位数算block的序列关系""" - fix_blocks = cal_block_index(fix_blocks, sorted_bboxes) - - """将image和table的block还原回group形式参与后续流程""" - fix_blocks = revert_group_blocks(fix_blocks) - - """重排block""" - sorted_blocks = sorted(fix_blocks, key=lambda b: b['index']) - - """block内重排(img和table的block内多个caption或footnote的排序)""" - for block in sorted_blocks: - if block['type'] in [BlockType.Image, BlockType.Table]: - block['blocks'] = sorted(block['blocks'], key=lambda b: b['index']) - - """获取QA需要外置的list""" - images, tables, interline_equations = get_qa_need_list_v2(sorted_blocks) - - """构造pdf_info_dict""" - page_info = ocr_construct_page_component_v2( - sorted_blocks, - [], - page_id, - page_w, - page_h, - [], - images, - tables, - interline_equations, - fix_discarded_blocks, - need_drop, - drop_reason, - ) - return page_info - - -def pdf_parse_union( - model_list, - dataset: Dataset, - imageWriter, - parse_mode, - start_page_id=0, - end_page_id=None, - debug_mode=False, - lang=None, -): - - pdf_bytes_md5 = compute_md5(dataset.data_bits()) - - """初始化空的pdf_info_dict""" - pdf_info_dict = {} - - """用model_list和docs对象初始化magic_model""" - magic_model = MagicModel(model_list, dataset) - - """根据输入的起始范围解析pdf""" - end_page_id = ( - end_page_id - if end_page_id is not None and end_page_id >= 0 - else len(dataset) - 1 - ) - - if end_page_id > len(dataset) - 1: - logger.warning('end_page_id is out of range, use pdf_docs length') - end_page_id = len(dataset) - 1 - - # """初始化启动时间""" - # start_time = time.time() - - # for page_id, page in enumerate(dataset): - for page_id, page in tqdm(enumerate(dataset), total=len(dataset), desc="Processing pages"): - # """debug时输出每页解析的耗时.""" - # if debug_mode: - # time_now = time.time() - # logger.info( - # f'page_id: {page_id}, last_page_cost_time: {round(time.time() - start_time, 2)}' - # ) - # start_time = time_now - - """解析pdf中的每一页""" - if start_page_id <= page_id <= end_page_id: - page_info = parse_page_core( - page, magic_model, page_id, pdf_bytes_md5, imageWriter, parse_mode, lang - ) - else: - page_info = page.get_page_info() - page_w = page_info.w - page_h = page_info.h - page_info = ocr_construct_page_component_v2( - [], [], page_id, page_w, page_h, [], [], [], [], [], True, 'skip page' - ) - pdf_info_dict[f'page_{page_id}'] = page_info - - need_ocr_list = [] - img_crop_list = [] - text_block_list = [] - for pange_id, page_info in pdf_info_dict.items(): - for block in page_info['preproc_blocks']: - if block['type'] in ['table', 'image']: - for sub_block in block['blocks']: - if sub_block['type'] in ['image_caption', 'image_footnote', 'table_caption', 'table_footnote']: - text_block_list.append(sub_block) - elif block['type'] in ['text', 'title']: - text_block_list.append(block) - for block in page_info['discarded_blocks']: - text_block_list.append(block) - for block in text_block_list: - for line in block['lines']: - for span in line['spans']: - if 'np_img' in span: - need_ocr_list.append(span) - img_crop_list.append(span['np_img']) - span.pop('np_img') - if len(img_crop_list) > 0: - # Get OCR results for this language's images - atom_model_manager = AtomModelSingleton() - ocr_model = atom_model_manager.get_atom_model( - atom_model_name='ocr', - ocr_show_log=False, - det_db_box_thresh=0.3, - lang=lang - ) - # rec_start = time.time() - ocr_res_list = ocr_model.ocr(img_crop_list, det=False, tqdm_enable=True)[0] - # Verify we have matching counts - assert len(ocr_res_list) == len(need_ocr_list), f'ocr_res_list: {len(ocr_res_list)}, need_ocr_list: {len(need_ocr_list)}' - # Process OCR results for this language - for index, span in enumerate(need_ocr_list): - ocr_text, ocr_score = ocr_res_list[index] - span['content'] = ocr_text - span['score'] = float(f"{ocr_score:.3f}") - # rec_time = time.time() - rec_start - # logger.info(f'ocr-dynamic-rec time: {round(rec_time, 2)}, total images processed: {len(img_crop_list)}') - - - """分段""" - para_split(pdf_info_dict) - - """llm优化""" - llm_aided_config = get_llm_aided_config() - if llm_aided_config is not None: - """公式优化""" - formula_aided_config = llm_aided_config.get('formula_aided', None) - if formula_aided_config is not None: - if formula_aided_config.get('enable', False): - llm_aided_formula_start_time = time.time() - llm_aided_formula(pdf_info_dict, formula_aided_config) - logger.info(f'llm aided formula time: {round(time.time() - llm_aided_formula_start_time, 2)}') - """文本优化""" - text_aided_config = llm_aided_config.get('text_aided', None) - if text_aided_config is not None: - if text_aided_config.get('enable', False): - llm_aided_text_start_time = time.time() - llm_aided_text(pdf_info_dict, text_aided_config) - logger.info(f'llm aided text time: {round(time.time() - llm_aided_text_start_time, 2)}') - """标题优化""" - title_aided_config = llm_aided_config.get('title_aided', None) - if title_aided_config is not None: - if title_aided_config.get('enable', False): - llm_aided_title_start_time = time.time() - llm_aided_title(pdf_info_dict, title_aided_config) - logger.info(f'llm aided title time: {round(time.time() - llm_aided_title_start_time, 2)}') - - """dict转list""" - pdf_info_list = dict_to_list(pdf_info_dict) - new_pdf_info_dict = { - 'pdf_info': pdf_info_list, - } - - clean_memory(get_device()) - - return new_pdf_info_dict - - -if __name__ == '__main__': - pass diff --git a/magic_pdf/pre_proc/__init__.py b/magic_pdf/pre_proc/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/pre_proc/construct_page_dict.py b/magic_pdf/pre_proc/construct_page_dict.py deleted file mode 100644 index 09c09c137bc75c869c4d6f58594bb713c6944ec8..0000000000000000000000000000000000000000 --- a/magic_pdf/pre_proc/construct_page_dict.py +++ /dev/null @@ -1,17 +0,0 @@ - -def ocr_construct_page_component_v2(blocks, layout_bboxes, page_id, page_w, page_h, layout_tree, - images, tables, interline_equations, discarded_blocks, need_drop, drop_reason): - return_dict = { - 'preproc_blocks': blocks, - 'layout_bboxes': layout_bboxes, - 'page_idx': page_id, - 'page_size': [page_w, page_h], - '_layout_tree': layout_tree, - 'images': images, - 'tables': tables, - 'interline_equations': interline_equations, - 'discarded_blocks': discarded_blocks, - 'need_drop': need_drop, - 'drop_reason': drop_reason, - } - return return_dict diff --git a/magic_pdf/pre_proc/cut_image.py b/magic_pdf/pre_proc/cut_image.py deleted file mode 100644 index 901d372ec9ee6a5c6d9cdd0e25cf3b683f9179a9..0000000000000000000000000000000000000000 --- a/magic_pdf/pre_proc/cut_image.py +++ /dev/null @@ -1,32 +0,0 @@ -from loguru import logger - -from magic_pdf.config.ocr_content_type import ContentType -from magic_pdf.libs.commons import join_path -from magic_pdf.libs.pdf_image_tools import cut_image - - -def ocr_cut_image_and_table(spans, page, page_id, pdf_bytes_md5, imageWriter): - def return_path(type): - return join_path(pdf_bytes_md5, type) - - for span in spans: - span_type = span['type'] - if span_type == ContentType.Image: - if not check_img_bbox(span['bbox']) or not imageWriter: - continue - span['image_path'] = cut_image(span['bbox'], page_id, page, return_path=return_path('images'), - imageWriter=imageWriter) - elif span_type == ContentType.Table: - if not check_img_bbox(span['bbox']) or not imageWriter: - continue - span['image_path'] = cut_image(span['bbox'], page_id, page, return_path=return_path('tables'), - imageWriter=imageWriter) - - return spans - - -def check_img_bbox(bbox) -> bool: - if any([bbox[0] >= bbox[2], bbox[1] >= bbox[3]]): - logger.warning(f'image_bboxes: 错误的box, {bbox}') - return False - return True diff --git a/magic_pdf/pre_proc/ocr_span_list_modify.py b/magic_pdf/pre_proc/ocr_span_list_modify.py deleted file mode 100644 index 3fa9d2dd556c07b7d8571141f7103b024513e78c..0000000000000000000000000000000000000000 --- a/magic_pdf/pre_proc/ocr_span_list_modify.py +++ /dev/null @@ -1,131 +0,0 @@ - -from magic_pdf.config.drop_tag import DropTag -from magic_pdf.config.ocr_content_type import BlockType -from magic_pdf.libs.boxbase import calculate_iou, get_minbox_if_overlap_by_ratio - - -def remove_overlaps_low_confidence_spans(spans): - dropped_spans = [] - # 删除重叠spans中置信度低的的那些 - for span1 in spans: - for span2 in spans: - if span1 != span2: - # span1 或 span2 任何一个都不应该在 dropped_spans 中 - if span1 in dropped_spans or span2 in dropped_spans: - continue - else: - if calculate_iou(span1['bbox'], span2['bbox']) > 0.9: - if span1['score'] < span2['score']: - span_need_remove = span1 - else: - span_need_remove = span2 - if ( - span_need_remove is not None - and span_need_remove not in dropped_spans - ): - dropped_spans.append(span_need_remove) - - if len(dropped_spans) > 0: - for span_need_remove in dropped_spans: - spans.remove(span_need_remove) - span_need_remove['tag'] = DropTag.SPAN_OVERLAP - - return spans, dropped_spans - - -def check_chars_is_overlap_in_span(chars): - for i in range(len(chars)): - for j in range(i + 1, len(chars)): - if calculate_iou(chars[i]['bbox'], chars[j]['bbox']) > 0.35: - return True - return False - - -def remove_x_overlapping_chars(span, median_width): - """ - Remove characters from a span that overlap significantly on the x-axis. - - Args: - median_width: - span (dict): A span containing a list of chars, each with bbox coordinates - in the format [x0, y0, x1, y1] - - Returns: - dict: The span with overlapping characters removed - """ - if 'chars' not in span or len(span['chars']) < 2: - return span - - overlap_threshold = median_width * 0.3 - - i = 0 - while i < len(span['chars']) - 1: - char1 = span['chars'][i] - char2 = span['chars'][i + 1] - - # Calculate overlap width - x_left = max(char1['bbox'][0], char2['bbox'][0]) - x_right = min(char1['bbox'][2], char2['bbox'][2]) - - if x_right > x_left: # There is overlap - overlap_width = x_right - x_left - - if overlap_width > overlap_threshold: - if char1['c'] == char2['c'] or char1['c'] == ' ' or char2['c'] == ' ': - # Determine which character to remove - width1 = char1['bbox'][2] - char1['bbox'][0] - width2 = char2['bbox'][2] - char2['bbox'][0] - if width1 < width2: - # Remove the narrower character - span['chars'].pop(i) - else: - span['chars'].pop(i + 1) - else: - i += 1 - - # Don't increment i since we need to check the new pair - else: - i += 1 - else: - i += 1 - - return span - - -def remove_overlaps_min_spans(spans): - dropped_spans = [] - # 删除重叠spans中较小的那些 - for span1 in spans: - for span2 in spans: - if span1 != span2: - # span1 或 span2 任何一个都不应该在 dropped_spans 中 - if span1 in dropped_spans or span2 in dropped_spans: - continue - else: - overlap_box = get_minbox_if_overlap_by_ratio(span1['bbox'], span2['bbox'], 0.65) - if overlap_box is not None: - span_need_remove = next((span for span in spans if span['bbox'] == overlap_box), None) - if span_need_remove is not None and span_need_remove not in dropped_spans: - dropped_spans.append(span_need_remove) - if len(dropped_spans) > 0: - for span_need_remove in dropped_spans: - spans.remove(span_need_remove) - span_need_remove['tag'] = DropTag.SPAN_OVERLAP - - return spans, dropped_spans - - -def get_qa_need_list_v2(blocks): - # 创建 images, tables, interline_equations, inline_equations 的副本 - images = [] - tables = [] - interline_equations = [] - - for block in blocks: - if block['type'] == BlockType.Image: - images.append(block) - elif block['type'] == BlockType.Table: - tables.append(block) - elif block['type'] == BlockType.InterlineEquation: - interline_equations.append(block) - return images, tables, interline_equations diff --git a/magic_pdf/pre_proc/remove_bbox_overlap.py b/magic_pdf/pre_proc/remove_bbox_overlap.py deleted file mode 100644 index 35f96a10ba30221d6fb218a5e99e17253b5e30b1..0000000000000000000000000000000000000000 --- a/magic_pdf/pre_proc/remove_bbox_overlap.py +++ /dev/null @@ -1,100 +0,0 @@ -from magic_pdf.config.drop_reason import DropReason -from magic_pdf.libs.boxbase import _is_in, _is_part_overlap - - -def _remove_overlap_between_bbox(bbox1, bbox2): - if _is_part_overlap(bbox1, bbox2): - ix0, iy0, ix1, iy1 = bbox1 - x0, y0, x1, y1 = bbox2 - - diff_x = min(x1, ix1) - max(x0, ix0) - diff_y = min(y1, iy1) - max(y0, iy0) - - if diff_y > diff_x: - if x1 >= ix1: - mid = (x0 + ix1) // 2 - ix1 = min(mid - 0.25, ix1) - x0 = max(mid + 0.25, x0) - else: - mid = (ix0 + x1) // 2 - ix0 = max(mid + 0.25, ix0) - x1 = min(mid - 0.25, x1) - else: - if y1 >= iy1: - mid = (y0 + iy1) // 2 - y0 = max(mid + 0.25, y0) - iy1 = min(iy1, mid - 0.25) - else: - mid = (iy0 + y1) // 2 - y1 = min(y1, mid - 0.25) - iy0 = max(mid + 0.25, iy0) - - if ix1 > ix0 and iy1 > iy0 and y1 > y0 and x1 > x0: - bbox1 = [ix0, iy0, ix1, iy1] - bbox2 = [x0, y0, x1, y1] - return bbox1, bbox2, None - else: - return bbox1, bbox2, DropReason.NEGATIVE_BBOX_AREA - else: - return bbox1, bbox2, None - - -def _remove_overlap_between_bboxes(arr): - drop_reasons = [] - N = len(arr) - keeps = [True] * N - res = [None] * N - for i in range(N): - for j in range(N): - if i == j: - continue - if _is_in(arr[i]['bbox'], arr[j]['bbox']): - keeps[i] = False - - for idx, v in enumerate(arr): - if not keeps[idx]: - continue - for i in range(N): - if res[i] is None: - continue - - bbox1, bbox2, drop_reason = _remove_overlap_between_bbox( - v['bbox'], res[i]['bbox'] - ) - if drop_reason is None: - v['bbox'] = bbox1 - res[i]['bbox'] = bbox2 - else: - if v['score'] > res[i]['score']: - keeps[i] = False - res[i] = None - else: - keeps[idx] = False - drop_reasons.append(drop_reason) - if keeps[idx]: - res[idx] = v - return res, drop_reasons - - -def remove_overlap_between_bbox_for_span(spans): - arr = [{'bbox': span['bbox'], 'score': span.get('score', 0.1)} for span in spans] - res, drop_reasons = _remove_overlap_between_bboxes(arr) - ret = [] - for i in range(len(res)): - if res[i] is None: - continue - spans[i]['bbox'] = res[i]['bbox'] - ret.append(spans[i]) - return ret, drop_reasons - - -def remove_overlap_between_bbox_for_block(all_bboxes): - arr = [{'bbox': bbox[:4], 'score': bbox[-1]} for bbox in all_bboxes] - res, drop_reasons = _remove_overlap_between_bboxes(arr) - ret = [] - for i in range(len(res)): - if res[i] is None: - continue - all_bboxes[i][:4] = res[i]['bbox'] - ret.append(all_bboxes[i]) - return ret, drop_reasons diff --git a/magic_pdf/resources/model_config/model_configs.yaml b/magic_pdf/resources/model_config/model_configs.yaml deleted file mode 100644 index 0ee1aa0e8de8ef6baec4964b75d9f753b5c25da5..0000000000000000000000000000000000000000 --- a/magic_pdf/resources/model_config/model_configs.yaml +++ /dev/null @@ -1,8 +0,0 @@ -weights: - layoutlmv3: Layout/LayoutLMv3/model_final.pth - doclayout_yolo: Layout/YOLO/doclayout_yolo_docstructbench_imgsz1280_2501.pt - yolo_v8_mfd: MFD/YOLO/yolo_v8_ft.pt - unimernet_small: MFR/unimernet_hf_small_2503 - struct_eqtable: TabRec/StructEqTable - tablemaster: TabRec/TableMaster - rapid_table: TabRec/RapidTable \ No newline at end of file diff --git a/magic_pdf/resources/slanet_plus/slanet-plus.onnx b/magic_pdf/resources/slanet_plus/slanet-plus.onnx deleted file mode 100644 index d263823cdbc683f63ab7ec3d46eaa381a93b8079..0000000000000000000000000000000000000000 Binary files a/magic_pdf/resources/slanet_plus/slanet-plus.onnx and /dev/null differ diff --git a/magic_pdf/resources/yolov11-langdetect/yolo_v11_ft.pt b/magic_pdf/resources/yolov11-langdetect/yolo_v11_ft.pt deleted file mode 100644 index 8e7dbe703a4431b318d5b73724bd9693acdd2be2..0000000000000000000000000000000000000000 Binary files a/magic_pdf/resources/yolov11-langdetect/yolo_v11_ft.pt and /dev/null differ diff --git a/magic_pdf/spark/__init__.py b/magic_pdf/spark/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/spark/spark_api.py b/magic_pdf/spark/spark_api.py deleted file mode 100644 index 5d9faeb580840336978e8f4c3e683a7ec709dfa1..0000000000000000000000000000000000000000 --- a/magic_pdf/spark/spark_api.py +++ /dev/null @@ -1,49 +0,0 @@ -from loguru import logger - -from magic_pdf.config.drop_reason import DropReason - - -def get_data_source(jso: dict): - data_source = jso.get('data_source') - if data_source is None: - data_source = jso.get('file_source') - return data_source - - -def get_data_type(jso: dict): - data_type = jso.get('data_type') - if data_type is None: - data_type = jso.get('file_type') - return data_type - - -def get_bookid(jso: dict): - book_id = jso.get('bookid') - if book_id is None: - book_id = jso.get('original_file_id') - return book_id - - -def exception_handler(jso: dict, e): - logger.exception(e) - jso['_need_drop'] = True - jso['_drop_reason'] = DropReason.Exception - jso['_exception'] = f'ERROR: {e}' - return jso - - -def get_bookname(jso: dict): - data_source = get_data_source(jso) - file_id = jso.get('file_id') - book_name = f'{data_source}/{file_id}' - return book_name - - -def spark_json_extractor(jso: dict) -> dict: - - """从json中提取数据,返回一个dict.""" - - return { - '_pdf_type': jso['_pdf_type'], - 'model_list': jso['doc_layout_result'], - } diff --git a/magic_pdf/tools/__init__.py b/magic_pdf/tools/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/tools/cli.py b/magic_pdf/tools/cli.py deleted file mode 100644 index d204b26a4cba7e5088bd7b37807df44ea478fbef..0000000000000000000000000000000000000000 --- a/magic_pdf/tools/cli.py +++ /dev/null @@ -1,161 +0,0 @@ -import os -import shutil -import tempfile -from pathlib import Path - -import click -import fitz -from loguru import logger - -import magic_pdf.model as model_config -from magic_pdf.data.batch_build_dataset import batch_build_dataset -from magic_pdf.data.data_reader_writer import FileBasedDataReader -from magic_pdf.data.dataset import Dataset -from magic_pdf.libs.version import __version__ -from magic_pdf.tools.common import batch_do_parse, do_parse, parse_pdf_methods -from magic_pdf.utils.office_to_pdf import convert_file_to_pdf - -pdf_suffixes = ['.pdf'] -ms_office_suffixes = ['.ppt', '.pptx', '.doc', '.docx'] -image_suffixes = ['.png', '.jpeg', '.jpg'] - - -@click.command() -@click.version_option(__version__, - '--version', - '-v', - help='display the version and exit') -@click.option( - '-p', - '--path', - 'path', - type=click.Path(exists=True), - required=True, - help='local filepath or directory. support PDF, PPT, PPTX, DOC, DOCX, PNG, JPG files', -) -@click.option( - '-o', - '--output-dir', - 'output_dir', - type=click.Path(), - required=True, - help='output local directory', -) -@click.option( - '-m', - '--method', - 'method', - type=parse_pdf_methods, - help="""the method for parsing pdf. -ocr: using ocr technique to extract information from pdf. -txt: suitable for the text-based pdf only and outperform ocr. -auto: automatically choose the best method for parsing pdf from ocr and txt. -without method specified, auto will be used by default.""", - default='auto', -) -@click.option( - '-l', - '--lang', - 'lang', - type=str, - help=""" - Input the languages in the pdf (if known) to improve OCR accuracy. Optional. - You should input "Abbreviation" with language form url: - https://paddlepaddle.github.io/PaddleOCR/latest/en/ppocr/blog/multi_languages.html#5-support-languages-and-abbreviations - """, - default=None, -) -@click.option( - '-d', - '--debug', - 'debug_able', - type=bool, - help='Enables detailed debugging information during the execution of the CLI commands.', - default=False, -) -@click.option( - '-s', - '--start', - 'start_page_id', - type=int, - help='The starting page for PDF parsing, beginning from 0.', - default=0, -) -@click.option( - '-e', - '--end', - 'end_page_id', - type=int, - help='The ending page for PDF parsing, beginning from 0.', - default=None, -) -def cli(path, output_dir, method, lang, debug_able, start_page_id, end_page_id): - os.makedirs(output_dir, exist_ok=True) - temp_dir = tempfile.mkdtemp() - def read_fn(path: Path): - if path.suffix in ms_office_suffixes: - convert_file_to_pdf(str(path), temp_dir) - fn = os.path.join(temp_dir, f'{path.stem}.pdf') - elif path.suffix in image_suffixes: - with open(str(path), 'rb') as f: - bits = f.read() - pdf_bytes = fitz.open(stream=bits).convert_to_pdf() - fn = os.path.join(temp_dir, f'{path.stem}.pdf') - with open(fn, 'wb') as f: - f.write(pdf_bytes) - elif path.suffix in pdf_suffixes: - fn = str(path) - else: - raise Exception(f'Unknown file suffix: {path.suffix}') - - disk_rw = FileBasedDataReader(os.path.dirname(fn)) - return disk_rw.read(os.path.basename(fn)) - - def parse_doc(doc_path: Path, dataset: Dataset | None = None): - try: - file_name = str(Path(doc_path).stem) - if dataset is None: - pdf_data_or_dataset = read_fn(doc_path) - else: - pdf_data_or_dataset = dataset - do_parse( - output_dir, - file_name, - pdf_data_or_dataset, - [], - method, - debug_able, - start_page_id=start_page_id, - end_page_id=end_page_id, - lang=lang - ) - - except Exception as e: - logger.exception(e) - - if os.path.isdir(path): - doc_paths = [] - for doc_path in Path(path).glob('*'): - if doc_path.suffix in pdf_suffixes + image_suffixes + ms_office_suffixes: - if doc_path.suffix in ms_office_suffixes: - convert_file_to_pdf(str(doc_path), temp_dir) - doc_path = Path(os.path.join(temp_dir, f'{doc_path.stem}.pdf')) - elif doc_path.suffix in image_suffixes: - with open(str(doc_path), 'rb') as f: - bits = f.read() - pdf_bytes = fitz.open(stream=bits).convert_to_pdf() - fn = os.path.join(temp_dir, f'{doc_path.stem}.pdf') - with open(fn, 'wb') as f: - f.write(pdf_bytes) - doc_path = Path(fn) - doc_paths.append(doc_path) - datasets = batch_build_dataset(doc_paths, 4, lang) - batch_do_parse(output_dir, [str(doc_path.stem) for doc_path in doc_paths], datasets, method, debug_able, lang=lang) - else: - parse_doc(Path(path)) - - shutil.rmtree(temp_dir) - - -if __name__ == '__main__': - cli() diff --git a/magic_pdf/tools/cli_dev.py b/magic_pdf/tools/cli_dev.py deleted file mode 100644 index 6973d04a60ccc31cfbfbcb8562324c05aac20e84..0000000000000000000000000000000000000000 --- a/magic_pdf/tools/cli_dev.py +++ /dev/null @@ -1,149 +0,0 @@ -import json as json_parse -import os -from pathlib import Path - -import click - -import magic_pdf.model as model_config -from magic_pdf.data.data_reader_writer import FileBasedDataReader, S3DataReader -from magic_pdf.libs.config_reader import get_s3_config -from magic_pdf.libs.path_utils import (parse_s3_range_params, parse_s3path, - remove_non_official_s3_args) -from magic_pdf.libs.version import __version__ -from magic_pdf.tools.common import do_parse, parse_pdf_methods - - -def read_s3_path(s3path): - bucket, key = parse_s3path(s3path) - - s3_ak, s3_sk, s3_endpoint = get_s3_config(bucket) - s3_rw = S3DataReader('', bucket, s3_ak, s3_sk, s3_endpoint, 'auto') - may_range_params = parse_s3_range_params(s3path) - if may_range_params is None or 2 != len(may_range_params): - byte_start, byte_end = 0, -1 - else: - byte_start, byte_end = int(may_range_params[0]), int( - may_range_params[1]) - return s3_rw.read_at( - remove_non_official_s3_args(s3path), - byte_start, - byte_end, - ) - - -@click.group() -@click.version_option(__version__, '--version', '-v', help='显示版本信息') -def cli(): - pass - - -@cli.command() -@click.option( - '-j', - '--jsonl', - 'jsonl', - type=str, - help='输入 jsonl 路径,本地或者 s3 上的文件', - required=True, -) -@click.option( - '-m', - '--method', - 'method', - type=parse_pdf_methods, - help='指定解析方法。txt: 文本型 pdf 解析方法, ocr: 光学识别解析 pdf, auto: 程序智能选择解析方法', - default='auto', -) -@click.option( - '-o', - '--output-dir', - 'output_dir', - type=click.Path(), - required=True, - help='输出到本地目录', -) -def jsonl(jsonl, method, output_dir): - model_config.__use_inside_model__ = False - if jsonl.startswith('s3://'): - jso = json_parse.loads(read_s3_path(jsonl).decode('utf-8')) - else: - with open(jsonl) as f: - jso = json_parse.loads(f.readline()) - os.makedirs(output_dir, exist_ok=True) - s3_file_path = jso.get('file_location') - if s3_file_path is None: - s3_file_path = jso.get('path') - pdf_file_name = Path(s3_file_path).stem - pdf_data = read_s3_path(s3_file_path) - - print(pdf_file_name, jso, method) - do_parse( - output_dir, - pdf_file_name, - pdf_data, - jso['doc_layout_result'], - method, - False, - f_dump_content_list=True, - f_draw_model_bbox=True, - ) - - -@cli.command() -@click.option( - '-p', - '--pdf', - 'pdf', - type=click.Path(exists=True), - required=True, - help='本地 PDF 文件', -) -@click.option( - '-j', - '--json', - 'json_data', - type=click.Path(exists=True), - required=True, - help='本地模型推理出的 json 数据', -) -@click.option('-o', - '--output-dir', - 'output_dir', - type=click.Path(), - required=True, - help='本地输出目录') -@click.option( - '-m', - '--method', - 'method', - type=parse_pdf_methods, - help='指定解析方法。txt: 文本型 pdf 解析方法, ocr: 光学识别解析 pdf, auto: 程序智能选择解析方法', - default='auto', -) -def pdf(pdf, json_data, output_dir, method): - model_config.__use_inside_model__ = False - full_pdf_path = os.path.realpath(pdf) - os.makedirs(output_dir, exist_ok=True) - - def read_fn(path): - disk_rw = FileBasedDataReader(os.path.dirname(path)) - return disk_rw.read(os.path.basename(path)) - - model_json_list = json_parse.loads(read_fn(json_data).decode('utf-8')) - - file_name = str(Path(full_pdf_path).stem) - pdf_data = read_fn(full_pdf_path) - do_parse( - output_dir, - file_name, - pdf_data, - model_json_list, - method, - False, - f_dump_content_list=True, - f_draw_model_bbox=True, - ) - - -if __name__ == '__main__': - cli() diff --git a/magic_pdf/tools/common.py b/magic_pdf/tools/common.py deleted file mode 100644 index 06c52a8aa425afd3fa754a4a4ae63a49187a0349..0000000000000000000000000000000000000000 --- a/magic_pdf/tools/common.py +++ /dev/null @@ -1,340 +0,0 @@ -import os - -import click -import fitz -from loguru import logger - -import magic_pdf.model as model_config -from magic_pdf.config.enums import SupportedPdfParseMethod -from magic_pdf.config.make_content_config import DropMode, MakeMode -from magic_pdf.data.data_reader_writer import FileBasedDataWriter -from magic_pdf.data.dataset import Dataset, PymuDocDataset -from magic_pdf.libs.draw_bbox import draw_char_bbox -from magic_pdf.model.doc_analyze_by_custom_model import (batch_doc_analyze, - doc_analyze) - -# from io import BytesIO -# from pypdf import PdfReader, PdfWriter - - -def prepare_env(output_dir, pdf_file_name, method): - local_parent_dir = os.path.join(output_dir, pdf_file_name, method) - - local_image_dir = os.path.join(str(local_parent_dir), 'images') - local_md_dir = local_parent_dir - os.makedirs(local_image_dir, exist_ok=True) - os.makedirs(local_md_dir, exist_ok=True) - return local_image_dir, local_md_dir - - -# def convert_pdf_bytes_to_bytes_by_pypdf(pdf_bytes, start_page_id=0, end_page_id=None): -# # 将字节数据包装在 BytesIO 对象中 -# pdf_file = BytesIO(pdf_bytes) -# # 读取 PDF 的字节数据 -# reader = PdfReader(pdf_file) -# # 创建一个新的 PDF 写入器 -# writer = PdfWriter() -# # 将所有页面添加到新的 PDF 写入器中 -# end_page_id = end_page_id if end_page_id is not None and end_page_id >= 0 else len(reader.pages) - 1 -# if end_page_id > len(reader.pages) - 1: -# logger.warning("end_page_id is out of range, use pdf_docs length") -# end_page_id = len(reader.pages) - 1 -# for i, page in enumerate(reader.pages): -# if start_page_id <= i <= end_page_id: -# writer.add_page(page) -# # 创建一个字节缓冲区来存储输出的 PDF 数据 -# output_buffer = BytesIO() -# # 将 PDF 写入字节缓冲区 -# writer.write(output_buffer) -# # 获取字节缓冲区的内容 -# converted_pdf_bytes = output_buffer.getvalue() -# return converted_pdf_bytes - - -def convert_pdf_bytes_to_bytes_by_pymupdf(pdf_bytes, start_page_id=0, end_page_id=None): - document = fitz.open('pdf', pdf_bytes) - output_document = fitz.open() - end_page_id = ( - end_page_id - if end_page_id is not None and end_page_id >= 0 - else len(document) - 1 - ) - if end_page_id > len(document) - 1: - logger.warning('end_page_id is out of range, use pdf_docs length') - end_page_id = len(document) - 1 - output_document.insert_pdf(document, from_page=start_page_id, to_page=end_page_id) - output_bytes = output_document.tobytes() - return output_bytes - - -def _do_parse( - output_dir, - pdf_file_name, - pdf_bytes_or_dataset, - model_list, - parse_method, - debug_able=False, - f_draw_span_bbox=True, - f_draw_layout_bbox=True, - f_dump_md=True, - f_dump_middle_json=True, - f_dump_model_json=True, - f_dump_orig_pdf=True, - f_dump_content_list=True, - f_make_md_mode=MakeMode.MM_MD, - f_draw_model_bbox=False, - f_draw_line_sort_bbox=False, - f_draw_char_bbox=False, - start_page_id=0, - end_page_id=None, - lang=None, - layout_model=None, - formula_enable=None, - table_enable=None, -): - from magic_pdf.operators.models import InferenceResult - if debug_able: - logger.warning('debug mode is on') - f_draw_model_bbox = True - f_draw_line_sort_bbox = True - # f_draw_char_bbox = True - - if isinstance(pdf_bytes_or_dataset, bytes): - pdf_bytes = convert_pdf_bytes_to_bytes_by_pymupdf( - pdf_bytes_or_dataset, start_page_id, end_page_id - ) - ds = PymuDocDataset(pdf_bytes, lang=lang) - else: - ds = pdf_bytes_or_dataset - pdf_bytes = ds._raw_data - local_image_dir, local_md_dir = prepare_env(output_dir, pdf_file_name, parse_method) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter(local_md_dir) - image_dir = str(os.path.basename(local_image_dir)) - - if len(model_list) == 0: - if model_config.__use_inside_model__: - if parse_method == 'auto': - if ds.classify() == SupportedPdfParseMethod.TXT: - infer_result = ds.apply( - doc_analyze, - ocr=False, - lang=ds._lang, - layout_model=layout_model, - formula_enable=formula_enable, - table_enable=table_enable, - ) - pipe_result = infer_result.pipe_txt_mode( - image_writer, debug_mode=True, lang=ds._lang - ) - else: - infer_result = ds.apply( - doc_analyze, - ocr=True, - lang=ds._lang, - layout_model=layout_model, - formula_enable=formula_enable, - table_enable=table_enable, - ) - pipe_result = infer_result.pipe_ocr_mode( - image_writer, debug_mode=True, lang=ds._lang - ) - - elif parse_method == 'txt': - infer_result = ds.apply( - doc_analyze, - ocr=False, - lang=ds._lang, - layout_model=layout_model, - formula_enable=formula_enable, - table_enable=table_enable, - ) - pipe_result = infer_result.pipe_txt_mode( - image_writer, debug_mode=True, lang=ds._lang - ) - elif parse_method == 'ocr': - infer_result = ds.apply( - doc_analyze, - ocr=True, - lang=ds._lang, - layout_model=layout_model, - formula_enable=formula_enable, - table_enable=table_enable, - ) - pipe_result = infer_result.pipe_ocr_mode( - image_writer, debug_mode=True, lang=ds._lang - ) - else: - logger.error('unknown parse method') - exit(1) - else: - logger.error('need model list input') - exit(2) - else: - - infer_result = InferenceResult(model_list, ds) - if parse_method == 'ocr': - pipe_result = infer_result.pipe_ocr_mode( - image_writer, debug_mode=True, lang=ds._lang - ) - elif parse_method == 'txt': - pipe_result = infer_result.pipe_txt_mode( - image_writer, debug_mode=True, lang=ds._lang - ) - else: - if ds.classify() == SupportedPdfParseMethod.TXT: - pipe_result = infer_result.pipe_txt_mode( - image_writer, debug_mode=True, lang=ds._lang - ) - else: - pipe_result = infer_result.pipe_ocr_mode( - image_writer, debug_mode=True, lang=ds._lang - ) - - - if f_draw_model_bbox: - infer_result.draw_model( - os.path.join(local_md_dir, f'{pdf_file_name}_model.pdf') - ) - - if f_draw_layout_bbox: - pipe_result.draw_layout( - os.path.join(local_md_dir, f'{pdf_file_name}_layout.pdf') - ) - if f_draw_span_bbox: - pipe_result.draw_span(os.path.join(local_md_dir, f'{pdf_file_name}_spans.pdf')) - - if f_draw_line_sort_bbox: - pipe_result.draw_line_sort( - os.path.join(local_md_dir, f'{pdf_file_name}_line_sort.pdf') - ) - - if f_draw_char_bbox: - draw_char_bbox(pdf_bytes, local_md_dir, f'{pdf_file_name}_char_bbox.pdf') - - if f_dump_md: - pipe_result.dump_md( - md_writer, - f'{pdf_file_name}.md', - image_dir, - drop_mode=DropMode.NONE, - md_make_mode=f_make_md_mode, - ) - - if f_dump_middle_json: - pipe_result.dump_middle_json(md_writer, f'{pdf_file_name}_middle.json') - - if f_dump_model_json: - infer_result.dump_model(md_writer, f'{pdf_file_name}_model.json') - - if f_dump_orig_pdf: - md_writer.write( - f'{pdf_file_name}_origin.pdf', - pdf_bytes, - ) - - if f_dump_content_list: - pipe_result.dump_content_list( - md_writer, - f'{pdf_file_name}_content_list.json', - image_dir - ) - - logger.info(f'local output dir is {local_md_dir}') - -def do_parse( - output_dir, - pdf_file_name, - pdf_bytes_or_dataset, - model_list, - parse_method, - debug_able=False, - f_draw_span_bbox=True, - f_draw_layout_bbox=True, - f_dump_md=True, - f_dump_middle_json=True, - f_dump_model_json=True, - f_dump_orig_pdf=True, - f_dump_content_list=True, - f_make_md_mode=MakeMode.MM_MD, - f_draw_model_bbox=False, - f_draw_line_sort_bbox=False, - f_draw_char_bbox=False, - start_page_id=0, - end_page_id=None, - lang=None, - layout_model=None, - formula_enable=None, - table_enable=None, -): - parallel_count = 1 - if os.environ.get('MINERU_PARALLEL_INFERENCE_COUNT'): - parallel_count = int(os.environ['MINERU_PARALLEL_INFERENCE_COUNT']) - - if parallel_count > 1: - if isinstance(pdf_bytes_or_dataset, bytes): - pdf_bytes = convert_pdf_bytes_to_bytes_by_pymupdf( - pdf_bytes_or_dataset, start_page_id, end_page_id - ) - ds = PymuDocDataset(pdf_bytes, lang=lang) - else: - ds = pdf_bytes_or_dataset - batch_do_parse(output_dir, [pdf_file_name], [ds], parse_method, debug_able, f_draw_span_bbox=f_draw_span_bbox, f_draw_layout_bbox=f_draw_layout_bbox, f_dump_md=f_dump_md, f_dump_middle_json=f_dump_middle_json, f_dump_model_json=f_dump_model_json, f_dump_orig_pdf=f_dump_orig_pdf, f_dump_content_list=f_dump_content_list, f_make_md_mode=f_make_md_mode, f_draw_model_bbox=f_draw_model_bbox, f_draw_line_sort_bbox=f_draw_line_sort_bbox, f_draw_char_bbox=f_draw_char_bbox, lang=lang) - else: - _do_parse(output_dir, pdf_file_name, pdf_bytes_or_dataset, model_list, parse_method, debug_able, start_page_id=start_page_id, end_page_id=end_page_id, lang=lang, layout_model=layout_model, formula_enable=formula_enable, table_enable=table_enable, f_draw_span_bbox=f_draw_span_bbox, f_draw_layout_bbox=f_draw_layout_bbox, f_dump_md=f_dump_md, f_dump_middle_json=f_dump_middle_json, f_dump_model_json=f_dump_model_json, f_dump_orig_pdf=f_dump_orig_pdf, f_dump_content_list=f_dump_content_list, f_make_md_mode=f_make_md_mode, f_draw_model_bbox=f_draw_model_bbox, f_draw_line_sort_bbox=f_draw_line_sort_bbox, f_draw_char_bbox=f_draw_char_bbox) - - -def batch_do_parse( - output_dir, - pdf_file_names: list[str], - pdf_bytes_or_datasets: list[bytes | Dataset], - parse_method, - debug_able=False, - f_draw_span_bbox=True, - f_draw_layout_bbox=True, - f_dump_md=True, - f_dump_middle_json=True, - f_dump_model_json=True, - f_dump_orig_pdf=True, - f_dump_content_list=True, - f_make_md_mode=MakeMode.MM_MD, - f_draw_model_bbox=False, - f_draw_line_sort_bbox=False, - f_draw_char_bbox=False, - lang=None, - layout_model=None, - formula_enable=None, - table_enable=None, -): - dss = [] - for v in pdf_bytes_or_datasets: - if isinstance(v, bytes): - dss.append(PymuDocDataset(v, lang=lang)) - else: - dss.append(v) - - infer_results = batch_doc_analyze(dss, parse_method, lang=lang, layout_model=layout_model, formula_enable=formula_enable, table_enable=table_enable) - for idx, infer_result in enumerate(infer_results): - _do_parse( - output_dir = output_dir, - pdf_file_name = pdf_file_names[idx], - pdf_bytes_or_dataset = dss[idx], - model_list = infer_result.get_infer_res(), - parse_method = parse_method, - debug_able = debug_able, - f_draw_span_bbox = f_draw_span_bbox, - f_draw_layout_bbox = f_draw_layout_bbox, - f_dump_md=f_dump_md, - f_dump_middle_json=f_dump_middle_json, - f_dump_model_json=f_dump_model_json, - f_dump_orig_pdf=f_dump_orig_pdf, - f_dump_content_list=f_dump_content_list, - f_make_md_mode=MakeMode.MM_MD, - f_draw_model_bbox=f_draw_model_bbox, - f_draw_line_sort_bbox=f_draw_line_sort_bbox, - f_draw_char_bbox=f_draw_char_bbox, - lang=lang, - ) - - -parse_pdf_methods = click.Choice(['ocr', 'txt', 'auto']) diff --git a/magic_pdf/utils/__init__.py b/magic_pdf/utils/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/magic_pdf/utils/annotations.py b/magic_pdf/utils/annotations.py deleted file mode 100644 index 898d88033b724b0083a6a2124b8f805cabadd104..0000000000000000000000000000000000000000 --- a/magic_pdf/utils/annotations.py +++ /dev/null @@ -1,11 +0,0 @@ - -from loguru import logger - - -def ImportPIL(f): - try: - import PIL # noqa: F401 - except ImportError: - logger.error('Pillow not installed, please install by pip.') - exit(1) - return f diff --git a/magic_pdf/utils/office_to_pdf.py b/magic_pdf/utils/office_to_pdf.py deleted file mode 100644 index b6d03daec6bb900f470041c096cd8d943d27382c..0000000000000000000000000000000000000000 --- a/magic_pdf/utils/office_to_pdf.py +++ /dev/null @@ -1,115 +0,0 @@ -import os -import subprocess -import platform -from pathlib import Path -import shutil - -from loguru import logger - - -class ConvertToPdfError(Exception): - def __init__(self, msg): - self.msg = msg - super().__init__(self.msg) - - -def check_fonts_installed(): - """Check if required Chinese fonts are installed.""" - system_type = platform.system() - - if system_type in ['Windows', 'Darwin']: - pass - else: - # Linux: use fc-list - try: - output = subprocess.check_output(['fc-list', ':lang=zh'], encoding='utf-8') - if output.strip(): # 只要有任何输出(非空) - return True - else: - logger.warning( - f"No Chinese fonts were detected, the converted document may not display Chinese content properly." - ) - except Exception: - pass - - -def get_soffice_command(): - """Return the path to LibreOffice's soffice executable depending on the platform.""" - system_type = platform.system() - - # First check if soffice is in PATH - soffice_path = shutil.which('soffice') - if soffice_path: - return soffice_path - - if system_type == 'Windows': - # Check common installation paths - possible_paths = [ - Path(os.environ.get('PROGRAMFILES', 'C:/Program Files')) / 'LibreOffice/program/soffice.exe', - Path(os.environ.get('PROGRAMFILES(X86)', 'C:/Program Files (x86)')) / 'LibreOffice/program/soffice.exe', - Path('C:/Program Files/LibreOffice/program/soffice.exe'), - Path('C:/Program Files (x86)/LibreOffice/program/soffice.exe') - ] - - # Check other drives for windows - for drive in ['C:', 'D:', 'E:', 'F:', 'G:', 'H:']: - possible_paths.append(Path(f"{drive}/LibreOffice/program/soffice.exe")) - - for path in possible_paths: - if path.exists(): - return str(path) - - raise ConvertToPdfError( - "LibreOffice not found. Please install LibreOffice from https://www.libreoffice.org/ " - "or ensure soffice.exe is in your PATH environment variable." - ) - else: - # For Linux/macOS, provide installation instructions if not found - try: - # Try to find soffice in standard locations - possible_paths = [ - '/usr/bin/soffice', - '/usr/local/bin/soffice', - '/opt/libreoffice/program/soffice', - '/Applications/LibreOffice.app/Contents/MacOS/soffice' - ] - for path in possible_paths: - if os.path.exists(path): - return path - - raise ConvertToPdfError( - "LibreOffice not found. Please install it:\n" - " - Ubuntu/Debian: sudo apt-get install libreoffice\n" - " - CentOS/RHEL: sudo yum install libreoffice\n" - " - macOS: brew install libreoffice or download from https://www.libreoffice.org/\n" - " - Or ensure soffice is in your PATH environment variable." - ) - except Exception as e: - raise ConvertToPdfError(f"Error locating LibreOffice: {str(e)}") - - -def convert_file_to_pdf(input_path, output_dir): - """Convert a single document (ppt, doc, etc.) to PDF.""" - if not os.path.isfile(input_path): - raise FileNotFoundError(f"The input file {input_path} does not exist.") - - os.makedirs(output_dir, exist_ok=True) - - check_fonts_installed() - - soffice_cmd = get_soffice_command() - - cmd = [ - soffice_cmd, - '--headless', - '--norestore', - '--invisible', - '--convert-to', 'pdf', - '--outdir', str(output_dir), - str(input_path) - ] - - process = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - if process.returncode != 0: - raise ConvertToPdfError(f"LibreOffice convert failed: {process.stderr.decode()}") diff --git a/mineru.template.json b/mineru.template.json new file mode 100644 index 0000000000000000000000000000000000000000..9b9971dbfd85e99ffd4b37821f0e94f4ed58f2c5 --- /dev/null +++ b/mineru.template.json @@ -0,0 +1,29 @@ +{ + "bucket_info":{ + "bucket-name-1":["ak", "sk", "endpoint"], + "bucket-name-2":["ak", "sk", "endpoint"] + }, + "latex-delimiter-config": { + "display": { + "left": "$$", + "right": "$$" + }, + "inline": { + "left": "$", + "right": "$" + } + }, + "llm-aided-config": { + "title_aided": { + "api_key": "your_api_key", + "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", + "model": "qwen2.5-32b-instruct", + "enable": false + } + }, + "models-dir": { + "pipeline": "", + "vlm": "" + }, + "config_version": "1.3.0" +} \ No newline at end of file diff --git a/magic_pdf/model/sub_modules/language_detection/__init__.py b/mineru/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/language_detection/__init__.py rename to mineru/__init__.py diff --git a/magic_pdf/model/sub_modules/language_detection/yolov11/__init__.py b/mineru/backend/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/language_detection/yolov11/__init__.py rename to mineru/backend/__init__.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/__init__.py b/mineru/backend/pipeline/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/__init__.py rename to mineru/backend/pipeline/__init__.py diff --git a/mineru/backend/pipeline/batch_analyze.py b/mineru/backend/pipeline/batch_analyze.py new file mode 100644 index 0000000000000000000000000000000000000000..97d98155d0afd0d92e6aeee7e0c6af78bcb9d460 --- /dev/null +++ b/mineru/backend/pipeline/batch_analyze.py @@ -0,0 +1,323 @@ +import cv2 +from loguru import logger +from tqdm import tqdm +from collections import defaultdict +import numpy as np + +from .model_init import AtomModelSingleton +from ...utils.model_utils import crop_img, get_res_list_from_layout_res +from ...utils.ocr_utils import get_adjusted_mfdetrec_res, get_ocr_result_list, OcrConfidence + +YOLO_LAYOUT_BASE_BATCH_SIZE = 1 +MFD_BASE_BATCH_SIZE = 1 +MFR_BASE_BATCH_SIZE = 16 + + +class BatchAnalyze: + def __init__(self, model_manager, batch_ratio: int, formula_enable, table_enable, enable_ocr_det_batch: bool = True): + self.batch_ratio = batch_ratio + self.formula_enable = formula_enable + self.table_enable = table_enable + self.model_manager = model_manager + self.enable_ocr_det_batch = enable_ocr_det_batch + + def __call__(self, images_with_extra_info: list) -> list: + if len(images_with_extra_info) == 0: + return [] + + images_layout_res = [] + + self.model = self.model_manager.get_model( + lang=None, + formula_enable=self.formula_enable, + table_enable=self.table_enable, + ) + atom_model_manager = AtomModelSingleton() + + images = [image for image, _, _ in images_with_extra_info] + + # doclayout_yolo + layout_images = [] + for image_index, image in enumerate(images): + layout_images.append(image) + + + images_layout_res += self.model.layout_model.batch_predict( + layout_images, YOLO_LAYOUT_BASE_BATCH_SIZE + ) + + if self.formula_enable: + # 公式检测 + images_mfd_res = self.model.mfd_model.batch_predict( + images, MFD_BASE_BATCH_SIZE + ) + + # 公式识别 + images_formula_list = self.model.mfr_model.batch_predict( + images_mfd_res, + images, + batch_size=self.batch_ratio * MFR_BASE_BATCH_SIZE, + ) + mfr_count = 0 + for image_index in range(len(images)): + images_layout_res[image_index] += images_formula_list[image_index] + mfr_count += len(images_formula_list[image_index]) + + # 清理显存 + # clean_vram(self.model.device, vram_threshold=8) + + ocr_res_list_all_page = [] + table_res_list_all_page = [] + for index in range(len(images)): + _, ocr_enable, _lang = images_with_extra_info[index] + layout_res = images_layout_res[index] + pil_img = images[index] + + ocr_res_list, table_res_list, single_page_mfdetrec_res = ( + get_res_list_from_layout_res(layout_res) + ) + + ocr_res_list_all_page.append({'ocr_res_list':ocr_res_list, + 'lang':_lang, + 'ocr_enable':ocr_enable, + 'pil_img':pil_img, + 'single_page_mfdetrec_res':single_page_mfdetrec_res, + 'layout_res':layout_res, + }) + + for table_res in table_res_list: + table_img, _ = crop_img(table_res, pil_img) + table_res_list_all_page.append({'table_res':table_res, + 'lang':_lang, + 'table_img':table_img, + }) + + # OCR检测处理 + if self.enable_ocr_det_batch: + # 批处理模式 - 按语言和分辨率分组 + # 收集所有需要OCR检测的裁剪图像 + all_cropped_images_info = [] + + for ocr_res_list_dict in ocr_res_list_all_page: + _lang = ocr_res_list_dict['lang'] + + for res in ocr_res_list_dict['ocr_res_list']: + new_image, useful_list = crop_img( + res, ocr_res_list_dict['pil_img'], crop_paste_x=50, crop_paste_y=50 + ) + adjusted_mfdetrec_res = get_adjusted_mfdetrec_res( + ocr_res_list_dict['single_page_mfdetrec_res'], useful_list + ) + + # BGR转换 + new_image = cv2.cvtColor(np.asarray(new_image), cv2.COLOR_RGB2BGR) + + all_cropped_images_info.append(( + new_image, useful_list, ocr_res_list_dict, res, adjusted_mfdetrec_res, _lang + )) + + # 按语言分组 + lang_groups = defaultdict(list) + for crop_info in all_cropped_images_info: + lang = crop_info[5] + lang_groups[lang].append(crop_info) + + # 对每种语言按分辨率分组并批处理 + for lang, lang_crop_list in lang_groups.items(): + if not lang_crop_list: + continue + + # logger.info(f"Processing OCR detection for language {lang} with {len(lang_crop_list)} images") + + # 获取OCR模型 + ocr_model = atom_model_manager.get_atom_model( + atom_model_name='ocr', + det_db_box_thresh=0.3, + lang=lang + ) + + # 按分辨率分组并同时完成padding + resolution_groups = defaultdict(list) + for crop_info in lang_crop_list: + cropped_img = crop_info[0] + h, w = cropped_img.shape[:2] + # 使用更大的分组容差,减少分组数量 + # 将尺寸标准化到32的倍数 + normalized_h = ((h + 32) // 32) * 32 # 向上取整到32的倍数 + normalized_w = ((w + 32) // 32) * 32 + group_key = (normalized_h, normalized_w) + resolution_groups[group_key].append(crop_info) + + # 对每个分辨率组进行批处理 + for group_key, group_crops in tqdm(resolution_groups.items(), desc=f"OCR-det {lang}"): + + # 计算目标尺寸(组内最大尺寸,向上取整到32的倍数) + max_h = max(crop_info[0].shape[0] for crop_info in group_crops) + max_w = max(crop_info[0].shape[1] for crop_info in group_crops) + target_h = ((max_h + 32 - 1) // 32) * 32 + target_w = ((max_w + 32 - 1) // 32) * 32 + + # 对所有图像进行padding到统一尺寸 + batch_images = [] + for crop_info in group_crops: + img = crop_info[0] + h, w = img.shape[:2] + # 创建目标尺寸的白色背景 + padded_img = np.ones((target_h, target_w, 3), dtype=np.uint8) * 255 + # 将原图像粘贴到左上角 + padded_img[:h, :w] = img + batch_images.append(padded_img) + + # 批处理检测 + batch_size = min(len(batch_images), self.batch_ratio * 16) # 增加批处理大小 + # logger.debug(f"OCR-det batch: {batch_size} images, target size: {target_h}x{target_w}") + batch_results = ocr_model.text_detector.batch_predict(batch_images, batch_size) + + # 处理批处理结果 + for i, (crop_info, (dt_boxes, elapse)) in enumerate(zip(group_crops, batch_results)): + new_image, useful_list, ocr_res_list_dict, res, adjusted_mfdetrec_res, _lang = crop_info + + if dt_boxes is not None and len(dt_boxes) > 0: + # 直接应用原始OCR流程中的关键处理步骤 + from mineru.utils.ocr_utils import ( + merge_det_boxes, update_det_boxes, sorted_boxes + ) + + # 1. 排序检测框 + if len(dt_boxes) > 0: + dt_boxes_sorted = sorted_boxes(dt_boxes) + else: + dt_boxes_sorted = [] + + # 2. 合并相邻检测框 + if dt_boxes_sorted: + dt_boxes_merged = merge_det_boxes(dt_boxes_sorted) + else: + dt_boxes_merged = [] + + # 3. 根据公式位置更新检测框(关键步骤!) + if dt_boxes_merged and adjusted_mfdetrec_res: + dt_boxes_final = update_det_boxes(dt_boxes_merged, adjusted_mfdetrec_res) + else: + dt_boxes_final = dt_boxes_merged + + # 构造OCR结果格式 + ocr_res = [box.tolist() if hasattr(box, 'tolist') else box for box in dt_boxes_final] + + if ocr_res: + ocr_result_list = get_ocr_result_list( + ocr_res, useful_list, ocr_res_list_dict['ocr_enable'], new_image, _lang + ) + + ocr_res_list_dict['layout_res'].extend(ocr_result_list) + else: + # 原始单张处理模式 + for ocr_res_list_dict in tqdm(ocr_res_list_all_page, desc="OCR-det Predict"): + # Process each area that requires OCR processing + _lang = ocr_res_list_dict['lang'] + # Get OCR results for this language's images + ocr_model = atom_model_manager.get_atom_model( + atom_model_name='ocr', + ocr_show_log=False, + det_db_box_thresh=0.3, + lang=_lang + ) + for res in ocr_res_list_dict['ocr_res_list']: + new_image, useful_list = crop_img( + res, ocr_res_list_dict['pil_img'], crop_paste_x=50, crop_paste_y=50 + ) + adjusted_mfdetrec_res = get_adjusted_mfdetrec_res( + ocr_res_list_dict['single_page_mfdetrec_res'], useful_list + ) + # OCR-det + new_image = cv2.cvtColor(np.asarray(new_image), cv2.COLOR_RGB2BGR) + ocr_res = ocr_model.ocr( + new_image, mfd_res=adjusted_mfdetrec_res, rec=False + )[0] + + # Integration results + if ocr_res: + ocr_result_list = get_ocr_result_list( + ocr_res, useful_list, ocr_res_list_dict['ocr_enable'],new_image, _lang + ) + + ocr_res_list_dict['layout_res'].extend(ocr_result_list) + + # 表格识别 table recognition + if self.table_enable: + for table_res_dict in tqdm(table_res_list_all_page, desc="Table Predict"): + _lang = table_res_dict['lang'] + table_model = atom_model_manager.get_atom_model( + atom_model_name='table', + lang=_lang, + ) + html_code, table_cell_bboxes, logic_points, elapse = table_model.predict(table_res_dict['table_img']) + # 判断是否返回正常 + if html_code: + expected_ending = html_code.strip().endswith('') or html_code.strip().endswith('') + if expected_ending: + table_res_dict['table_res']['html'] = html_code + else: + logger.warning( + 'table recognition processing fails, not found expected HTML table end' + ) + else: + logger.warning( + 'table recognition processing fails, not get html return' + ) + + # Create dictionaries to store items by language + need_ocr_lists_by_lang = {} # Dict of lists for each language + img_crop_lists_by_lang = {} # Dict of lists for each language + + for layout_res in images_layout_res: + for layout_res_item in layout_res: + if layout_res_item['category_id'] in [15]: + if 'np_img' in layout_res_item and 'lang' in layout_res_item: + lang = layout_res_item['lang'] + + # Initialize lists for this language if not exist + if lang not in need_ocr_lists_by_lang: + need_ocr_lists_by_lang[lang] = [] + img_crop_lists_by_lang[lang] = [] + + # Add to the appropriate language-specific lists + need_ocr_lists_by_lang[lang].append(layout_res_item) + img_crop_lists_by_lang[lang].append(layout_res_item['np_img']) + + # Remove the fields after adding to lists + layout_res_item.pop('np_img') + layout_res_item.pop('lang') + + if len(img_crop_lists_by_lang) > 0: + + # Process OCR by language + total_processed = 0 + + # Process each language separately + for lang, img_crop_list in img_crop_lists_by_lang.items(): + if len(img_crop_list) > 0: + # Get OCR results for this language's images + + ocr_model = atom_model_manager.get_atom_model( + atom_model_name='ocr', + det_db_box_thresh=0.3, + lang=lang + ) + ocr_res_list = ocr_model.ocr(img_crop_list, det=False, tqdm_enable=True)[0] + + # Verify we have matching counts + assert len(ocr_res_list) == len( + need_ocr_lists_by_lang[lang]), f'ocr_res_list: {len(ocr_res_list)}, need_ocr_list: {len(need_ocr_lists_by_lang[lang])} for lang: {lang}' + + # Process OCR results for this language + for index, layout_res_item in enumerate(need_ocr_lists_by_lang[lang]): + ocr_text, ocr_score = ocr_res_list[index] + layout_res_item['text'] = ocr_text + layout_res_item['score'] = float(f"{ocr_score:.3f}") + if ocr_score < OcrConfidence.min_confidence: + layout_res_item['category_id'] = 16 + + total_processed += len(img_crop_list) + + return images_layout_res diff --git a/mineru/backend/pipeline/model_init.py b/mineru/backend/pipeline/model_init.py new file mode 100644 index 0000000000000000000000000000000000000000..ac6f2e8de0d03a3045f7019bb07607b3e48eed0b --- /dev/null +++ b/mineru/backend/pipeline/model_init.py @@ -0,0 +1,182 @@ +import os + +import torch +from loguru import logger + +from .model_list import AtomicModel +from ...model.layout.doclayout_yolo import DocLayoutYOLOModel +from ...model.mfd.yolo_v8 import YOLOv8MFDModel +from ...model.mfr.unimernet.Unimernet import UnimernetModel +from ...model.ocr.paddleocr2pytorch.pytorch_paddle import PytorchPaddleOCR +from ...model.table.rapid_table import RapidTableModel +from ...utils.enum_class import ModelPath +from ...utils.models_download_utils import auto_download_and_get_model_root_path + + +def table_model_init(lang=None): + atom_model_manager = AtomModelSingleton() + ocr_engine = atom_model_manager.get_atom_model( + atom_model_name='ocr', + det_db_box_thresh=0.5, + det_db_unclip_ratio=1.6, + lang=lang + ) + table_model = RapidTableModel(ocr_engine) + return table_model + + +def mfd_model_init(weight, device='cpu'): + if str(device).startswith('npu'): + device = torch.device(device) + mfd_model = YOLOv8MFDModel(weight, device) + return mfd_model + + +def mfr_model_init(weight_dir, device='cpu'): + mfr_model = UnimernetModel(weight_dir, device) + return mfr_model + + +def doclayout_yolo_model_init(weight, device='cpu'): + if str(device).startswith('npu'): + device = torch.device(device) + model = DocLayoutYOLOModel(weight, device) + return model + +def ocr_model_init(det_db_box_thresh=0.3, + lang=None, + use_dilation=True, + det_db_unclip_ratio=1.8, + ): + if lang is not None and lang != '': + model = PytorchPaddleOCR( + det_db_box_thresh=det_db_box_thresh, + lang=lang, + use_dilation=use_dilation, + det_db_unclip_ratio=det_db_unclip_ratio, + ) + else: + model = PytorchPaddleOCR( + det_db_box_thresh=det_db_box_thresh, + use_dilation=use_dilation, + det_db_unclip_ratio=det_db_unclip_ratio, + ) + return model + + +class AtomModelSingleton: + _instance = None + _models = {} + + def __new__(cls, *args, **kwargs): + if cls._instance is None: + cls._instance = super().__new__(cls) + return cls._instance + + def get_atom_model(self, atom_model_name: str, **kwargs): + + lang = kwargs.get('lang', None) + table_model_name = kwargs.get('table_model_name', None) + + if atom_model_name in [AtomicModel.OCR]: + key = (atom_model_name, lang) + elif atom_model_name in [AtomicModel.Table]: + key = (atom_model_name, table_model_name, lang) + else: + key = atom_model_name + + if key not in self._models: + self._models[key] = atom_model_init(model_name=atom_model_name, **kwargs) + return self._models[key] + +def atom_model_init(model_name: str, **kwargs): + atom_model = None + if model_name == AtomicModel.Layout: + atom_model = doclayout_yolo_model_init( + kwargs.get('doclayout_yolo_weights'), + kwargs.get('device') + ) + elif model_name == AtomicModel.MFD: + atom_model = mfd_model_init( + kwargs.get('mfd_weights'), + kwargs.get('device') + ) + elif model_name == AtomicModel.MFR: + atom_model = mfr_model_init( + kwargs.get('mfr_weight_dir'), + kwargs.get('device') + ) + elif model_name == AtomicModel.OCR: + atom_model = ocr_model_init( + kwargs.get('det_db_box_thresh'), + kwargs.get('lang'), + ) + elif model_name == AtomicModel.Table: + atom_model = table_model_init( + kwargs.get('lang'), + ) + else: + logger.error('model name not allow') + exit(1) + + if atom_model is None: + logger.error('model init failed') + exit(1) + else: + return atom_model + + +class MineruPipelineModel: + def __init__(self, **kwargs): + self.formula_config = kwargs.get('formula_config') + self.apply_formula = self.formula_config.get('enable', True) + self.table_config = kwargs.get('table_config') + self.apply_table = self.table_config.get('enable', True) + self.lang = kwargs.get('lang', None) + self.device = kwargs.get('device', 'cpu') + logger.info( + 'DocAnalysis init, this may take some times......' + ) + atom_model_manager = AtomModelSingleton() + + if self.apply_formula: + # 初始化公式检测模型 + self.mfd_model = atom_model_manager.get_atom_model( + atom_model_name=AtomicModel.MFD, + mfd_weights=str( + os.path.join(auto_download_and_get_model_root_path(ModelPath.yolo_v8_mfd), ModelPath.yolo_v8_mfd) + ), + device=self.device, + ) + + # 初始化公式解析模型 + mfr_weight_dir = os.path.join(auto_download_and_get_model_root_path(ModelPath.unimernet_small), ModelPath.unimernet_small) + + self.mfr_model = atom_model_manager.get_atom_model( + atom_model_name=AtomicModel.MFR, + mfr_weight_dir=mfr_weight_dir, + device=self.device, + ) + + # 初始化layout模型 + self.layout_model = atom_model_manager.get_atom_model( + atom_model_name=AtomicModel.Layout, + doclayout_yolo_weights=str( + os.path.join(auto_download_and_get_model_root_path(ModelPath.doclayout_yolo), ModelPath.doclayout_yolo) + ), + device=self.device, + ) + # 初始化ocr + self.ocr_model = atom_model_manager.get_atom_model( + atom_model_name=AtomicModel.OCR, + det_db_box_thresh=0.3, + lang=self.lang + ) + # init table model + if self.apply_table: + self.table_model = atom_model_manager.get_atom_model( + atom_model_name=AtomicModel.Table, + lang=self.lang, + ) + + logger.info('DocAnalysis init done!') \ No newline at end of file diff --git a/mineru/backend/pipeline/model_json_to_middle_json.py b/mineru/backend/pipeline/model_json_to_middle_json.py new file mode 100644 index 0000000000000000000000000000000000000000..668574b543eccbac57cf45917ff2219f46501c89 --- /dev/null +++ b/mineru/backend/pipeline/model_json_to_middle_json.py @@ -0,0 +1,249 @@ +# Copyright (c) Opendatalab. All rights reserved. +import time + +from loguru import logger +from tqdm import tqdm + +from mineru.utils.config_reader import get_device, get_llm_aided_config +from mineru.backend.pipeline.model_init import AtomModelSingleton +from mineru.backend.pipeline.para_split import para_split +from mineru.utils.block_pre_proc import prepare_block_bboxes, process_groups +from mineru.utils.block_sort import sort_blocks_by_bbox +from mineru.utils.boxbase import calculate_overlap_area_in_bbox1_area_ratio +from mineru.utils.cut_image import cut_image_and_table +from mineru.utils.enum_class import ContentType +from mineru.utils.llm_aided import llm_aided_title +from mineru.utils.model_utils import clean_memory +from mineru.backend.pipeline.pipeline_magic_model import MagicModel +from mineru.utils.ocr_utils import OcrConfidence +from mineru.utils.span_block_fix import fill_spans_in_blocks, fix_discarded_block, fix_block_spans +from mineru.utils.span_pre_proc import remove_outside_spans, remove_overlaps_low_confidence_spans, \ + remove_overlaps_min_spans, txt_spans_extract +from mineru.version import __version__ +from mineru.utils.hash_utils import str_md5 + + +def page_model_info_to_page_info(page_model_info, image_dict, page, image_writer, page_index, ocr_enable=False, formula_enabled=True): + scale = image_dict["scale"] + page_pil_img = image_dict["img_pil"] + page_img_md5 = str_md5(image_dict["img_base64"]) + page_w, page_h = map(int, page.get_size()) + magic_model = MagicModel(page_model_info, scale) + + """从magic_model对象中获取后面会用到的区块信息""" + discarded_blocks = magic_model.get_discarded() + text_blocks = magic_model.get_text_blocks() + title_blocks = magic_model.get_title_blocks() + inline_equations, interline_equations, interline_equation_blocks = magic_model.get_equations() + + img_groups = magic_model.get_imgs() + table_groups = magic_model.get_tables() + + """对image和table的区块分组""" + img_body_blocks, img_caption_blocks, img_footnote_blocks, maybe_text_image_blocks = process_groups( + img_groups, 'image_body', 'image_caption_list', 'image_footnote_list' + ) + + table_body_blocks, table_caption_blocks, table_footnote_blocks, _ = process_groups( + table_groups, 'table_body', 'table_caption_list', 'table_footnote_list' + ) + + """获取所有的spans信息""" + spans = magic_model.get_all_spans() + + """某些图可能是文本块,通过简单的规则判断一下""" + if len(maybe_text_image_blocks) > 0: + for block in maybe_text_image_blocks: + span_in_block_list = [] + for span in spans: + if span['type'] == 'text' and calculate_overlap_area_in_bbox1_area_ratio(span['bbox'], block['bbox']) > 0.7: + span_in_block_list.append(span) + if len(span_in_block_list) > 0: + # span_in_block_list中所有bbox的面积之和 + spans_area = sum((span['bbox'][2] - span['bbox'][0]) * (span['bbox'][3] - span['bbox'][1]) for span in span_in_block_list) + # 求ocr_res_area和res的面积的比值 + block_area = (block['bbox'][2] - block['bbox'][0]) * (block['bbox'][3] - block['bbox'][1]) + if block_area > 0: + ratio = spans_area / block_area + if ratio > 0.25 and ocr_enable: + # 移除block的group_id + block.pop('group_id', None) + # 符合文本图的条件就把块加入到文本块列表中 + text_blocks.append(block) + else: + # 如果不符合文本图的条件,就把块加回到图片块列表中 + img_body_blocks.append(block) + else: + img_body_blocks.append(block) + + + """将所有区块的bbox整理到一起""" + if formula_enabled: + interline_equation_blocks = [] + + if len(interline_equation_blocks) > 0: + + for block in interline_equation_blocks: + spans.append({ + "type": ContentType.INTERLINE_EQUATION, + 'score': block['score'], + "bbox": block['bbox'], + }) + + all_bboxes, all_discarded_blocks, footnote_blocks = prepare_block_bboxes( + img_body_blocks, img_caption_blocks, img_footnote_blocks, + table_body_blocks, table_caption_blocks, table_footnote_blocks, + discarded_blocks, + text_blocks, + title_blocks, + interline_equation_blocks, + page_w, + page_h, + ) + else: + all_bboxes, all_discarded_blocks, footnote_blocks = prepare_block_bboxes( + img_body_blocks, img_caption_blocks, img_footnote_blocks, + table_body_blocks, table_caption_blocks, table_footnote_blocks, + discarded_blocks, + text_blocks, + title_blocks, + interline_equations, + page_w, + page_h, + ) + + """在删除重复span之前,应该通过image_body和table_body的block过滤一下image和table的span""" + """顺便删除大水印并保留abandon的span""" + spans = remove_outside_spans(spans, all_bboxes, all_discarded_blocks) + + """删除重叠spans中置信度较低的那些""" + spans, dropped_spans_by_confidence = remove_overlaps_low_confidence_spans(spans) + """删除重叠spans中较小的那些""" + spans, dropped_spans_by_span_overlap = remove_overlaps_min_spans(spans) + + """根据parse_mode,构造spans,主要是文本类的字符填充""" + if ocr_enable: + pass + else: + """使用新版本的混合ocr方案.""" + spans = txt_spans_extract(page, spans, page_pil_img, scale, all_bboxes, all_discarded_blocks) + + """先处理不需要排版的discarded_blocks""" + discarded_block_with_spans, spans = fill_spans_in_blocks( + all_discarded_blocks, spans, 0.4 + ) + fix_discarded_blocks = fix_discarded_block(discarded_block_with_spans) + + """如果当前页面没有有效的bbox则跳过""" + if len(all_bboxes) == 0: + return None + + """对image/table/interline_equation截图""" + for span in spans: + if span['type'] in [ContentType.IMAGE, ContentType.TABLE, ContentType.INTERLINE_EQUATION]: + span = cut_image_and_table( + span, page_pil_img, page_img_md5, page_index, image_writer, scale=scale + ) + + """span填充进block""" + block_with_spans, spans = fill_spans_in_blocks(all_bboxes, spans, 0.5) + + """对block进行fix操作""" + fix_blocks = fix_block_spans(block_with_spans) + + """同一行被断开的titile合并""" + # merge_title_blocks(fix_blocks) + + """对block进行排序""" + sorted_blocks = sort_blocks_by_bbox(fix_blocks, page_w, page_h, footnote_blocks) + + """构造page_info""" + page_info = make_page_info_dict(sorted_blocks, page_index, page_w, page_h, fix_discarded_blocks) + + return page_info + + +def result_to_middle_json(model_list, images_list, pdf_doc, image_writer, lang=None, ocr_enable=False, formula_enabled=True): + middle_json = {"pdf_info": [], "_backend":"pipeline", "_version_name": __version__} + for page_index, page_model_info in tqdm(enumerate(model_list), total=len(model_list), desc="Processing pages"): + page = pdf_doc[page_index] + image_dict = images_list[page_index] + page_info = page_model_info_to_page_info( + page_model_info, image_dict, page, image_writer, page_index, ocr_enable=ocr_enable, formula_enabled=formula_enabled + ) + if page_info is None: + page_w, page_h = map(int, page.get_size()) + page_info = make_page_info_dict([], page_index, page_w, page_h, []) + middle_json["pdf_info"].append(page_info) + + """后置ocr处理""" + need_ocr_list = [] + img_crop_list = [] + text_block_list = [] + for page_info in middle_json["pdf_info"]: + for block in page_info['preproc_blocks']: + if block['type'] in ['table', 'image']: + for sub_block in block['blocks']: + if sub_block['type'] in ['image_caption', 'image_footnote', 'table_caption', 'table_footnote']: + text_block_list.append(sub_block) + elif block['type'] in ['text', 'title']: + text_block_list.append(block) + for block in page_info['discarded_blocks']: + text_block_list.append(block) + for block in text_block_list: + for line in block['lines']: + for span in line['spans']: + if 'np_img' in span: + need_ocr_list.append(span) + img_crop_list.append(span['np_img']) + span.pop('np_img') + if len(img_crop_list) > 0: + atom_model_manager = AtomModelSingleton() + ocr_model = atom_model_manager.get_atom_model( + atom_model_name='ocr', + ocr_show_log=False, + det_db_box_thresh=0.3, + lang=lang + ) + ocr_res_list = ocr_model.ocr(img_crop_list, det=False, tqdm_enable=True)[0] + assert len(ocr_res_list) == len( + need_ocr_list), f'ocr_res_list: {len(ocr_res_list)}, need_ocr_list: {len(need_ocr_list)}' + for index, span in enumerate(need_ocr_list): + ocr_text, ocr_score = ocr_res_list[index] + if ocr_score > OcrConfidence.min_confidence: + span['content'] = ocr_text + span['score'] = float(f"{ocr_score:.3f}") + else: + span['content'] = '' + span['score'] = 0.0 + + """分段""" + para_split(middle_json["pdf_info"]) + + """llm优化""" + llm_aided_config = get_llm_aided_config() + + if llm_aided_config is not None: + """标题优化""" + title_aided_config = llm_aided_config.get('title_aided', None) + if title_aided_config is not None: + if title_aided_config.get('enable', False): + llm_aided_title_start_time = time.time() + llm_aided_title(middle_json["pdf_info"], title_aided_config) + logger.info(f'llm aided title time: {round(time.time() - llm_aided_title_start_time, 2)}') + + """清理内存""" + pdf_doc.close() + clean_memory(get_device()) + + return middle_json + + +def make_page_info_dict(blocks, page_id, page_w, page_h, discarded_blocks): + return_dict = { + 'preproc_blocks': blocks, + 'page_idx': page_id, + 'page_size': [page_w, page_h], + 'discarded_blocks': discarded_blocks, + } + return return_dict \ No newline at end of file diff --git a/magic_pdf/model/model_list.py b/mineru/backend/pipeline/model_list.py similarity index 51% rename from magic_pdf/model/model_list.py rename to mineru/backend/pipeline/model_list.py index ec871d16981dc663d9ff635886ca847d6b16f6d5..3676ae6709b7eeea746470f2233e0772a6bf62bf 100644 --- a/magic_pdf/model/model_list.py +++ b/mineru/backend/pipeline/model_list.py @@ -1,12 +1,6 @@ -class MODEL: - Paddle = "pp_structure_v2" - PEK = "pdf_extract_kit" - - class AtomicModel: Layout = "layout" MFD = "mfd" MFR = "mfr" OCR = "ocr" Table = "table" - LangDetect = "langdetect" diff --git a/magic_pdf/post_proc/para_split_v3.py b/mineru/backend/pipeline/para_split.py similarity index 91% rename from magic_pdf/post_proc/para_split_v3.py rename to mineru/backend/pipeline/para_split.py index 5f6852a69c40bbf3e6bd2d42c2c0218ce88ab280..39e568105ea8a01610ba99fef041c8c0622a61b9 100644 --- a/magic_pdf/post_proc/para_split_v3.py +++ b/mineru/backend/pipeline/para_split.py @@ -1,27 +1,10 @@ import copy - from loguru import logger +from mineru.utils.enum_class import ContentType, BlockType, SplitFlag +from mineru.utils.language import detect_lang + -from magic_pdf.config.constants import CROSS_PAGE, LINES_DELETED -from magic_pdf.config.ocr_content_type import BlockType, ContentType -from magic_pdf.libs.language import detect_lang - -LINE_STOP_FLAG = ( - '.', - '!', - '?', - '。', - '!', - '?', - ')', - ')', - '"', - '”', - ':', - ':', - ';', - ';', -) +LINE_STOP_FLAG = ('.', '!', '?', '。', '!', '?', ')', ')', '"', '”', ':', ':', ';', ';') LIST_END_FLAG = ('.', '。', ';', ';') @@ -115,7 +98,7 @@ def __is_list_or_index_block(block): for span in line['spans']: span_type = span['type'] - if span_type == ContentType.Text: + if span_type == ContentType.TEXT: line_text += span['content'].strip() # 添加所有文本,包括空行,保持与block['lines']长度一致 lines_text_list.append(line_text) @@ -191,7 +174,7 @@ def __is_list_or_index_block(block): ) and line_num_flag: for line in block['lines']: line[ListLineTag.IS_LIST_START_LINE] = True - return BlockType.Index + return BlockType.INDEX # 全部line都居中的特殊list识别,每行都需要换行,特征是多行,且大多数行都前后not_close,每line中点x坐标接近 # 补充条件block的长宽比有要求 @@ -203,7 +186,7 @@ def __is_list_or_index_block(block): ): for line in block['lines']: line[ListLineTag.IS_LIST_START_LINE] = True - return BlockType.List + return BlockType.LIST elif ( left_close_num >= 2 @@ -260,11 +243,11 @@ def __is_list_or_index_block(block): if abs(block['bbox_fs'][2] - line['bbox'][2]) > line_height: line[ListLineTag.IS_LIST_END_LINE] = True - return BlockType.List + return BlockType.LIST else: - return BlockType.Text + return BlockType.TEXT else: - return BlockType.Text + return BlockType.TEXT def __merge_2_text_blocks(block1, block2): @@ -299,10 +282,10 @@ def __merge_2_text_blocks(block1, block2): if block1['page_num'] != block2['page_num']: for line in block1['lines']: for span in line['spans']: - span[CROSS_PAGE] = True + span[SplitFlag.CROSS_PAGE] = True block2['lines'].extend(block1['lines']) block1['lines'] = [] - block1[LINES_DELETED] = True + block1[SplitFlag.LINES_DELETED] = True return block1, block2 @@ -311,10 +294,10 @@ def __merge_2_list_blocks(block1, block2): if block1['page_num'] != block2['page_num']: for line in block1['lines']: for span in line['spans']: - span[CROSS_PAGE] = True + span[SplitFlag.CROSS_PAGE] = True block2['lines'].extend(block1['lines']) block1['lines'] = [] - block1[LINES_DELETED] = True + block1[SplitFlag.LINES_DELETED] = True return block1, block2 @@ -357,11 +340,11 @@ def __para_merge_page(blocks): ): __merge_2_text_blocks(current_block, prev_block) elif ( - current_block['type'] == BlockType.List - and prev_block['type'] == BlockType.List + current_block['type'] == BlockType.LIST + and prev_block['type'] == BlockType.LIST ) or ( - current_block['type'] == BlockType.Index - and prev_block['type'] == BlockType.Index + current_block['type'] == BlockType.INDEX + and prev_block['type'] == BlockType.INDEX ): __merge_2_list_blocks(current_block, prev_block) @@ -369,21 +352,21 @@ def __para_merge_page(blocks): continue -def para_split(pdf_info_dict): +def para_split(page_info_list): all_blocks = [] - for page_num, page in pdf_info_dict.items(): - blocks = copy.deepcopy(page['preproc_blocks']) + for page_info in page_info_list: + blocks = copy.deepcopy(page_info['preproc_blocks']) for block in blocks: - block['page_num'] = page_num - block['page_size'] = page['page_size'] + block['page_num'] = page_info['page_idx'] + block['page_size'] = page_info['page_size'] all_blocks.extend(blocks) __para_merge_page(all_blocks) - for page_num, page in pdf_info_dict.items(): - page['para_blocks'] = [] + for page_info in page_info_list: + page_info['para_blocks'] = [] for block in all_blocks: - if block['page_num'] == page_num: - page['para_blocks'].append(block) + if block['page_num'] == page_info['page_idx']: + page_info['para_blocks'].append(block) if __name__ == '__main__': diff --git a/mineru/backend/pipeline/pipeline_analyze.py b/mineru/backend/pipeline/pipeline_analyze.py new file mode 100644 index 0000000000000000000000000000000000000000..3df9d4a5d414dc699a981a0fe5c12f3e9f9b6d04 --- /dev/null +++ b/mineru/backend/pipeline/pipeline_analyze.py @@ -0,0 +1,202 @@ +import os +import time +from typing import List, Tuple +import PIL.Image +import torch + +from .model_init import MineruPipelineModel +from mineru.utils.config_reader import get_device, get_formula_config, get_table_recog_config +from ...utils.pdf_classify import classify +from ...utils.pdf_image_tools import load_images_from_pdf + +from loguru import logger + +from ...utils.model_utils import get_vram, clean_memory + + +os.environ['PYTORCH_ENABLE_MPS_FALLBACK'] = '1' # 让mps可以fallback +os.environ['NO_ALBUMENTATIONS_UPDATE'] = '1' # 禁止albumentations检查更新 + +class ModelSingleton: + _instance = None + _models = {} + + def __new__(cls, *args, **kwargs): + if cls._instance is None: + cls._instance = super().__new__(cls) + return cls._instance + + def get_model( + self, + lang=None, + formula_enable=None, + table_enable=None, + ): + key = (lang, formula_enable, table_enable) + if key not in self._models: + self._models[key] = custom_model_init( + lang=lang, + formula_enable=formula_enable, + table_enable=table_enable, + ) + return self._models[key] + + +def custom_model_init( + lang=None, + formula_enable=None, + table_enable=None, +): + model_init_start = time.time() + # 从配置文件读取model-dir和device + device = get_device() + + formula_config = get_formula_config() + if formula_enable is not None: + formula_config['enable'] = formula_enable + + table_config = get_table_recog_config() + if table_enable is not None: + table_config['enable'] = table_enable + + model_input = { + 'device': device, + 'table_config': table_config, + 'formula_config': formula_config, + 'lang': lang, + } + + custom_model = MineruPipelineModel(**model_input) + + model_init_cost = time.time() - model_init_start + logger.info(f'model init cost: {model_init_cost}') + + return custom_model + + +def doc_analyze( + pdf_bytes_list, + lang_list, + parse_method: str = 'auto', + formula_enable=None, + table_enable=None, +): + MIN_BATCH_INFERENCE_SIZE = int(os.environ.get('MINERU_MIN_BATCH_INFERENCE_SIZE', 100)) + + # 收集所有页面信息 + all_pages_info = [] # 存储(dataset_index, page_index, img, ocr, lang, width, height) + + all_image_lists = [] + all_pdf_docs = [] + ocr_enabled_list = [] + for pdf_idx, pdf_bytes in enumerate(pdf_bytes_list): + # 确定OCR设置 + _ocr_enable = False + if parse_method == 'auto': + if classify(pdf_bytes) == 'ocr': + _ocr_enable = True + elif parse_method == 'ocr': + _ocr_enable = True + + ocr_enabled_list.append(_ocr_enable) + _lang = lang_list[pdf_idx] + + # 收集每个数据集中的页面 + images_list, pdf_doc = load_images_from_pdf(pdf_bytes) + all_image_lists.append(images_list) + all_pdf_docs.append(pdf_doc) + for page_idx in range(len(images_list)): + img_dict = images_list[page_idx] + all_pages_info.append(( + pdf_idx, page_idx, + img_dict['img_pil'], _ocr_enable, _lang, + )) + + # 准备批处理 + images_with_extra_info = [(info[2], info[3], info[4]) for info in all_pages_info] + batch_size = MIN_BATCH_INFERENCE_SIZE + batch_images = [ + images_with_extra_info[i:i + batch_size] + for i in range(0, len(images_with_extra_info), batch_size) + ] + + # 执行批处理 + results = [] + processed_images_count = 0 + for index, batch_image in enumerate(batch_images): + processed_images_count += len(batch_image) + logger.info( + f'Batch {index + 1}/{len(batch_images)}: ' + f'{processed_images_count} pages/{len(images_with_extra_info)} pages' + ) + batch_results = batch_image_analyze(batch_image, formula_enable, table_enable) + results.extend(batch_results) + + # 构建返回结果 + infer_results = [] + + for _ in range(len(pdf_bytes_list)): + infer_results.append([]) + + for i, page_info in enumerate(all_pages_info): + pdf_idx, page_idx, pil_img, _, _ = page_info + result = results[i] + + page_info_dict = {'page_no': page_idx, 'width': pil_img.width, 'height': pil_img.height} + page_dict = {'layout_dets': result, 'page_info': page_info_dict} + + infer_results[pdf_idx].append(page_dict) + + return infer_results, all_image_lists, all_pdf_docs, lang_list, ocr_enabled_list + + +def batch_image_analyze( + images_with_extra_info: List[Tuple[PIL.Image.Image, bool, str]], + formula_enable=None, + table_enable=None): + # os.environ['CUDA_VISIBLE_DEVICES'] = str(idx) + + from .batch_analyze import BatchAnalyze + + model_manager = ModelSingleton() + + batch_ratio = 1 + device = get_device() + + if str(device).startswith('npu'): + try: + import torch_npu + if torch_npu.npu.is_available(): + torch.npu.set_compile_mode(jit_compile=False) + except Exception as e: + raise RuntimeError( + "NPU is selected as device, but torch_npu is not available. " + "Please ensure that the torch_npu package is installed correctly." + ) from e + + if str(device).startswith('npu') or str(device).startswith('cuda'): + vram = get_vram(device) + if vram is not None: + gpu_memory = int(os.getenv('MINERU_VIRTUAL_VRAM_SIZE', round(vram))) + if gpu_memory >= 16: + batch_ratio = 16 + elif gpu_memory >= 12: + batch_ratio = 8 + elif gpu_memory >= 8: + batch_ratio = 4 + elif gpu_memory >= 6: + batch_ratio = 2 + else: + batch_ratio = 1 + logger.info(f'gpu_memory: {gpu_memory} GB, batch_ratio: {batch_ratio}') + else: + # Default batch_ratio when VRAM can't be determined + batch_ratio = 1 + logger.info(f'Could not determine GPU memory, using default batch_ratio: {batch_ratio}') + + batch_model = BatchAnalyze(model_manager, batch_ratio, formula_enable, table_enable) + results = batch_model(images_with_extra_info) + + clean_memory(get_device()) + + return results \ No newline at end of file diff --git a/mineru/backend/pipeline/pipeline_magic_model.py b/mineru/backend/pipeline/pipeline_magic_model.py new file mode 100644 index 0000000000000000000000000000000000000000..1c5c0434233941cf30664171e4b311bb48d9644a --- /dev/null +++ b/mineru/backend/pipeline/pipeline_magic_model.py @@ -0,0 +1,441 @@ +from mineru.utils.boxbase import bbox_relative_pos, calculate_iou, bbox_distance, is_in +from mineru.utils.enum_class import CategoryId, ContentType + + +class MagicModel: + """每个函数没有得到元素的时候返回空list.""" + def __init__(self, page_model_info: dict, scale: float): + self.__page_model_info = page_model_info + self.__scale = scale + """为所有模型数据添加bbox信息(缩放,poly->bbox)""" + self.__fix_axis() + """删除置信度特别低的模型数据(<0.05),提高质量""" + self.__fix_by_remove_low_confidence() + """删除高iou(>0.9)数据中置信度较低的那个""" + self.__fix_by_remove_high_iou_and_low_confidence() + self.__fix_footnote() + + def __fix_axis(self): + need_remove_list = [] + layout_dets = self.__page_model_info['layout_dets'] + for layout_det in layout_dets: + x0, y0, _, _, x1, y1, _, _ = layout_det['poly'] + bbox = [ + int(x0 / self.__scale), + int(y0 / self.__scale), + int(x1 / self.__scale), + int(y1 / self.__scale), + ] + layout_det['bbox'] = bbox + # 删除高度或者宽度小于等于0的spans + if bbox[2] - bbox[0] <= 0 or bbox[3] - bbox[1] <= 0: + need_remove_list.append(layout_det) + for need_remove in need_remove_list: + layout_dets.remove(need_remove) + + def __fix_by_remove_low_confidence(self): + need_remove_list = [] + layout_dets = self.__page_model_info['layout_dets'] + for layout_det in layout_dets: + if layout_det['score'] <= 0.05: + need_remove_list.append(layout_det) + else: + continue + for need_remove in need_remove_list: + layout_dets.remove(need_remove) + + def __fix_by_remove_high_iou_and_low_confidence(self): + need_remove_list = [] + layout_dets = self.__page_model_info['layout_dets'] + for layout_det1 in layout_dets: + for layout_det2 in layout_dets: + if layout_det1 == layout_det2: + continue + if layout_det1['category_id'] in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] and layout_det2['category_id'] in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]: + if ( + calculate_iou(layout_det1['bbox'], layout_det2['bbox']) + > 0.9 + ): + if layout_det1['score'] < layout_det2['score']: + layout_det_need_remove = layout_det1 + else: + layout_det_need_remove = layout_det2 + + if layout_det_need_remove not in need_remove_list: + need_remove_list.append(layout_det_need_remove) + else: + continue + else: + continue + for need_remove in need_remove_list: + layout_dets.remove(need_remove) + + def __fix_footnote(self): + # 3: figure, 5: table, 7: footnote + footnotes = [] + figures = [] + tables = [] + + for obj in self.__page_model_info['layout_dets']: + if obj['category_id'] == 7: + footnotes.append(obj) + elif obj['category_id'] == 3: + figures.append(obj) + elif obj['category_id'] == 5: + tables.append(obj) + if len(footnotes) * len(figures) == 0: + continue + dis_figure_footnote = {} + dis_table_footnote = {} + + for i in range(len(footnotes)): + for j in range(len(figures)): + pos_flag_count = sum( + list( + map( + lambda x: 1 if x else 0, + bbox_relative_pos( + footnotes[i]['bbox'], figures[j]['bbox'] + ), + ) + ) + ) + if pos_flag_count > 1: + continue + dis_figure_footnote[i] = min( + self._bbox_distance(figures[j]['bbox'], footnotes[i]['bbox']), + dis_figure_footnote.get(i, float('inf')), + ) + for i in range(len(footnotes)): + for j in range(len(tables)): + pos_flag_count = sum( + list( + map( + lambda x: 1 if x else 0, + bbox_relative_pos( + footnotes[i]['bbox'], tables[j]['bbox'] + ), + ) + ) + ) + if pos_flag_count > 1: + continue + + dis_table_footnote[i] = min( + self._bbox_distance(tables[j]['bbox'], footnotes[i]['bbox']), + dis_table_footnote.get(i, float('inf')), + ) + for i in range(len(footnotes)): + if i not in dis_figure_footnote: + continue + if dis_table_footnote.get(i, float('inf')) > dis_figure_footnote[i]: + footnotes[i]['category_id'] = CategoryId.ImageFootnote + + def _bbox_distance(self, bbox1, bbox2): + left, right, bottom, top = bbox_relative_pos(bbox1, bbox2) + flags = [left, right, bottom, top] + count = sum([1 if v else 0 for v in flags]) + if count > 1: + return float('inf') + if left or right: + l1 = bbox1[3] - bbox1[1] + l2 = bbox2[3] - bbox2[1] + else: + l1 = bbox1[2] - bbox1[0] + l2 = bbox2[2] - bbox2[0] + + if l2 > l1 and (l2 - l1) / l1 > 0.3: + return float('inf') + + return bbox_distance(bbox1, bbox2) + + def __reduct_overlap(self, bboxes): + N = len(bboxes) + keep = [True] * N + for i in range(N): + for j in range(N): + if i == j: + continue + if is_in(bboxes[i]['bbox'], bboxes[j]['bbox']): + keep[i] = False + return [bboxes[i] for i in range(N) if keep[i]] + + def __tie_up_category_by_distance_v3( + self, + subject_category_id: int, + object_category_id: int, + ): + subjects = self.__reduct_overlap( + list( + map( + lambda x: {'bbox': x['bbox'], 'score': x['score']}, + filter( + lambda x: x['category_id'] == subject_category_id, + self.__page_model_info['layout_dets'], + ), + ) + ) + ) + objects = self.__reduct_overlap( + list( + map( + lambda x: {'bbox': x['bbox'], 'score': x['score']}, + filter( + lambda x: x['category_id'] == object_category_id, + self.__page_model_info['layout_dets'], + ), + ) + ) + ) + + ret = [] + N, M = len(subjects), len(objects) + subjects.sort(key=lambda x: x['bbox'][0] ** 2 + x['bbox'][1] ** 2) + objects.sort(key=lambda x: x['bbox'][0] ** 2 + x['bbox'][1] ** 2) + + OBJ_IDX_OFFSET = 10000 + SUB_BIT_KIND, OBJ_BIT_KIND = 0, 1 + + all_boxes_with_idx = [(i, SUB_BIT_KIND, sub['bbox'][0], sub['bbox'][1]) for i, sub in enumerate(subjects)] + [(i + OBJ_IDX_OFFSET , OBJ_BIT_KIND, obj['bbox'][0], obj['bbox'][1]) for i, obj in enumerate(objects)] + seen_idx = set() + seen_sub_idx = set() + + while N > len(seen_sub_idx): + candidates = [] + for idx, kind, x0, y0 in all_boxes_with_idx: + if idx in seen_idx: + continue + candidates.append((idx, kind, x0, y0)) + + if len(candidates) == 0: + break + left_x = min([v[2] for v in candidates]) + top_y = min([v[3] for v in candidates]) + + candidates.sort(key=lambda x: (x[2]-left_x) ** 2 + (x[3] - top_y) ** 2) + + + fst_idx, fst_kind, left_x, top_y = candidates[0] + candidates.sort(key=lambda x: (x[2] - left_x) ** 2 + (x[3] - top_y)**2) + nxt = None + + for i in range(1, len(candidates)): + if candidates[i][1] ^ fst_kind == 1: + nxt = candidates[i] + break + if nxt is None: + break + + if fst_kind == SUB_BIT_KIND: + sub_idx, obj_idx = fst_idx, nxt[0] - OBJ_IDX_OFFSET + + else: + sub_idx, obj_idx = nxt[0], fst_idx - OBJ_IDX_OFFSET + + pair_dis = bbox_distance(subjects[sub_idx]['bbox'], objects[obj_idx]['bbox']) + nearest_dis = float('inf') + for i in range(N): + if i in seen_idx or i == sub_idx:continue + nearest_dis = min(nearest_dis, bbox_distance(subjects[i]['bbox'], objects[obj_idx]['bbox'])) + + if pair_dis >= 3*nearest_dis: + seen_idx.add(sub_idx) + continue + + seen_idx.add(sub_idx) + seen_idx.add(obj_idx + OBJ_IDX_OFFSET) + seen_sub_idx.add(sub_idx) + + ret.append( + { + 'sub_bbox': { + 'bbox': subjects[sub_idx]['bbox'], + 'score': subjects[sub_idx]['score'], + }, + 'obj_bboxes': [ + {'score': objects[obj_idx]['score'], 'bbox': objects[obj_idx]['bbox']} + ], + 'sub_idx': sub_idx, + } + ) + + for i in range(len(objects)): + j = i + OBJ_IDX_OFFSET + if j in seen_idx: + continue + seen_idx.add(j) + nearest_dis, nearest_sub_idx = float('inf'), -1 + for k in range(len(subjects)): + dis = bbox_distance(objects[i]['bbox'], subjects[k]['bbox']) + if dis < nearest_dis: + nearest_dis = dis + nearest_sub_idx = k + + for k in range(len(subjects)): + if k != nearest_sub_idx: continue + if k in seen_sub_idx: + for kk in range(len(ret)): + if ret[kk]['sub_idx'] == k: + ret[kk]['obj_bboxes'].append({'score': objects[i]['score'], 'bbox': objects[i]['bbox']}) + break + else: + ret.append( + { + 'sub_bbox': { + 'bbox': subjects[k]['bbox'], + 'score': subjects[k]['score'], + }, + 'obj_bboxes': [ + {'score': objects[i]['score'], 'bbox': objects[i]['bbox']} + ], + 'sub_idx': k, + } + ) + seen_sub_idx.add(k) + seen_idx.add(k) + + + for i in range(len(subjects)): + if i in seen_sub_idx: + continue + ret.append( + { + 'sub_bbox': { + 'bbox': subjects[i]['bbox'], + 'score': subjects[i]['score'], + }, + 'obj_bboxes': [], + 'sub_idx': i, + } + ) + + + return ret + + def get_imgs(self): + with_captions = self.__tie_up_category_by_distance_v3( + 3, 4 + ) + with_footnotes = self.__tie_up_category_by_distance_v3( + 3, CategoryId.ImageFootnote + ) + ret = [] + for v in with_captions: + record = { + 'image_body': v['sub_bbox'], + 'image_caption_list': v['obj_bboxes'], + } + filter_idx = v['sub_idx'] + d = next(filter(lambda x: x['sub_idx'] == filter_idx, with_footnotes)) + record['image_footnote_list'] = d['obj_bboxes'] + ret.append(record) + return ret + + def get_tables(self) -> list: + with_captions = self.__tie_up_category_by_distance_v3( + 5, 6 + ) + with_footnotes = self.__tie_up_category_by_distance_v3( + 5, 7 + ) + ret = [] + for v in with_captions: + record = { + 'table_body': v['sub_bbox'], + 'table_caption_list': v['obj_bboxes'], + } + filter_idx = v['sub_idx'] + d = next(filter(lambda x: x['sub_idx'] == filter_idx, with_footnotes)) + record['table_footnote_list'] = d['obj_bboxes'] + ret.append(record) + return ret + + def get_equations(self) -> tuple[list, list, list]: # 有坐标,也有字 + inline_equations = self.__get_blocks_by_type( + CategoryId.InlineEquation, ['latex'] + ) + interline_equations = self.__get_blocks_by_type( + CategoryId.InterlineEquation_YOLO, ['latex'] + ) + interline_equations_blocks = self.__get_blocks_by_type( + CategoryId.InterlineEquation_Layout + ) + return inline_equations, interline_equations, interline_equations_blocks + + def get_discarded(self) -> list: # 自研模型,只有坐标 + blocks = self.__get_blocks_by_type(CategoryId.Abandon) + return blocks + + def get_text_blocks(self) -> list: # 自研模型搞的,只有坐标,没有字 + blocks = self.__get_blocks_by_type(CategoryId.Text) + return blocks + + def get_title_blocks(self) -> list: # 自研模型,只有坐标,没字 + blocks = self.__get_blocks_by_type(CategoryId.Title) + return blocks + + def get_all_spans(self) -> list: + + def remove_duplicate_spans(spans): + new_spans = [] + for span in spans: + if not any(span == existing_span for existing_span in new_spans): + new_spans.append(span) + return new_spans + + all_spans = [] + layout_dets = self.__page_model_info['layout_dets'] + allow_category_id_list = [3, 5, 13, 14, 15] + """当成span拼接的""" + # 3: 'image', # 图片 + # 5: 'table', # 表格 + # 13: 'inline_equation', # 行内公式 + # 14: 'interline_equation', # 行间公式 + # 15: 'text', # ocr识别文本 + for layout_det in layout_dets: + category_id = layout_det['category_id'] + if category_id in allow_category_id_list: + span = {'bbox': layout_det['bbox'], 'score': layout_det['score']} + if category_id == 3: + span['type'] = ContentType.IMAGE + elif category_id == 5: + # 获取table模型结果 + latex = layout_det.get('latex', None) + html = layout_det.get('html', None) + if latex: + span['latex'] = latex + elif html: + span['html'] = html + span['type'] = ContentType.TABLE + elif category_id == 13: + span['content'] = layout_det['latex'] + span['type'] = ContentType.INLINE_EQUATION + elif category_id == 14: + span['content'] = layout_det['latex'] + span['type'] = ContentType.INTERLINE_EQUATION + elif category_id == 15: + span['content'] = layout_det['text'] + span['type'] = ContentType.TEXT + all_spans.append(span) + return remove_duplicate_spans(all_spans) + + def __get_blocks_by_type( + self, category_type: int, extra_col=None + ) -> list: + if extra_col is None: + extra_col = [] + blocks = [] + layout_dets = self.__page_model_info.get('layout_dets', []) + for item in layout_dets: + category_id = item.get('category_id', -1) + bbox = item.get('bbox', None) + + if category_id == category_type: + block = { + 'bbox': bbox, + 'score': item.get('score'), + } + for col in extra_col: + block[col] = item.get(col, None) + blocks.append(block) + return blocks diff --git a/magic_pdf/dict2md/ocr_mkcontent.py b/mineru/backend/pipeline/pipeline_middle_json_mkcontent.py similarity index 59% rename from magic_pdf/dict2md/ocr_mkcontent.py rename to mineru/backend/pipeline/pipeline_middle_json_mkcontent.py index 997b1832a96be934f93c1c6c680b3de35d79bcc6..3e3c7ae4d8af26ce332102f5011460d09fd05022 100644 --- a/magic_pdf/dict2md/ocr_mkcontent.py +++ b/mineru/backend/pipeline/pipeline_middle_json_mkcontent.py @@ -1,14 +1,10 @@ import re - from loguru import logger -from magic_pdf.config.make_content_config import DropMode, MakeMode -from magic_pdf.config.ocr_content_type import BlockType, ContentType -from magic_pdf.libs.commons import join_path -from magic_pdf.libs.config_reader import get_latex_delimiter_config -from magic_pdf.libs.language import detect_lang -from magic_pdf.libs.markdown_utils import ocr_escape_special_markdown_char -from magic_pdf.post_proc.para_split_v3 import ListLineTag +from mineru.utils.config_reader import get_latex_delimiter_config +from mineru.backend.pipeline.para_split import ListLineTag +from mineru.utils.enum_class import BlockType, ContentType, MakeMode +from mineru.utils.language import detect_lang def __is_hyphen_at_line_end(line): @@ -24,34 +20,7 @@ def __is_hyphen_at_line_end(line): return bool(re.search(r'[A-Za-z]+-\s*$', line)) -def ocr_mk_mm_markdown_with_para_and_pagination(pdf_info_dict: list, - img_buket_path): - markdown_with_para_and_pagination = [] - page_no = 0 - for page_info in pdf_info_dict: - paras_of_layout = page_info.get('para_blocks') - if not paras_of_layout: - markdown_with_para_and_pagination.append({ - 'page_no': - page_no, - 'md_content': - '', - }) - page_no += 1 - continue - page_markdown = ocr_mk_markdown_with_para_core_v2( - paras_of_layout, 'mm', img_buket_path) - markdown_with_para_and_pagination.append({ - 'page_no': - page_no, - 'md_content': - '\n\n'.join(page_markdown) - }) - page_no += 1 - return markdown_with_para_and_pagination - - -def ocr_mk_markdown_with_para_core_v2(paras_of_layout, +def make_blocks_to_markdown(paras_of_layout, mode, img_buket_path='', ): @@ -59,64 +28,69 @@ def ocr_mk_markdown_with_para_core_v2(paras_of_layout, for para_block in paras_of_layout: para_text = '' para_type = para_block['type'] - if para_type in [BlockType.Text, BlockType.List, BlockType.Index]: + if para_type in [BlockType.TEXT, BlockType.LIST, BlockType.INDEX]: para_text = merge_para_with_text(para_block) - elif para_type == BlockType.Title: + elif para_type == BlockType.TITLE: title_level = get_title_level(para_block) para_text = f'{"#" * title_level} {merge_para_with_text(para_block)}' - elif para_type == BlockType.InterlineEquation: - para_text = merge_para_with_text(para_block) - elif para_type == BlockType.Image: - if mode == 'nlp': + elif para_type == BlockType.INTERLINE_EQUATION: + if len(para_block['lines']) == 0 or len(para_block['lines'][0]['spans']) == 0: continue - elif mode == 'mm': + if para_block['lines'][0]['spans'][0].get('content', ''): + para_text = merge_para_with_text(para_block) + else: + para_text += f"![]({img_buket_path}/{para_block['lines'][0]['spans'][0]['image_path']})" + elif para_type == BlockType.IMAGE: + if mode == MakeMode.NLP_MD: + continue + elif mode == MakeMode.MM_MD: # 检测是否存在图片脚注 - has_image_footnote = any(block['type'] == BlockType.ImageFootnote for block in para_block['blocks']) + has_image_footnote = any(block['type'] == BlockType.IMAGE_FOOTNOTE for block in para_block['blocks']) # 如果存在图片脚注,则将图片脚注拼接到图片正文后面 if has_image_footnote: for block in para_block['blocks']: # 1st.拼image_caption - if block['type'] == BlockType.ImageCaption: + if block['type'] == BlockType.IMAGE_CAPTION: para_text += merge_para_with_text(block) + ' \n' for block in para_block['blocks']: # 2nd.拼image_body - if block['type'] == BlockType.ImageBody: + if block['type'] == BlockType.IMAGE_BODY: for line in block['lines']: for span in line['spans']: - if span['type'] == ContentType.Image: + if span['type'] == ContentType.IMAGE: if span.get('image_path', ''): para_text += f"![]({img_buket_path}/{span['image_path']})" for block in para_block['blocks']: # 3rd.拼image_footnote - if block['type'] == BlockType.ImageFootnote: + if block['type'] == BlockType.IMAGE_FOOTNOTE: para_text += ' \n' + merge_para_with_text(block) else: for block in para_block['blocks']: # 1st.拼image_body - if block['type'] == BlockType.ImageBody: + if block['type'] == BlockType.IMAGE_BODY: for line in block['lines']: for span in line['spans']: - if span['type'] == ContentType.Image: + if span['type'] == ContentType.IMAGE: if span.get('image_path', ''): para_text += f"![]({img_buket_path}/{span['image_path']})" for block in para_block['blocks']: # 2nd.拼image_caption - if block['type'] == BlockType.ImageCaption: + if block['type'] == BlockType.IMAGE_CAPTION: para_text += ' \n' + merge_para_with_text(block) - elif para_type == BlockType.Table: - if mode == 'nlp': + elif para_type == BlockType.TABLE: + if mode == MakeMode.NLP_MD: continue - elif mode == 'mm': + elif mode == MakeMode.MM_MD: for block in para_block['blocks']: # 1st.拼table_caption - if block['type'] == BlockType.TableCaption: + if block['type'] == BlockType.TABLE_CAPTION: para_text += merge_para_with_text(block) + ' \n' for block in para_block['blocks']: # 2nd.拼table_body - if block['type'] == BlockType.TableBody: + if block['type'] == BlockType.TABLE_BODY: for line in block['lines']: for span in line['spans']: - if span['type'] == ContentType.Table: + if span['type'] == ContentType.TABLE: # if processed by table model if span.get('html', ''): para_text += f"\n{span['html']}\n" elif span.get('image_path', ''): para_text += f"![]({img_buket_path}/{span['image_path']})" for block in para_block['blocks']: # 3rd.拼table_footnote - if block['type'] == BlockType.TableFootnote: + if block['type'] == BlockType.TABLE_FOOTNOTE: para_text += '\n' + merge_para_with_text(block) + ' ' if para_text.strip() == '': @@ -128,19 +102,6 @@ def ocr_mk_markdown_with_para_core_v2(paras_of_layout, return page_markdown -def detect_language(text): - en_pattern = r'[a-zA-Z]+' - en_matches = re.findall(en_pattern, text) - en_length = sum(len(match) for match in en_matches) - if len(text) > 0: - if en_length / len(text) >= 0.5: - return 'en' - else: - return 'unknown' - else: - return 'empty' - - def full_to_half(text: str) -> str: """Convert full-width characters to half-width characters using code point manipulation. @@ -178,7 +139,7 @@ def merge_para_with_text(para_block): block_text = '' for line in para_block['lines']: for span in line['spans']: - if span['type'] in [ContentType.Text]: + if span['type'] in [ContentType.TEXT]: span['content'] = full_to_half(span['content']) block_text += span['content'] block_lang = detect_lang(block_text) @@ -193,11 +154,11 @@ def merge_para_with_text(para_block): span_type = span['type'] content = '' - if span_type == ContentType.Text: - content = ocr_escape_special_markdown_char(span['content']) - elif span_type == ContentType.InlineEquation: + if span_type == ContentType.TEXT: + content = escape_special_markdown_char(span['content']) + elif span_type == ContentType.INLINE_EQUATION: content = f"{inline_left_delimiter}{span['content']}{inline_right_delimiter}" - elif span_type == ContentType.InterlineEquation: + elif span_type == ContentType.INTERLINE_EQUATION: content = f"\n{display_left_delimiter}\n{span['content']}\n{display_right_delimiter}\n" content = content.strip() @@ -206,36 +167,34 @@ def merge_para_with_text(para_block): langs = ['zh', 'ja', 'ko'] # logger.info(f'block_lang: {block_lang}, content: {content}') if block_lang in langs: # 中文/日语/韩文语境下,换行不需要空格分隔,但是如果是行内公式结尾,还是要加空格 - if j == len(line['spans']) - 1 and span_type not in [ContentType.InlineEquation]: + if j == len(line['spans']) - 1 and span_type not in [ContentType.INLINE_EQUATION]: para_text += content else: para_text += f'{content} ' else: - if span_type in [ContentType.Text, ContentType.InlineEquation]: + if span_type in [ContentType.TEXT, ContentType.INLINE_EQUATION]: # 如果span是line的最后一个且末尾带有-连字符,那么末尾不应该加空格,同时应该把-删除 - if j == len(line['spans'])-1 and span_type == ContentType.Text and __is_hyphen_at_line_end(content): + if j == len(line['spans'])-1 and span_type == ContentType.TEXT and __is_hyphen_at_line_end(content): para_text += content[:-1] else: # 西方文本语境下 content间需要空格分隔 para_text += f'{content} ' - elif span_type == ContentType.InterlineEquation: + elif span_type == ContentType.INTERLINE_EQUATION: para_text += content else: continue - # 连写字符拆分 - # para_text = __replace_ligatures(para_text) return para_text -def para_to_standard_format_v2(para_block, img_buket_path, page_idx, drop_reason=None): +def make_blocks_to_content_list(para_block, img_buket_path, page_idx): para_type = para_block['type'] para_content = {} - if para_type in [BlockType.Text, BlockType.List, BlockType.Index]: + if para_type in [BlockType.TEXT, BlockType.LIST, BlockType.INDEX]: para_content = { 'type': 'text', 'text': merge_para_with_text(para_block), } - elif para_type == BlockType.Title: + elif para_type == BlockType.TITLE: para_content = { 'type': 'text', 'text': merge_para_with_text(para_block), @@ -243,32 +202,36 @@ def para_to_standard_format_v2(para_block, img_buket_path, page_idx, drop_reason title_level = get_title_level(para_block) if title_level != 0: para_content['text_level'] = title_level - elif para_type == BlockType.InterlineEquation: + elif para_type == BlockType.INTERLINE_EQUATION: + if len(para_block['lines']) == 0 or len(para_block['lines'][0]['spans']) == 0: + return None para_content = { 'type': 'equation', - 'text': merge_para_with_text(para_block), - 'text_format': 'latex', + 'img_path': f"{img_buket_path}/{para_block['lines'][0]['spans'][0].get('image_path', '')}", } - elif para_type == BlockType.Image: + if para_block['lines'][0]['spans'][0].get('content', ''): + para_content['text'] = merge_para_with_text(para_block) + para_content['text_format'] = 'latex' + elif para_type == BlockType.IMAGE: para_content = {'type': 'image', 'img_path': '', 'img_caption': [], 'img_footnote': []} for block in para_block['blocks']: - if block['type'] == BlockType.ImageBody: + if block['type'] == BlockType.IMAGE_BODY: for line in block['lines']: for span in line['spans']: - if span['type'] == ContentType.Image: + if span['type'] == ContentType.IMAGE: if span.get('image_path', ''): - para_content['img_path'] = join_path(img_buket_path, span['image_path']) - if block['type'] == BlockType.ImageCaption: + para_content['img_path'] = f"{img_buket_path}/{span['image_path']}" + if block['type'] == BlockType.IMAGE_CAPTION: para_content['img_caption'].append(merge_para_with_text(block)) - if block['type'] == BlockType.ImageFootnote: + if block['type'] == BlockType.IMAGE_FOOTNOTE: para_content['img_footnote'].append(merge_para_with_text(block)) - elif para_type == BlockType.Table: + elif para_type == BlockType.TABLE: para_content = {'type': 'table', 'img_path': '', 'table_caption': [], 'table_footnote': []} for block in para_block['blocks']: - if block['type'] == BlockType.TableBody: + if block['type'] == BlockType.TABLE_BODY: for line in block['lines']: for span in line['spans']: - if span['type'] == ContentType.Table: + if span['type'] == ContentType.TABLE: if span.get('latex', ''): para_content['table_body'] = f"{span['latex']}" @@ -276,71 +239,44 @@ def para_to_standard_format_v2(para_block, img_buket_path, page_idx, drop_reason para_content['table_body'] = f"{span['html']}" if span.get('image_path', ''): - para_content['img_path'] = join_path(img_buket_path, span['image_path']) + para_content['img_path'] = f"{img_buket_path}/{span['image_path']}" - if block['type'] == BlockType.TableCaption: + if block['type'] == BlockType.TABLE_CAPTION: para_content['table_caption'].append(merge_para_with_text(block)) - if block['type'] == BlockType.TableFootnote: + if block['type'] == BlockType.TABLE_FOOTNOTE: para_content['table_footnote'].append(merge_para_with_text(block)) para_content['page_idx'] = page_idx - if drop_reason is not None: - para_content['drop_reason'] = drop_reason - return para_content def union_make(pdf_info_dict: list, make_mode: str, - drop_mode: str, img_buket_path: str = '', ): output_content = [] for page_info in pdf_info_dict: - drop_reason_flag = False - drop_reason = None - if page_info.get('need_drop', False): - drop_reason = page_info.get('drop_reason') - if drop_mode == DropMode.NONE: - pass - elif drop_mode == DropMode.NONE_WITH_REASON: - drop_reason_flag = True - elif drop_mode == DropMode.WHOLE_PDF: - raise Exception((f'drop_mode is {DropMode.WHOLE_PDF} ,' - f'drop_reason is {drop_reason}')) - elif drop_mode == DropMode.SINGLE_PAGE: - logger.warning((f'drop_mode is {DropMode.SINGLE_PAGE} ,' - f'drop_reason is {drop_reason}')) - continue - else: - raise Exception('drop_mode can not be null') - paras_of_layout = page_info.get('para_blocks') page_idx = page_info.get('page_idx') if not paras_of_layout: continue - if make_mode == MakeMode.MM_MD: - page_markdown = ocr_mk_markdown_with_para_core_v2( - paras_of_layout, 'mm', img_buket_path) + if make_mode in [MakeMode.MM_MD, MakeMode.NLP_MD]: + page_markdown = make_blocks_to_markdown(paras_of_layout, make_mode, img_buket_path) output_content.extend(page_markdown) - elif make_mode == MakeMode.NLP_MD: - page_markdown = ocr_mk_markdown_with_para_core_v2( - paras_of_layout, 'nlp') - output_content.extend(page_markdown) - elif make_mode == MakeMode.STANDARD_FORMAT: + elif make_mode == MakeMode.CONTENT_LIST: for para_block in paras_of_layout: - if drop_reason_flag: - para_content = para_to_standard_format_v2( - para_block, img_buket_path, page_idx) - else: - para_content = para_to_standard_format_v2( - para_block, img_buket_path, page_idx) - output_content.append(para_content) + para_content = make_blocks_to_content_list(para_block, img_buket_path, page_idx) + if para_content: + output_content.append(para_content) + if make_mode in [MakeMode.MM_MD, MakeMode.NLP_MD]: return '\n\n'.join(output_content) - elif make_mode == MakeMode.STANDARD_FORMAT: + elif make_mode == MakeMode.CONTENT_LIST: return output_content + else: + logger.error(f"Unsupported make mode: {make_mode}") + return None def get_title_level(block): @@ -349,4 +285,15 @@ def get_title_level(block): title_level = 4 elif title_level < 1: title_level = 0 - return title_level \ No newline at end of file + return title_level + + +def escape_special_markdown_char(content): + """ + 转义正文里对markdown语法有特殊意义的字符 + """ + special_chars = ["*", "`", "~", "$"] + for char in special_chars: + content = content.replace(char, "\\" + char) + + return content \ No newline at end of file diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/__init__.py b/mineru/backend/vlm/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/__init__.py rename to mineru/backend/vlm/__init__.py diff --git a/mineru/backend/vlm/base_predictor.py b/mineru/backend/vlm/base_predictor.py new file mode 100644 index 0000000000000000000000000000000000000000..f65b4a482cc8a84154c50e8d5acc2a22a91a7df4 --- /dev/null +++ b/mineru/backend/vlm/base_predictor.py @@ -0,0 +1,186 @@ +import asyncio +from abc import ABC, abstractmethod +from typing import AsyncIterable, Iterable, List, Optional, Union + +DEFAULT_SYSTEM_PROMPT = ( + "A conversation between a user and an LLM-based AI assistant. The assistant gives helpful and honest answers." +) +DEFAULT_USER_PROMPT = "Document Parsing:" +DEFAULT_TEMPERATURE = 0.0 +DEFAULT_TOP_P = 0.8 +DEFAULT_TOP_K = 20 +DEFAULT_REPETITION_PENALTY = 1.0 +DEFAULT_PRESENCE_PENALTY = 0.0 +DEFAULT_NO_REPEAT_NGRAM_SIZE = 100 +DEFAULT_MAX_NEW_TOKENS = 16384 + + +class BasePredictor(ABC): + system_prompt = DEFAULT_SYSTEM_PROMPT + + def __init__( + self, + temperature: float = DEFAULT_TEMPERATURE, + top_p: float = DEFAULT_TOP_P, + top_k: int = DEFAULT_TOP_K, + repetition_penalty: float = DEFAULT_REPETITION_PENALTY, + presence_penalty: float = DEFAULT_PRESENCE_PENALTY, + no_repeat_ngram_size: int = DEFAULT_NO_REPEAT_NGRAM_SIZE, + max_new_tokens: int = DEFAULT_MAX_NEW_TOKENS, + ) -> None: + self.temperature = temperature + self.top_p = top_p + self.top_k = top_k + self.repetition_penalty = repetition_penalty + self.presence_penalty = presence_penalty + self.no_repeat_ngram_size = no_repeat_ngram_size + self.max_new_tokens = max_new_tokens + + @abstractmethod + def predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> str: ... + + @abstractmethod + def batch_predict( + self, + images: List[str] | List[bytes], + prompts: Union[List[str], str] = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> List[str]: ... + + @abstractmethod + def stream_predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> Iterable[str]: ... + + async def aio_predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> str: + return await asyncio.to_thread( + self.predict, + image, + prompt, + temperature, + top_p, + top_k, + repetition_penalty, + presence_penalty, + no_repeat_ngram_size, + max_new_tokens, + ) + + async def aio_batch_predict( + self, + images: List[str] | List[bytes], + prompts: Union[List[str], str] = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> List[str]: + return await asyncio.to_thread( + self.batch_predict, + images, + prompts, + temperature, + top_p, + top_k, + repetition_penalty, + presence_penalty, + no_repeat_ngram_size, + max_new_tokens, + ) + + async def aio_stream_predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> AsyncIterable[str]: + queue = asyncio.Queue() + loop = asyncio.get_running_loop() + + def synced_predict(): + for chunk in self.stream_predict( + image=image, + prompt=prompt, + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + ): + asyncio.run_coroutine_threadsafe(queue.put(chunk), loop) + asyncio.run_coroutine_threadsafe(queue.put(None), loop) + + asyncio.create_task( + asyncio.to_thread(synced_predict), + ) + + while True: + chunk = await queue.get() + if chunk is None: + return + assert isinstance(chunk, str) + yield chunk + + def build_prompt(self, prompt: str) -> str: + if prompt.startswith("<|im_start|>"): + return prompt + if not prompt: + prompt = DEFAULT_USER_PROMPT + + return f"<|im_start|>system\n{self.system_prompt}<|im_end|><|im_start|>user\n\n{prompt}<|im_end|><|im_start|>assistant\n" + # Modify here. We add <|box_start|> at the end of the prompt to force the model to generate bounding box. + # if "Document OCR" in prompt: + # return f"<|im_start|>system\n{self.system_prompt}<|im_end|><|im_start|>user\n\n{prompt}<|im_end|><|im_start|>assistant\n<|box_start|>" + # else: + # return f"<|im_start|>system\n{self.system_prompt}<|im_end|><|im_start|>user\n\n{prompt}<|im_end|><|im_start|>assistant\n" + + def close(self): + pass diff --git a/mineru/backend/vlm/hf_predictor.py b/mineru/backend/vlm/hf_predictor.py new file mode 100644 index 0000000000000000000000000000000000000000..f3cd69d55e549d45a132ec541c54f756f078982e --- /dev/null +++ b/mineru/backend/vlm/hf_predictor.py @@ -0,0 +1,211 @@ +from io import BytesIO +from typing import Iterable, List, Optional, Union + +import torch +from PIL import Image +from tqdm import tqdm +from transformers import AutoTokenizer, BitsAndBytesConfig + +from ...model.vlm_hf_model import Mineru2QwenForCausalLM +from ...model.vlm_hf_model.image_processing_mineru2 import process_images +from .base_predictor import ( + DEFAULT_MAX_NEW_TOKENS, + DEFAULT_NO_REPEAT_NGRAM_SIZE, + DEFAULT_PRESENCE_PENALTY, + DEFAULT_REPETITION_PENALTY, + DEFAULT_TEMPERATURE, + DEFAULT_TOP_K, + DEFAULT_TOP_P, + BasePredictor, +) +from .utils import load_resource + + +class HuggingfacePredictor(BasePredictor): + def __init__( + self, + model_path: str, + device_map="auto", + device="cuda", + torch_dtype="auto", + load_in_8bit=False, + load_in_4bit=False, + use_flash_attn=False, + temperature: float = DEFAULT_TEMPERATURE, + top_p: float = DEFAULT_TOP_P, + top_k: int = DEFAULT_TOP_K, + repetition_penalty: float = DEFAULT_REPETITION_PENALTY, + presence_penalty: float = DEFAULT_PRESENCE_PENALTY, + no_repeat_ngram_size: int = DEFAULT_NO_REPEAT_NGRAM_SIZE, + max_new_tokens: int = DEFAULT_MAX_NEW_TOKENS, + **kwargs, + ): + super().__init__( + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + ) + + kwargs = {"device_map": device_map, **kwargs} + + if device != "cuda": + kwargs["device_map"] = {"": device} + + if load_in_8bit: + kwargs["load_in_8bit"] = True + elif load_in_4bit: + kwargs["load_in_4bit"] = True + kwargs["quantization_config"] = BitsAndBytesConfig( + load_in_4bit=True, + bnb_4bit_compute_dtype=torch.float16, + bnb_4bit_use_double_quant=True, + bnb_4bit_quant_type="nf4", + ) + else: + kwargs["torch_dtype"] = torch_dtype + + if use_flash_attn: + kwargs["attn_implementation"] = "flash_attention_2" + + self.tokenizer = AutoTokenizer.from_pretrained(model_path) + self.model = Mineru2QwenForCausalLM.from_pretrained( + model_path, + low_cpu_mem_usage=True, + **kwargs, + ) + setattr(self.model.config, "_name_or_path", model_path) + self.model.eval() + + vision_tower = self.model.get_model().vision_tower + if device_map != "auto": + vision_tower.to(device=device_map, dtype=self.model.dtype) + + self.image_processor = vision_tower.image_processor + self.eos_token_id = self.model.config.eos_token_id + + def predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + **kwargs, + ) -> str: + prompt = self.build_prompt(prompt) + + if temperature is None: + temperature = self.temperature + if top_p is None: + top_p = self.top_p + if top_k is None: + top_k = self.top_k + if repetition_penalty is None: + repetition_penalty = self.repetition_penalty + if no_repeat_ngram_size is None: + no_repeat_ngram_size = self.no_repeat_ngram_size + if max_new_tokens is None: + max_new_tokens = self.max_new_tokens + + do_sample = (temperature > 0.0) and (top_k > 1) + + generate_kwargs = { + "repetition_penalty": repetition_penalty, + "no_repeat_ngram_size": no_repeat_ngram_size, + "max_new_tokens": max_new_tokens, + "do_sample": do_sample, + } + if do_sample: + generate_kwargs["temperature"] = temperature + generate_kwargs["top_p"] = top_p + generate_kwargs["top_k"] = top_k + + if isinstance(image, str): + image = load_resource(image) + + image_obj = Image.open(BytesIO(image)) + image_tensor = process_images([image_obj], self.image_processor, self.model.config) + image_tensor = image_tensor[0].unsqueeze(0) + image_tensor = image_tensor.to(device=self.model.device, dtype=self.model.dtype) + image_sizes = [[*image_obj.size]] + + input_ids = self.tokenizer(prompt, return_tensors="pt").input_ids + input_ids = input_ids.to(device=self.model.device) + + with torch.inference_mode(): + output_ids = self.model.generate( + input_ids, + images=image_tensor, + image_sizes=image_sizes, + use_cache=True, + **generate_kwargs, + **kwargs, + ) + + # Remove the last token if it is the eos_token_id + if len(output_ids[0]) > 0 and output_ids[0, -1] == self.eos_token_id: + output_ids = output_ids[:, :-1] + + output = self.tokenizer.batch_decode( + output_ids, + skip_special_tokens=False, + )[0].strip() + + return output + + def batch_predict( + self, + images: List[str] | List[bytes], + prompts: Union[List[str], str] = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, # not supported by hf + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + **kwargs, + ) -> List[str]: + if not isinstance(prompts, list): + prompts = [prompts] * len(images) + + assert len(prompts) == len(images), "Length of prompts and images must match." + + outputs = [] + for prompt, image in tqdm(zip(prompts, images), total=len(images), desc="Predict"): + output = self.predict( + image, + prompt, + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + **kwargs, + ) + outputs.append(output) + return outputs + + def stream_predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> Iterable[str]: + raise NotImplementedError("Streaming is not supported yet.") diff --git a/mineru/backend/vlm/predictor.py b/mineru/backend/vlm/predictor.py new file mode 100644 index 0000000000000000000000000000000000000000..f4976ec9b542faf5002f7da83fbd3ec70ef8b35b --- /dev/null +++ b/mineru/backend/vlm/predictor.py @@ -0,0 +1,111 @@ +# Copyright (c) Opendatalab. All rights reserved. + +import time + +from loguru import logger + +from .base_predictor import ( + DEFAULT_MAX_NEW_TOKENS, + DEFAULT_NO_REPEAT_NGRAM_SIZE, + DEFAULT_PRESENCE_PENALTY, + DEFAULT_REPETITION_PENALTY, + DEFAULT_TEMPERATURE, + DEFAULT_TOP_K, + DEFAULT_TOP_P, + BasePredictor, +) +from .sglang_client_predictor import SglangClientPredictor + +hf_loaded = False +try: + from .hf_predictor import HuggingfacePredictor + + hf_loaded = True +except ImportError as e: + logger.warning("hf is not installed. If you are not using transformers, you can ignore this warning.") + +engine_loaded = False +try: + from sglang.srt.server_args import ServerArgs + + from .sglang_engine_predictor import SglangEnginePredictor + + engine_loaded = True +except Exception as e: + logger.warning("sglang is not installed. If you are not using sglang, you can ignore this warning.") + + +def get_predictor( + backend: str = "sglang-client", + model_path: str | None = None, + server_url: str | None = None, + temperature: float = DEFAULT_TEMPERATURE, + top_p: float = DEFAULT_TOP_P, + top_k: int = DEFAULT_TOP_K, + repetition_penalty: float = DEFAULT_REPETITION_PENALTY, + presence_penalty: float = DEFAULT_PRESENCE_PENALTY, + no_repeat_ngram_size: int = DEFAULT_NO_REPEAT_NGRAM_SIZE, + max_new_tokens: int = DEFAULT_MAX_NEW_TOKENS, + http_timeout: int = 600, + **kwargs, +) -> BasePredictor: + start_time = time.time() + + if backend == "transformers": + if not model_path: + raise ValueError("model_path must be provided for transformers backend.") + if not hf_loaded: + raise ImportError( + "transformers is not installed, so huggingface backend cannot be used. " + "If you need to use huggingface backend, please install transformers first." + ) + predictor = HuggingfacePredictor( + model_path=model_path, + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + **kwargs, + ) + elif backend == "sglang-engine": + if not model_path: + raise ValueError("model_path must be provided for sglang-engine backend.") + if not engine_loaded: + raise ImportError( + "sglang is not installed, so sglang-engine backend cannot be used. " + "If you need to use sglang-engine backend for inference, " + "please install sglang[all]==0.4.7 or a newer version." + ) + predictor = SglangEnginePredictor( + server_args=ServerArgs(model_path, **kwargs), + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + ) + elif backend == "sglang-client": + if not server_url: + raise ValueError("server_url must be provided for sglang-client backend.") + predictor = SglangClientPredictor( + server_url=server_url, + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + http_timeout=http_timeout, + ) + else: + raise ValueError(f"Unsupported backend: {backend}. Supports: transformers, sglang-engine, sglang-client.") + + elapsed = round(time.time() - start_time, 2) + logger.info(f"get_predictor cost: {elapsed}s") + return predictor diff --git a/mineru/backend/vlm/sglang_client_predictor.py b/mineru/backend/vlm/sglang_client_predictor.py new file mode 100644 index 0000000000000000000000000000000000000000..e886184cd7eea6522623c9215ee04284e95130ea --- /dev/null +++ b/mineru/backend/vlm/sglang_client_predictor.py @@ -0,0 +1,443 @@ +import asyncio +import json +import re +from base64 import b64encode +from typing import AsyncIterable, Iterable, List, Optional, Set, Tuple, Union + +import httpx + +from .base_predictor import ( + DEFAULT_MAX_NEW_TOKENS, + DEFAULT_NO_REPEAT_NGRAM_SIZE, + DEFAULT_PRESENCE_PENALTY, + DEFAULT_REPETITION_PENALTY, + DEFAULT_TEMPERATURE, + DEFAULT_TOP_K, + DEFAULT_TOP_P, + BasePredictor, +) +from .utils import aio_load_resource, load_resource + + +class SglangClientPredictor(BasePredictor): + def __init__( + self, + server_url: str, + temperature: float = DEFAULT_TEMPERATURE, + top_p: float = DEFAULT_TOP_P, + top_k: int = DEFAULT_TOP_K, + repetition_penalty: float = DEFAULT_REPETITION_PENALTY, + presence_penalty: float = DEFAULT_PRESENCE_PENALTY, + no_repeat_ngram_size: int = DEFAULT_NO_REPEAT_NGRAM_SIZE, + max_new_tokens: int = DEFAULT_MAX_NEW_TOKENS, + http_timeout: int = 600, + ) -> None: + super().__init__( + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + ) + self.http_timeout = http_timeout + + base_url = self.get_base_url(server_url) + self.check_server_health(base_url) + self.model_path = self.get_model_path(base_url) + self.server_url = f"{base_url}/generate" + + @staticmethod + def get_base_url(server_url: str) -> str: + matched = re.match(r"^(https?://[^/]+)", server_url) + if not matched: + raise ValueError(f"Invalid server URL: {server_url}") + return matched.group(1) + + def check_server_health(self, base_url: str): + try: + response = httpx.get(f"{base_url}/health_generate", timeout=self.http_timeout) + except httpx.ConnectError: + raise RuntimeError(f"Failed to connect to server {base_url}. Please check if the server is running.") + if response.status_code != 200: + raise RuntimeError( + f"Server {base_url} is not healthy. Status code: {response.status_code}, response body: {response.text}" + ) + + def get_model_path(self, base_url: str) -> str: + try: + response = httpx.get(f"{base_url}/get_model_info", timeout=self.http_timeout) + except httpx.ConnectError: + raise RuntimeError(f"Failed to connect to server {base_url}. Please check if the server is running.") + if response.status_code != 200: + raise RuntimeError( + f"Failed to get model info from {base_url}. Status code: {response.status_code}, response body: {response.text}" + ) + return response.json()["model_path"] + + def build_sampling_params( + self, + temperature: Optional[float], + top_p: Optional[float], + top_k: Optional[int], + repetition_penalty: Optional[float], + presence_penalty: Optional[float], + no_repeat_ngram_size: Optional[int], + max_new_tokens: Optional[int], + ) -> dict: + if temperature is None: + temperature = self.temperature + if top_p is None: + top_p = self.top_p + if top_k is None: + top_k = self.top_k + if repetition_penalty is None: + repetition_penalty = self.repetition_penalty + if presence_penalty is None: + presence_penalty = self.presence_penalty + if no_repeat_ngram_size is None: + no_repeat_ngram_size = self.no_repeat_ngram_size + if max_new_tokens is None: + max_new_tokens = self.max_new_tokens + + # see SamplingParams for more details + return { + "temperature": temperature, + "top_p": top_p, + "top_k": top_k, + "repetition_penalty": repetition_penalty, + "presence_penalty": presence_penalty, + "custom_params": { + "no_repeat_ngram_size": no_repeat_ngram_size, + }, + "max_new_tokens": max_new_tokens, + "skip_special_tokens": False, + } + + def build_request_body( + self, + image: bytes, + prompt: str, + sampling_params: dict, + ) -> dict: + image_base64 = b64encode(image).decode("utf-8") + return { + "text": prompt, + "image_data": image_base64, + "sampling_params": sampling_params, + "modalities": ["image"], + } + + def predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> str: + prompt = self.build_prompt(prompt) + + sampling_params = self.build_sampling_params( + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + ) + + if isinstance(image, str): + image = load_resource(image) + + request_body = self.build_request_body(image, prompt, sampling_params) + response = httpx.post(self.server_url, json=request_body, timeout=self.http_timeout) + response_body = response.json() + return response_body["text"] + + def batch_predict( + self, + images: List[str] | List[bytes], + prompts: Union[List[str], str] = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + max_concurrency: int = 100, + ) -> List[str]: + try: + loop = asyncio.get_running_loop() + except RuntimeError: + loop = None + + task = self.aio_batch_predict( + images=images, + prompts=prompts, + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + max_concurrency=max_concurrency, + ) + + if loop is not None: + return loop.run_until_complete(task) + else: + return asyncio.run(task) + + def stream_predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> Iterable[str]: + prompt = self.build_prompt(prompt) + + sampling_params = self.build_sampling_params( + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + ) + + if isinstance(image, str): + image = load_resource(image) + + request_body = self.build_request_body(image, prompt, sampling_params) + request_body["stream"] = True + + with httpx.stream( + "POST", + self.server_url, + json=request_body, + timeout=self.http_timeout, + ) as response: + pos = 0 + for chunk in response.iter_lines(): + if not (chunk or "").startswith("data:"): + continue + if chunk == "data: [DONE]": + break + data = json.loads(chunk[5:].strip("\n")) + chunk_text = data["text"][pos:] + # meta_info = data["meta_info"] + pos += len(chunk_text) + yield chunk_text + + async def aio_predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + async_client: Optional[httpx.AsyncClient] = None, + ) -> str: + prompt = self.build_prompt(prompt) + + sampling_params = self.build_sampling_params( + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + ) + + if isinstance(image, str): + image = await aio_load_resource(image) + + request_body = self.build_request_body(image, prompt, sampling_params) + + if async_client is None: + async with httpx.AsyncClient(timeout=self.http_timeout) as client: + response = await client.post(self.server_url, json=request_body) + response_body = response.json() + else: + response = await async_client.post(self.server_url, json=request_body) + response_body = response.json() + + return response_body["text"] + + async def aio_batch_predict( + self, + images: List[str] | List[bytes], + prompts: Union[List[str], str] = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + max_concurrency: int = 100, + ) -> List[str]: + if not isinstance(prompts, list): + prompts = [prompts] * len(images) + + assert len(prompts) == len(images), "Length of prompts and images must match." + + semaphore = asyncio.Semaphore(max_concurrency) + outputs = [""] * len(images) + + async def predict_with_semaphore( + idx: int, + image: str | bytes, + prompt: str, + async_client: httpx.AsyncClient, + ): + async with semaphore: + output = await self.aio_predict( + image=image, + prompt=prompt, + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + async_client=async_client, + ) + outputs[idx] = output + + async with httpx.AsyncClient(timeout=self.http_timeout) as client: + tasks = [] + for idx, (prompt, image) in enumerate(zip(prompts, images)): + tasks.append(predict_with_semaphore(idx, image, prompt, client)) + await asyncio.gather(*tasks) + + return outputs + + async def aio_batch_predict_as_iter( + self, + images: List[str] | List[bytes], + prompts: Union[List[str], str] = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + max_concurrency: int = 100, + ) -> AsyncIterable[Tuple[int, str]]: + if not isinstance(prompts, list): + prompts = [prompts] * len(images) + + assert len(prompts) == len(images), "Length of prompts and images must match." + + semaphore = asyncio.Semaphore(max_concurrency) + + async def predict_with_semaphore( + idx: int, + image: str | bytes, + prompt: str, + async_client: httpx.AsyncClient, + ): + async with semaphore: + output = await self.aio_predict( + image=image, + prompt=prompt, + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + async_client=async_client, + ) + return (idx, output) + + async with httpx.AsyncClient(timeout=self.http_timeout) as client: + pending: Set[asyncio.Task[Tuple[int, str]]] = set() + + for idx, (prompt, image) in enumerate(zip(prompts, images)): + pending.add( + asyncio.create_task( + predict_with_semaphore(idx, image, prompt, client), + ) + ) + + while len(pending) > 0: + done, pending = await asyncio.wait( + pending, + return_when=asyncio.FIRST_COMPLETED, + ) + for task in done: + yield task.result() + + async def aio_stream_predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> AsyncIterable[str]: + prompt = self.build_prompt(prompt) + + sampling_params = self.build_sampling_params( + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + ) + + if isinstance(image, str): + image = await aio_load_resource(image) + + request_body = self.build_request_body(image, prompt, sampling_params) + request_body["stream"] = True + + async with httpx.AsyncClient(timeout=self.http_timeout) as client: + async with client.stream( + "POST", + self.server_url, + json=request_body, + ) as response: + pos = 0 + async for chunk in response.aiter_lines(): + if not (chunk or "").startswith("data:"): + continue + if chunk == "data: [DONE]": + break + data = json.loads(chunk[5:].strip("\n")) + chunk_text = data["text"][pos:] + # meta_info = data["meta_info"] + pos += len(chunk_text) + yield chunk_text diff --git a/mineru/backend/vlm/sglang_engine_predictor.py b/mineru/backend/vlm/sglang_engine_predictor.py new file mode 100644 index 0000000000000000000000000000000000000000..0a167c633ae47b1533810c22e76c5c63736ecb96 --- /dev/null +++ b/mineru/backend/vlm/sglang_engine_predictor.py @@ -0,0 +1,246 @@ +from base64 import b64encode +from typing import AsyncIterable, Iterable, List, Optional, Union + +from sglang.srt.server_args import ServerArgs + +from ...model.vlm_sglang_model.engine import BatchEngine +from .base_predictor import ( + DEFAULT_MAX_NEW_TOKENS, + DEFAULT_NO_REPEAT_NGRAM_SIZE, + DEFAULT_PRESENCE_PENALTY, + DEFAULT_REPETITION_PENALTY, + DEFAULT_TEMPERATURE, + DEFAULT_TOP_K, + DEFAULT_TOP_P, + BasePredictor, +) + + +class SglangEnginePredictor(BasePredictor): + def __init__( + self, + server_args: ServerArgs, + temperature: float = DEFAULT_TEMPERATURE, + top_p: float = DEFAULT_TOP_P, + top_k: int = DEFAULT_TOP_K, + repetition_penalty: float = DEFAULT_REPETITION_PENALTY, + presence_penalty: float = DEFAULT_PRESENCE_PENALTY, + no_repeat_ngram_size: int = DEFAULT_NO_REPEAT_NGRAM_SIZE, + max_new_tokens: int = DEFAULT_MAX_NEW_TOKENS, + ) -> None: + super().__init__( + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + ) + self.engine = BatchEngine(server_args=server_args) + + def load_image_string(self, image: str | bytes) -> str: + if not isinstance(image, (str, bytes)): + raise ValueError("Image must be a string or bytes.") + if isinstance(image, bytes): + return b64encode(image).decode("utf-8") + if image.startswith("file://"): + return image[len("file://") :] + return image + + def predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> str: + return self.batch_predict( + [image], # type: ignore + [prompt], + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + )[0] + + def batch_predict( + self, + images: List[str] | List[bytes], + prompts: Union[List[str], str] = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> List[str]: + + if not isinstance(prompts, list): + prompts = [prompts] * len(images) + + assert len(prompts) == len(images), "Length of prompts and images must match." + prompts = [self.build_prompt(prompt) for prompt in prompts] + + if temperature is None: + temperature = self.temperature + if top_p is None: + top_p = self.top_p + if top_k is None: + top_k = self.top_k + if repetition_penalty is None: + repetition_penalty = self.repetition_penalty + if presence_penalty is None: + presence_penalty = self.presence_penalty + if no_repeat_ngram_size is None: + no_repeat_ngram_size = self.no_repeat_ngram_size + if max_new_tokens is None: + max_new_tokens = self.max_new_tokens + + # see SamplingParams for more details + sampling_params = { + "temperature": temperature, + "top_p": top_p, + "top_k": top_k, + "repetition_penalty": repetition_penalty, + "presence_penalty": presence_penalty, + "custom_params": { + "no_repeat_ngram_size": no_repeat_ngram_size, + }, + "max_new_tokens": max_new_tokens, + "skip_special_tokens": False, + } + + image_strings = [self.load_image_string(img) for img in images] + + output = self.engine.generate( + prompt=prompts, + image_data=image_strings, + sampling_params=sampling_params, + ) + return [item["text"] for item in output] + + def stream_predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> Iterable[str]: + raise NotImplementedError("Streaming is not supported yet.") + + async def aio_predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> str: + output = await self.aio_batch_predict( + [image], # type: ignore + [prompt], + temperature=temperature, + top_p=top_p, + top_k=top_k, + repetition_penalty=repetition_penalty, + presence_penalty=presence_penalty, + no_repeat_ngram_size=no_repeat_ngram_size, + max_new_tokens=max_new_tokens, + ) + return output[0] + + async def aio_batch_predict( + self, + images: List[str] | List[bytes], + prompts: Union[List[str], str] = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> List[str]: + + if not isinstance(prompts, list): + prompts = [prompts] * len(images) + + assert len(prompts) == len(images), "Length of prompts and images must match." + prompts = [self.build_prompt(prompt) for prompt in prompts] + + if temperature is None: + temperature = self.temperature + if top_p is None: + top_p = self.top_p + if top_k is None: + top_k = self.top_k + if repetition_penalty is None: + repetition_penalty = self.repetition_penalty + if presence_penalty is None: + presence_penalty = self.presence_penalty + if no_repeat_ngram_size is None: + no_repeat_ngram_size = self.no_repeat_ngram_size + if max_new_tokens is None: + max_new_tokens = self.max_new_tokens + + # see SamplingParams for more details + sampling_params = { + "temperature": temperature, + "top_p": top_p, + "top_k": top_k, + "repetition_penalty": repetition_penalty, + "presence_penalty": presence_penalty, + "custom_params": { + "no_repeat_ngram_size": no_repeat_ngram_size, + }, + "max_new_tokens": max_new_tokens, + "skip_special_tokens": False, + } + + image_strings = [self.load_image_string(img) for img in images] + + output = await self.engine.async_generate( + prompt=prompts, + image_data=image_strings, + sampling_params=sampling_params, + ) + ret = [] + for item in output: # type: ignore + ret.append(item["text"]) + return ret + + async def aio_stream_predict( + self, + image: str | bytes, + prompt: str = "", + temperature: Optional[float] = None, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + repetition_penalty: Optional[float] = None, + presence_penalty: Optional[float] = None, + no_repeat_ngram_size: Optional[int] = None, + max_new_tokens: Optional[int] = None, + ) -> AsyncIterable[str]: + raise NotImplementedError("Streaming is not supported yet.") + + def close(self): + self.engine.shutdown() diff --git a/mineru/backend/vlm/token_to_middle_json.py b/mineru/backend/vlm/token_to_middle_json.py new file mode 100644 index 0000000000000000000000000000000000000000..c76db01becb9f839ed3c81f0f7ff041d1d58b406 --- /dev/null +++ b/mineru/backend/vlm/token_to_middle_json.py @@ -0,0 +1,65 @@ +import re + +from mineru.utils.cut_image import cut_image_and_table +from mineru.utils.enum_class import BlockType, ContentType +from mineru.utils.hash_utils import str_md5 +from mineru.backend.vlm.vlm_magic_model import MagicModel +from mineru.version import __version__ + + +def token_to_page_info(token, image_dict, page, image_writer, page_index) -> dict: + """将token转换为页面信息""" + # 解析token,提取坐标和类型 + # 假设token格式为:<|box_start|>x0 y0 x1 y1<|box_end|><|ref_start|>type<|ref_end|><|md_start|>content<|md_end|> + # 这里需要根据实际的token格式进行解析 + # 提取所有完整块,每个块从<|box_start|>开始到<|md_end|>或<|im_end|>结束 + + scale = image_dict["scale"] + page_pil_img = image_dict["img_pil"] + page_img_md5 = str_md5(image_dict["img_base64"]) + width, height = map(int, page.get_size()) + + magic_model = MagicModel(token, width, height) + image_blocks = magic_model.get_image_blocks() + table_blocks = magic_model.get_table_blocks() + title_blocks = magic_model.get_title_blocks() + text_blocks = magic_model.get_text_blocks() + interline_equation_blocks = magic_model.get_interline_equation_blocks() + + all_spans = magic_model.get_all_spans() + # 对image/table/interline_equation的span截图 + for span in all_spans: + if span["type"] in [ContentType.IMAGE, ContentType.TABLE, ContentType.INTERLINE_EQUATION]: + span = cut_image_and_table(span, page_pil_img, page_img_md5, page_index, image_writer, scale=scale) + + page_blocks = [] + page_blocks.extend([*image_blocks, *table_blocks, *title_blocks, *text_blocks, *interline_equation_blocks]) + # 对page_blocks根据index的值进行排序 + page_blocks.sort(key=lambda x: x["index"]) + + page_info = {"para_blocks": page_blocks, "discarded_blocks": [], "page_size": [width, height], "page_idx": page_index} + return page_info + + +def result_to_middle_json(token_list, images_list, pdf_doc, image_writer): + middle_json = {"pdf_info": [], "_backend":"vlm", "_version_name": __version__} + for index, token in enumerate(token_list): + page = pdf_doc[index] + image_dict = images_list[index] + page_info = token_to_page_info(token, image_dict, page, image_writer, index) + middle_json["pdf_info"].append(page_info) + # 关闭pdf文档 + pdf_doc.close() + return middle_json + + +if __name__ == "__main__": + + output = r"<|box_start|>088 119 472 571<|box_end|><|ref_start|>image<|ref_end|><|md_start|>![]('img_url')<|md_end|>\n<|box_start|>079 582 482 608<|box_end|><|ref_start|>image_caption<|ref_end|><|md_start|>Fig. 2. (a) Schematic of the change in the FDC over time, and (b) definition of model parameters.<|md_end|>\n<|box_start|>079 624 285 638<|box_end|><|ref_start|>title<|ref_end|><|md_start|># 2.2. Zero flow day analysis<|md_end|>\n<|box_start|>079 656 482 801<|box_end|><|ref_start|>text<|ref_end|><|md_start|>A notable feature of Fig. 1 is the increase in the number of zero flow days. A similar approach to Eq. (2), using an inverse sigmoidal function was employed to assess the impact of afforestation on the number of zero flow days per year \((N_{\mathrm{zero}})\). In this case, the left hand side of Eq. (2) is replaced by \(N_{\mathrm{zero}}\) and \(b\) and \(S\) are constrained to negative as \(N_{\mathrm{zero}}\) decreases as rainfall increases, and increases with plantation growth:<|md_end|>\n<|box_start|>076 813 368 853<|box_end|><|ref_start|>equation<|ref_end|><|md_start|>\[\nN_{\mathrm{zero}}=a+b(\Delta P)+\frac{Y}{1+\exp\left(\frac{T-T_{\mathrm{half}}}{S}\right)}\n\]<|md_end|>\n<|box_start|>079 865 482 895<|box_end|><|ref_start|>text<|ref_end|><|md_start|>For the average pre-treatment condition \(\Delta P=0\) and \(T=0\), \(N_{\mathrm{zero}}\) approximately equals \(a\). \(Y\) gives<|md_end|>\n<|box_start|>525 119 926 215<|box_end|><|ref_start|>text<|ref_end|><|md_start|>the magnitude of change in zero flow days due to afforestation, and \(S\) describes the shape of the response. For the average climate condition \(\Delta P=0\), \(a+Y\) becomes the number of zero flow days when the new equilibrium condition under afforestation is reached.<|md_end|>\n<|box_start|>525 240 704 253<|box_end|><|ref_start|>title<|ref_end|><|md_start|># 2.3. Statistical analyses<|md_end|>\n<|box_start|>525 271 926 368<|box_end|><|ref_start|>text<|ref_end|><|md_start|>The coefficient of efficiency \((E)\) (Nash and Sutcliffe, 1970; Chiew and McMahon, 1993; Legates and McCabe, 1999) was used as the 'goodness of fit' measure to evaluate the fit between observed and predicted flow deciles (2) and zero flow days (3). \(E\) is given by:<|md_end|>\n<|box_start|>520 375 735 415<|box_end|><|ref_start|>equation<|ref_end|><|md_start|>\[\nE=1.0-\frac{\sum_{i=1}^{N}(O_{i}-P_{i})^{2}}{\sum_{i=1}^{N}(O_{i}-\bar{O})^{2}}\n\]<|md_end|>\n<|box_start|>525 424 926 601<|box_end|><|ref_start|>text<|ref_end|><|md_start|>where \(O\) are observed data, \(P\) are predicted values, and \(\bar{O}\) is the mean for the entire period. \(E\) is unity minus the ratio of the mean square error to the variance in the observed data, and ranges from \(-\infty\) to 1.0. Higher values indicate greater agreement between observed and predicted data as per the coefficient of determination \((r^{2})\). \(E\) is used in preference to \(r^{2}\) in evaluating hydrologic modelling because it is a measure of the deviation from the 1:1 line. As \(E\) is always \(0.7\) to indicate adequate model fits.<|md_end|>\n<|box_start|>525 603 926 731<|box_end|><|ref_start|>text<|ref_end|><|md_start|>It is important to assess the significance of the model parameters to check the model assumptions that rainfall and forest age are driving changes in the FDC. The model (2) was split into simplified forms, where only the rainfall or time terms were included by setting \(b=0\), as shown in Eq. (5), or \(Y=0\) as shown in Eq. (6). The component models (5) and (6) were then tested against the complete model, (2).<|md_end|>\n<|box_start|>520 739 735 778<|box_end|><|ref_start|>equation<|ref_end|><|md_start|>\[\nQ_{\%}=a+\frac{Y}{1+\exp\left(\frac{T-T_{\mathrm{half}}^{\prime}}{S}\right)}\n\]<|md_end|>\n<|box_start|>525 787 553 799<|box_end|><|ref_start|>text<|ref_end|><|md_start|>and<|md_end|>\n<|box_start|>520 807 646 825<|box_end|><|ref_start|>equation<|ref_end|><|md_start|>\[\nQ_{\%}=a+b\Delta P\n\]<|md_end|>\n<|box_start|>525 833 926 895<|box_end|><|ref_start|>text<|ref_end|><|md_start|>For both the flow duration curve analysis and zero flow days analysis, a \(t\)-test was then performed to test whether (5) and (6) were significantly different to (2). A critical value of \(t\) exceeding the calculated \(t\)-value<|md_end|><|im_end|>" + + p_info = token_to_page_info(output) + # 将blocks 转换为json文本 + import json + + json_str = json.dumps(p_info, ensure_ascii=False, indent=4) + print(json_str) diff --git a/mineru/backend/vlm/utils.py b/mineru/backend/vlm/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..0783d17e03a60437c300b37773a18e26f61bfbd9 --- /dev/null +++ b/mineru/backend/vlm/utils.py @@ -0,0 +1,40 @@ +import os +import re +from base64 import b64decode + +import httpx + +_timeout = int(os.getenv("REQUEST_TIMEOUT", "3")) +_file_exts = (".png", ".jpg", ".jpeg", ".webp", ".gif", ".pdf") +_data_uri_regex = re.compile(r"^data:[^;,]+;base64,") + + +def load_resource(uri: str) -> bytes: + if uri.startswith("http://") or uri.startswith("https://"): + response = httpx.get(uri, timeout=_timeout) + return response.content + if uri.startswith("file://"): + with open(uri[len("file://") :], "rb") as file: + return file.read() + if uri.lower().endswith(_file_exts): + with open(uri, "rb") as file: + return file.read() + if re.match(_data_uri_regex, uri): + return b64decode(uri.split(",")[1]) + return b64decode(uri) + + +async def aio_load_resource(uri: str) -> bytes: + if uri.startswith("http://") or uri.startswith("https://"): + async with httpx.AsyncClient(timeout=_timeout) as client: + response = await client.get(uri) + return response.content + if uri.startswith("file://"): + with open(uri[len("file://") :], "rb") as file: + return file.read() + if uri.lower().endswith(_file_exts): + with open(uri, "rb") as file: + return file.read() + if re.match(_data_uri_regex, uri): + return b64decode(uri.split(",")[1]) + return b64decode(uri) diff --git a/mineru/backend/vlm/vlm_analyze.py b/mineru/backend/vlm/vlm_analyze.py new file mode 100644 index 0000000000000000000000000000000000000000..3963651ea34dbef306dff123b1d8bdd1af155fb3 --- /dev/null +++ b/mineru/backend/vlm/vlm_analyze.py @@ -0,0 +1,90 @@ +# Copyright (c) Opendatalab. All rights reserved. +import time + +from loguru import logger + +from ...data.data_reader_writer import DataWriter +from mineru.utils.pdf_image_tools import load_images_from_pdf +from .base_predictor import BasePredictor +from .predictor import get_predictor +from .token_to_middle_json import result_to_middle_json +from ...utils.enum_class import ModelPath +from ...utils.models_download_utils import auto_download_and_get_model_root_path + + +class ModelSingleton: + _instance = None + _models = {} + + def __new__(cls, *args, **kwargs): + if cls._instance is None: + cls._instance = super().__new__(cls) + return cls._instance + + def get_model( + self, + backend: str, + model_path: str | None, + server_url: str | None, + ) -> BasePredictor: + key = (backend,) + if key not in self._models: + if not model_path: + model_path = auto_download_and_get_model_root_path("/","vlm") + self._models[key] = get_predictor( + backend=backend, + model_path=model_path, + server_url=server_url, + ) + return self._models[key] + + +def doc_analyze( + pdf_bytes, + image_writer: DataWriter | None, + predictor: BasePredictor | None = None, + backend="transformers", + model_path: str | None = None, + server_url: str | None = None, +): + if predictor is None: + predictor = ModelSingleton().get_model(backend, model_path, server_url) + + # load_images_start = time.time() + images_list, pdf_doc = load_images_from_pdf(pdf_bytes) + images_base64_list = [image_dict["img_base64"] for image_dict in images_list] + # load_images_time = round(time.time() - load_images_start, 2) + # logger.info(f"load images cost: {load_images_time}, speed: {round(len(images_base64_list)/load_images_time, 3)} images/s") + + # infer_start = time.time() + results = predictor.batch_predict(images=images_base64_list) + # infer_time = round(time.time() - infer_start, 2) + # logger.info(f"infer finished, cost: {infer_time}, speed: {round(len(results)/infer_time, 3)} page/s") + + middle_json = result_to_middle_json(results, images_list, pdf_doc, image_writer) + return middle_json, results + + +async def aio_doc_analyze( + pdf_bytes, + image_writer: DataWriter | None, + predictor: BasePredictor | None = None, + backend="transformers", + model_path: str | None = None, + server_url: str | None = None, +): + if predictor is None: + predictor = ModelSingleton().get_model(backend, model_path, server_url) + + load_images_start = time.time() + images_list, pdf_doc = load_images_from_pdf(pdf_bytes) + images_base64_list = [image_dict["img_base64"] for image_dict in images_list] + load_images_time = round(time.time() - load_images_start, 2) + logger.info(f"load images cost: {load_images_time}, speed: {round(len(images_base64_list)/load_images_time, 3)} images/s") + + infer_start = time.time() + results = await predictor.aio_batch_predict(images=images_base64_list) + infer_time = round(time.time() - infer_start, 2) + logger.info(f"infer finished, cost: {infer_time}, speed: {round(len(results)/infer_time, 3)} page/s") + middle_json = result_to_middle_json(results, images_list, pdf_doc, image_writer) + return middle_json diff --git a/mineru/backend/vlm/vlm_magic_model.py b/mineru/backend/vlm/vlm_magic_model.py new file mode 100644 index 0000000000000000000000000000000000000000..b33595c4cddfb82d24596e816cabcba4e8610759 --- /dev/null +++ b/mineru/backend/vlm/vlm_magic_model.py @@ -0,0 +1,514 @@ +import re +from typing import Literal + +from mineru.utils.boxbase import bbox_distance, is_in +from mineru.utils.enum_class import ContentType, BlockType, SplitFlag +from mineru.backend.vlm.vlm_middle_json_mkcontent import merge_para_with_text +from mineru.utils.format_utils import convert_otsl_to_html + + +class MagicModel: + def __init__(self, token: str, width, height): + self.token = token + + # 使用正则表达式查找所有块 + pattern = ( + r"<\|box_start\|>(.*?)<\|box_end\|><\|ref_start\|>(.*?)<\|ref_end\|><\|md_start\|>(.*?)(?:<\|md_end\|>|<\|im_end\|>)" + ) + block_infos = re.findall(pattern, token, re.DOTALL) + + blocks = [] + self.all_spans = [] + # 解析每个块 + for index, block_info in enumerate(block_infos): + block_bbox = block_info[0].strip() + x1, y1, x2, y2 = map(int, block_bbox.split()) + x_1, y_1, x_2, y_2 = ( + int(x1 * width / 1000), + int(y1 * height / 1000), + int(x2 * width / 1000), + int(y2 * height / 1000), + ) + if x_2 < x_1: + x_1, x_2 = x_2, x_1 + if y_2 < y_1: + y_1, y_2 = y_2, y_1 + block_bbox = (x_1, y_1, x_2, y_2) + block_type = block_info[1].strip() + block_content = block_info[2].strip() + + # print(f"坐标: {block_bbox}") + # print(f"类型: {block_type}") + # print(f"内容: {block_content}") + # print("-" * 50) + + span_type = "unknown" + if block_type in [ + "text", + "title", + "image_caption", + "image_footnote", + "table_caption", + "table_footnote", + "list", + "index", + ]: + span_type = ContentType.TEXT + elif block_type in ["image"]: + block_type = BlockType.IMAGE_BODY + span_type = ContentType.IMAGE + elif block_type in ["table"]: + block_type = BlockType.TABLE_BODY + span_type = ContentType.TABLE + elif block_type in ["equation"]: + block_type = BlockType.INTERLINE_EQUATION + span_type = ContentType.INTERLINE_EQUATION + + if span_type in ["image", "table"]: + span = { + "bbox": block_bbox, + "type": span_type, + } + if span_type == ContentType.TABLE: + if "" in block_content or "" in block_content: + lines = block_content.split("\n\n") + new_lines = [] + for line in lines: + if "" in line or "" in line: + line = convert_otsl_to_html(line) + new_lines.append(line) + span["html"] = "\n\n".join(new_lines) + else: + span["html"] = block_content + elif span_type in [ContentType.INTERLINE_EQUATION]: + span = { + "bbox": block_bbox, + "type": span_type, + "content": isolated_formula_clean(block_content), + } + else: + if block_content.count("\\(") == block_content.count("\\)") and block_content.count("\\(") > 0: + # 生成包含文本和公式的span列表 + spans = [] + last_end = 0 + + # 查找所有公式 + for match in re.finditer(r'\\\((.+?)\\\)', block_content): + start, end = match.span() + + # 添加公式前的文本 + if start > last_end: + text_before = block_content[last_end:start] + if text_before.strip(): + spans.append({ + "bbox": block_bbox, + "type": ContentType.TEXT, + "content": text_before + }) + + # 添加公式(去除\(和\)) + formula = match.group(1) + spans.append({ + "bbox": block_bbox, + "type": ContentType.INLINE_EQUATION, + "content": formula.strip() + }) + + last_end = end + + # 添加最后一个公式后的文本 + if last_end < len(block_content): + text_after = block_content[last_end:] + if text_after.strip(): + spans.append({ + "bbox": block_bbox, + "type": ContentType.TEXT, + "content": text_after + }) + + span = spans + else: + span = { + "bbox": block_bbox, + "type": span_type, + "content": block_content, + } + + if isinstance(span, dict) and "bbox" in span: + self.all_spans.append(span) + line = { + "bbox": block_bbox, + "spans": [span], + } + elif isinstance(span, list): + self.all_spans.extend(span) + line = { + "bbox": block_bbox, + "spans": span, + } + else: + raise ValueError(f"Invalid span type: {span_type}, expected dict or list, got {type(span)}") + + blocks.append( + { + "bbox": block_bbox, + "type": block_type, + "lines": [line], + "index": index, + } + ) + + self.image_blocks = [] + self.table_blocks = [] + self.interline_equation_blocks = [] + self.text_blocks = [] + self.title_blocks = [] + for block in blocks: + if block["type"] in [BlockType.IMAGE_BODY, BlockType.IMAGE_CAPTION, BlockType.IMAGE_FOOTNOTE]: + self.image_blocks.append(block) + elif block["type"] in [BlockType.TABLE_BODY, BlockType.TABLE_CAPTION, BlockType.TABLE_FOOTNOTE]: + self.table_blocks.append(block) + elif block["type"] == BlockType.INTERLINE_EQUATION: + self.interline_equation_blocks.append(block) + elif block["type"] == BlockType.TEXT: + self.text_blocks.append(block) + elif block["type"] == BlockType.TITLE: + self.title_blocks.append(block) + else: + continue + + def get_image_blocks(self): + return fix_two_layer_blocks(self.image_blocks, BlockType.IMAGE) + + def get_table_blocks(self): + return fix_two_layer_blocks(self.table_blocks, BlockType.TABLE) + + def get_title_blocks(self): + return fix_title_blocks(self.title_blocks) + + def get_text_blocks(self): + return fix_text_blocks(self.text_blocks) + + def get_interline_equation_blocks(self): + return self.interline_equation_blocks + + def get_all_spans(self): + return self.all_spans + + +def isolated_formula_clean(txt): + latex = txt[:] + if latex.startswith("\\["): latex = latex[2:] + if latex.endswith("\\]"): latex = latex[:-2] + latex = latex_fix(latex.strip()) + return latex + + +def latex_fix(latex): + # valid pairs: + # \left\{ ... \right\} + # \left( ... \right) + # \left| ... \right| + # \left\| ... \right\| + # \left[ ... \right] + + LEFT_COUNT_PATTERN = re.compile(r'\\left(?![a-zA-Z])') + RIGHT_COUNT_PATTERN = re.compile(r'\\right(?![a-zA-Z])') + left_count = len(LEFT_COUNT_PATTERN.findall(latex)) # 不匹配\lefteqn等 + right_count = len(RIGHT_COUNT_PATTERN.findall(latex)) # 不匹配\rightarrow + + if left_count != right_count: + for _ in range(2): + # replace valid pairs + latex = re.sub(r'\\left\\\{', "{", latex) # \left\{ + latex = re.sub(r"\\left\|", "|", latex) # \left| + latex = re.sub(r"\\left\\\|", "|", latex) # \left\| + latex = re.sub(r"\\left\(", "(", latex) # \left( + latex = re.sub(r"\\left\[", "[", latex) # \left[ + + latex = re.sub(r"\\right\\\}", "}", latex) # \right\} + latex = re.sub(r"\\right\|", "|", latex) # \right| + latex = re.sub(r"\\right\\\|", "|", latex) # \right\| + latex = re.sub(r"\\right\)", ")", latex) # \right) + latex = re.sub(r"\\right\]", "]", latex) # \right] + latex = re.sub(r"\\right\.", "", latex) # \right. + + # replace invalid pairs first + latex = re.sub(r'\\left\{', "{", latex) + latex = re.sub(r'\\right\}', "}", latex) # \left{ ... \right} + latex = re.sub(r'\\left\\\(', "(", latex) + latex = re.sub(r'\\right\\\)', ")", latex) # \left\( ... \right\) + latex = re.sub(r'\\left\\\[', "[", latex) + latex = re.sub(r'\\right\\\]', "]", latex) # \left\[ ... \right\] + + return latex + + +def __reduct_overlap(bboxes): + N = len(bboxes) + keep = [True] * N + for i in range(N): + for j in range(N): + if i == j: + continue + if is_in(bboxes[i]["bbox"], bboxes[j]["bbox"]): + keep[i] = False + return [bboxes[i] for i in range(N) if keep[i]] + + +def __tie_up_category_by_distance_v3( + blocks: list, + subject_block_type: str, + object_block_type: str, +): + subjects = __reduct_overlap( + list( + map( + lambda x: {"bbox": x["bbox"], "lines": x["lines"], "index": x["index"]}, + filter( + lambda x: x["type"] == subject_block_type, + blocks, + ), + ) + ) + ) + objects = __reduct_overlap( + list( + map( + lambda x: {"bbox": x["bbox"], "lines": x["lines"], "index": x["index"]}, + filter( + lambda x: x["type"] == object_block_type, + blocks, + ), + ) + ) + ) + + ret = [] + N, M = len(subjects), len(objects) + subjects.sort(key=lambda x: x["bbox"][0] ** 2 + x["bbox"][1] ** 2) + objects.sort(key=lambda x: x["bbox"][0] ** 2 + x["bbox"][1] ** 2) + + OBJ_IDX_OFFSET = 10000 + SUB_BIT_KIND, OBJ_BIT_KIND = 0, 1 + + all_boxes_with_idx = [(i, SUB_BIT_KIND, sub["bbox"][0], sub["bbox"][1]) for i, sub in enumerate(subjects)] + [ + (i + OBJ_IDX_OFFSET, OBJ_BIT_KIND, obj["bbox"][0], obj["bbox"][1]) for i, obj in enumerate(objects) + ] + seen_idx = set() + seen_sub_idx = set() + + while N > len(seen_sub_idx): + candidates = [] + for idx, kind, x0, y0 in all_boxes_with_idx: + if idx in seen_idx: + continue + candidates.append((idx, kind, x0, y0)) + + if len(candidates) == 0: + break + left_x = min([v[2] for v in candidates]) + top_y = min([v[3] for v in candidates]) + + candidates.sort(key=lambda x: (x[2] - left_x) ** 2 + (x[3] - top_y) ** 2) + + fst_idx, fst_kind, left_x, top_y = candidates[0] + candidates.sort(key=lambda x: (x[2] - left_x) ** 2 + (x[3] - top_y) ** 2) + nxt = None + + for i in range(1, len(candidates)): + if candidates[i][1] ^ fst_kind == 1: + nxt = candidates[i] + break + if nxt is None: + break + + if fst_kind == SUB_BIT_KIND: + sub_idx, obj_idx = fst_idx, nxt[0] - OBJ_IDX_OFFSET + + else: + sub_idx, obj_idx = nxt[0], fst_idx - OBJ_IDX_OFFSET + + pair_dis = bbox_distance(subjects[sub_idx]["bbox"], objects[obj_idx]["bbox"]) + nearest_dis = float("inf") + for i in range(N): + if i in seen_idx or i == sub_idx: + continue + nearest_dis = min(nearest_dis, bbox_distance(subjects[i]["bbox"], objects[obj_idx]["bbox"])) + + if pair_dis >= 3 * nearest_dis: + seen_idx.add(sub_idx) + continue + + seen_idx.add(sub_idx) + seen_idx.add(obj_idx + OBJ_IDX_OFFSET) + seen_sub_idx.add(sub_idx) + + ret.append( + { + "sub_bbox": { + "bbox": subjects[sub_idx]["bbox"], + "lines": subjects[sub_idx]["lines"], + "index": subjects[sub_idx]["index"], + }, + "obj_bboxes": [ + {"bbox": objects[obj_idx]["bbox"], "lines": objects[obj_idx]["lines"], "index": objects[obj_idx]["index"]} + ], + "sub_idx": sub_idx, + } + ) + + for i in range(len(objects)): + j = i + OBJ_IDX_OFFSET + if j in seen_idx: + continue + seen_idx.add(j) + nearest_dis, nearest_sub_idx = float("inf"), -1 + for k in range(len(subjects)): + dis = bbox_distance(objects[i]["bbox"], subjects[k]["bbox"]) + if dis < nearest_dis: + nearest_dis = dis + nearest_sub_idx = k + + for k in range(len(subjects)): + if k != nearest_sub_idx: + continue + if k in seen_sub_idx: + for kk in range(len(ret)): + if ret[kk]["sub_idx"] == k: + ret[kk]["obj_bboxes"].append( + {"bbox": objects[i]["bbox"], "lines": objects[i]["lines"], "index": objects[i]["index"]} + ) + break + else: + ret.append( + { + "sub_bbox": { + "bbox": subjects[k]["bbox"], + "lines": subjects[k]["lines"], + "index": subjects[k]["index"], + }, + "obj_bboxes": [ + {"bbox": objects[i]["bbox"], "lines": objects[i]["lines"], "index": objects[i]["index"]} + ], + "sub_idx": k, + } + ) + seen_sub_idx.add(k) + seen_idx.add(k) + + for i in range(len(subjects)): + if i in seen_sub_idx: + continue + ret.append( + { + "sub_bbox": { + "bbox": subjects[i]["bbox"], + "lines": subjects[i]["lines"], + "index": subjects[i]["index"], + }, + "obj_bboxes": [], + "sub_idx": i, + } + ) + + return ret + + +def get_type_blocks(blocks, block_type: Literal["image", "table"]): + with_captions = __tie_up_category_by_distance_v3(blocks, f"{block_type}_body", f"{block_type}_caption") + with_footnotes = __tie_up_category_by_distance_v3(blocks, f"{block_type}_body", f"{block_type}_footnote") + ret = [] + for v in with_captions: + record = { + f"{block_type}_body": v["sub_bbox"], + f"{block_type}_caption_list": v["obj_bboxes"], + } + filter_idx = v["sub_idx"] + d = next(filter(lambda x: x["sub_idx"] == filter_idx, with_footnotes)) + record[f"{block_type}_footnote_list"] = d["obj_bboxes"] + ret.append(record) + return ret + + +def fix_two_layer_blocks(blocks, fix_type: Literal["image", "table"]): + need_fix_blocks = get_type_blocks(blocks, fix_type) + fixed_blocks = [] + for block in need_fix_blocks: + body = block[f"{fix_type}_body"] + caption_list = block[f"{fix_type}_caption_list"] + footnote_list = block[f"{fix_type}_footnote_list"] + + body["type"] = f"{fix_type}_body" + for caption in caption_list: + caption["type"] = f"{fix_type}_caption" + for footnote in footnote_list: + footnote["type"] = f"{fix_type}_footnote" + + two_layer_block = { + "type": fix_type, + "bbox": body["bbox"], + "blocks": [ + body, + ], + "index": body["index"], + } + two_layer_block["blocks"].extend([*caption_list, *footnote_list]) + + fixed_blocks.append(two_layer_block) + + return fixed_blocks + + +def fix_title_blocks(blocks): + for block in blocks: + if block["type"] == BlockType.TITLE: + title_content = merge_para_with_text(block) + title_level = count_leading_hashes(title_content) + block['level'] = title_level + for line in block['lines']: + for span in line['spans']: + span['content'] = strip_leading_hashes(span['content']) + break + break + return blocks + + +def count_leading_hashes(text): + match = re.match(r'^(#+)', text) + return len(match.group(1)) if match else 0 + + +def strip_leading_hashes(text): + # 去除开头的#和紧随其后的空格 + return re.sub(r'^#+\s*', '', text) + + +def fix_text_blocks(blocks): + i = 0 + while i < len(blocks): + block = blocks[i] + last_line = block["lines"][-1]if block["lines"] else None + if last_line: + last_span = last_line["spans"][-1] if last_line["spans"] else None + if last_span and last_span['content'].endswith('<|txt_contd|>'): + last_span['content'] = last_span['content'][:-len('<|txt_contd|>')] + + # 查找下一个未被清空的块 + next_idx = i + 1 + while next_idx < len(blocks) and blocks[next_idx].get(SplitFlag.LINES_DELETED, False): + next_idx += 1 + + # 如果找到下一个有效块,则合并 + if next_idx < len(blocks): + next_block = blocks[next_idx] + # 将下一个块的lines扩展到当前块的lines中 + block["lines"].extend(next_block["lines"]) + # 清空下一个块的lines + next_block["lines"] = [] + # 在下一个块中添加标志 + next_block[SplitFlag.LINES_DELETED] = True + # 不增加i,继续检查当前块(现在已包含下一个块的内容) + continue + i += 1 + return blocks \ No newline at end of file diff --git a/mineru/backend/vlm/vlm_middle_json_mkcontent.py b/mineru/backend/vlm/vlm_middle_json_mkcontent.py new file mode 100644 index 0000000000000000000000000000000000000000..87b7039cd8b9344bd9a2a0ee2f759d2827b3a3a3 --- /dev/null +++ b/mineru/backend/vlm/vlm_middle_json_mkcontent.py @@ -0,0 +1,207 @@ +from mineru.utils.config_reader import get_latex_delimiter_config +from mineru.utils.enum_class import MakeMode, BlockType, ContentType + + +latex_delimiters_config = get_latex_delimiter_config() + +default_delimiters = { + 'display': {'left': '$$', 'right': '$$'}, + 'inline': {'left': '$', 'right': '$'} +} + +delimiters = latex_delimiters_config if latex_delimiters_config else default_delimiters + +display_left_delimiter = delimiters['display']['left'] +display_right_delimiter = delimiters['display']['right'] +inline_left_delimiter = delimiters['inline']['left'] +inline_right_delimiter = delimiters['inline']['right'] + +def merge_para_with_text(para_block): + para_text = '' + for line in para_block['lines']: + for j, span in enumerate(line['spans']): + span_type = span['type'] + content = '' + if span_type == ContentType.TEXT: + content = span['content'] + elif span_type == ContentType.INLINE_EQUATION: + content = f"{inline_left_delimiter}{span['content']}{inline_right_delimiter}" + elif span_type == ContentType.INTERLINE_EQUATION: + content = f"\n{display_left_delimiter}\n{span['content']}\n{display_right_delimiter}\n" + # content = content.strip() + if content: + if span_type in [ContentType.TEXT, ContentType.INLINE_EQUATION]: + if j == len(line['spans']) - 1: + para_text += content + else: + para_text += f'{content} ' + elif span_type == ContentType.INTERLINE_EQUATION: + para_text += content + return para_text + +def mk_blocks_to_markdown(para_blocks, make_mode, img_buket_path=''): + page_markdown = [] + for para_block in para_blocks: + para_text = '' + para_type = para_block['type'] + if para_type in [BlockType.TEXT, BlockType.LIST, BlockType.INDEX, BlockType.INTERLINE_EQUATION]: + para_text = merge_para_with_text(para_block) + elif para_type == BlockType.TITLE: + title_level = get_title_level(para_block) + para_text = f'{"#" * title_level} {merge_para_with_text(para_block)}' + elif para_type == BlockType.IMAGE: + if make_mode == MakeMode.NLP_MD: + continue + elif make_mode == MakeMode.MM_MD: + # 检测是否存在图片脚注 + has_image_footnote = any(block['type'] == BlockType.IMAGE_FOOTNOTE for block in para_block['blocks']) + # 如果存在图片脚注,则将图片脚注拼接到图片正文后面 + if has_image_footnote: + for block in para_block['blocks']: # 1st.拼image_caption + if block['type'] == BlockType.IMAGE_CAPTION: + para_text += merge_para_with_text(block) + ' \n' + for block in para_block['blocks']: # 2nd.拼image_body + if block['type'] == BlockType.IMAGE_BODY: + for line in block['lines']: + for span in line['spans']: + if span['type'] == ContentType.IMAGE: + if span.get('image_path', ''): + para_text += f"![]({img_buket_path}/{span['image_path']})" + for block in para_block['blocks']: # 3rd.拼image_footnote + if block['type'] == BlockType.IMAGE_FOOTNOTE: + para_text += ' \n' + merge_para_with_text(block) + else: + for block in para_block['blocks']: # 1st.拼image_body + if block['type'] == BlockType.IMAGE_BODY: + for line in block['lines']: + for span in line['spans']: + if span['type'] == ContentType.IMAGE: + if span.get('image_path', ''): + para_text += f"![]({img_buket_path}/{span['image_path']})" + for block in para_block['blocks']: # 2nd.拼image_caption + if block['type'] == BlockType.IMAGE_CAPTION: + para_text += ' \n' + merge_para_with_text(block) + + elif para_type == BlockType.TABLE: + if make_mode == MakeMode.NLP_MD: + continue + elif make_mode == MakeMode.MM_MD: + for block in para_block['blocks']: # 1st.拼table_caption + if block['type'] == BlockType.TABLE_CAPTION: + para_text += merge_para_with_text(block) + ' \n' + for block in para_block['blocks']: # 2nd.拼table_body + if block['type'] == BlockType.TABLE_BODY: + for line in block['lines']: + for span in line['spans']: + if span['type'] == ContentType.TABLE: + # if processed by table model + if span.get('html', ''): + para_text += f"\n{span['html']}\n" + elif span.get('image_path', ''): + para_text += f"![]({img_buket_path}/{span['image_path']})" + for block in para_block['blocks']: # 3rd.拼table_footnote + if block['type'] == BlockType.TABLE_FOOTNOTE: + para_text += '\n' + merge_para_with_text(block) + ' ' + + if para_text.strip() == '': + continue + else: + # page_markdown.append(para_text.strip() + ' ') + page_markdown.append(para_text.strip()) + + return page_markdown + + + + + +def make_blocks_to_content_list(para_block, img_buket_path, page_idx): + para_type = para_block['type'] + para_content = {} + if para_type in [BlockType.TEXT, BlockType.LIST, BlockType.INDEX]: + para_content = { + 'type': 'text', + 'text': merge_para_with_text(para_block), + } + elif para_type == BlockType.TITLE: + title_level = get_title_level(para_block) + para_content = { + 'type': 'text', + 'text': merge_para_with_text(para_block), + } + if title_level != 0: + para_content['text_level'] = title_level + elif para_type == BlockType.INTERLINE_EQUATION: + para_content = { + 'type': 'equation', + 'text': merge_para_with_text(para_block), + 'text_format': 'latex', + } + elif para_type == BlockType.IMAGE: + para_content = {'type': 'image', 'img_path': '', 'img_caption': [], 'img_footnote': []} + for block in para_block['blocks']: + if block['type'] == BlockType.IMAGE_BODY: + for line in block['lines']: + for span in line['spans']: + if span['type'] == ContentType.IMAGE: + if span.get('image_path', ''): + para_content['img_path'] = f"{img_buket_path}/{span['image_path']}" + if block['type'] == BlockType.IMAGE_CAPTION: + para_content['img_caption'].append(merge_para_with_text(block)) + if block['type'] == BlockType.IMAGE_FOOTNOTE: + para_content['img_footnote'].append(merge_para_with_text(block)) + elif para_type == BlockType.TABLE: + para_content = {'type': 'table', 'img_path': '', 'table_caption': [], 'table_footnote': []} + for block in para_block['blocks']: + if block['type'] == BlockType.TABLE_BODY: + for line in block['lines']: + for span in line['spans']: + if span['type'] == ContentType.TABLE: + + if span.get('html', ''): + para_content['table_body'] = f"{span['html']}" + + if span.get('image_path', ''): + para_content['img_path'] = f"{img_buket_path}/{span['image_path']}" + + if block['type'] == BlockType.TABLE_CAPTION: + para_content['table_caption'].append(merge_para_with_text(block)) + if block['type'] == BlockType.TABLE_FOOTNOTE: + para_content['table_footnote'].append(merge_para_with_text(block)) + + para_content['page_idx'] = page_idx + + return para_content + +def union_make(pdf_info_dict: list, + make_mode: str, + img_buket_path: str = '', + ): + output_content = [] + for page_info in pdf_info_dict: + paras_of_layout = page_info.get('para_blocks') + page_idx = page_info.get('page_idx') + if not paras_of_layout: + continue + if make_mode in [MakeMode.MM_MD, MakeMode.NLP_MD]: + page_markdown = mk_blocks_to_markdown(paras_of_layout, make_mode, img_buket_path) + output_content.extend(page_markdown) + elif make_mode == MakeMode.CONTENT_LIST: + for para_block in paras_of_layout: + para_content = make_blocks_to_content_list(para_block, img_buket_path, page_idx) + output_content.append(para_content) + + if make_mode in [MakeMode.MM_MD, MakeMode.NLP_MD]: + return '\n\n'.join(output_content) + elif make_mode == MakeMode.CONTENT_LIST: + return output_content + return None + + +def get_title_level(block): + title_level = block.get('level', 1) + if title_level > 4: + title_level = 4 + elif title_level < 1: + title_level = 0 + return title_level diff --git a/magic_pdf/post_proc/__init__.py b/mineru/cli/__init__.py similarity index 100% rename from magic_pdf/post_proc/__init__.py rename to mineru/cli/__init__.py diff --git a/mineru/cli/client.py b/mineru/cli/client.py new file mode 100644 index 0000000000000000000000000000000000000000..41818224584219fb73b3661f4e05138ca94cfea4 --- /dev/null +++ b/mineru/cli/client.py @@ -0,0 +1,204 @@ +# Copyright (c) Opendatalab. All rights reserved. +import os +import click +from pathlib import Path +import torch +from loguru import logger + +from mineru.utils.config_reader import get_device +from mineru.utils.model_utils import get_vram +from ..version import __version__ +from .common import do_parse, read_fn, pdf_suffixes, image_suffixes + + +@click.command() +@click.version_option(__version__, + '--version', + '-v', + help='display the version and exit') +@click.option( + '-p', + '--path', + 'input_path', + type=click.Path(exists=True), + required=True, + help='local filepath or directory. support pdf, png, jpg, jpeg files', +) +@click.option( + '-o', + '--output', + 'output_dir', + type=click.Path(), + required=True, + help='output local directory', +) +@click.option( + '-m', + '--method', + 'method', + type=click.Choice(['auto', 'txt', 'ocr']), + help="""the method for parsing pdf: + auto: Automatically determine the method based on the file type. + txt: Use text extraction method. + ocr: Use OCR method for image-based PDFs. + Without method specified, 'auto' will be used by default. + Adapted only for the case where the backend is set to "pipeline".""", + default='auto', +) +@click.option( + '-b', + '--backend', + 'backend', + type=click.Choice(['pipeline', 'vlm-transformers', 'vlm-sglang-engine', 'vlm-sglang-client']), + help="""the backend for parsing pdf: + pipeline: More general. + vlm-transformers: More general. + vlm-sglang-engine: Faster(engine). + vlm-sglang-client: Faster(client). + without method specified, pipeline will be used by default.""", + default='pipeline', +) +@click.option( + '-l', + '--lang', + 'lang', + type=click.Choice(['ch', 'ch_server', 'ch_lite', 'en', 'korean', 'japan', 'chinese_cht', 'ta', 'te', 'ka']), + help=""" + Input the languages in the pdf (if known) to improve OCR accuracy. Optional. + Without languages specified, 'ch' will be used by default. + Adapted only for the case where the backend is set to "pipeline". + """, + default='ch', +) +@click.option( + '-u', + '--url', + 'server_url', + type=str, + help=""" + When the backend is `sglang-client`, you need to specify the server_url, for example:`http://127.0.0.1:30000` + """, + default=None, +) +@click.option( + '-s', + '--start', + 'start_page_id', + type=int, + help='The starting page for PDF parsing, beginning from 0.', + default=0, +) +@click.option( + '-e', + '--end', + 'end_page_id', + type=int, + help='The ending page for PDF parsing, beginning from 0.', + default=None, +) +@click.option( + '-f', + '--formula', + 'formula_enable', + type=bool, + help='Enable formula parsing. Default is True. Adapted only for the case where the backend is set to "pipeline".', + default=True, +) +@click.option( + '-t', + '--table', + 'table_enable', + type=bool, + help='Enable table parsing. Default is True. Adapted only for the case where the backend is set to "pipeline".', + default=True, +) +@click.option( + '-d', + '--device', + 'device_mode', + type=str, + help='Device mode for model inference, e.g., "cpu", "cuda", "cuda:0", "npu", "npu:0", "mps". Adapted only for the case where the backend is set to "pipeline". ', + default=None, +) +@click.option( + '--vram', + 'virtual_vram', + type=int, + help='Upper limit of GPU memory occupied by a single process. Adapted only for the case where the backend is set to "pipeline". ', + default=None, +) +@click.option( + '--source', + 'model_source', + type=click.Choice(['huggingface', 'modelscope', 'local']), + help=""" + The source of the model repository. Default is 'huggingface'. + """, + default='huggingface', +) + + +def main(input_path, output_dir, method, backend, lang, server_url, start_page_id, end_page_id, formula_enable, table_enable, device_mode, virtual_vram, model_source): + + if os.getenv('MINERU_FORMULA_ENABLE', None) is None: + os.environ['MINERU_FORMULA_ENABLE'] = str(formula_enable).lower() + if os.getenv('MINERU_TABLE_ENABLE', None) is None: + os.environ['MINERU_TABLE_ENABLE'] = str(table_enable).lower() + def get_device_mode() -> str: + if device_mode is not None: + return device_mode + else: + return get_device() + if os.getenv('MINERU_DEVICE_MODE', None) is None: + os.environ['MINERU_DEVICE_MODE'] = get_device_mode() + + def get_virtual_vram_size() -> int: + if virtual_vram is not None: + return virtual_vram + if get_device_mode().startswith("cuda") or get_device_mode().startswith("npu"): + return round(get_vram(get_device_mode())) + return 1 + if os.getenv('MINERU_VIRTUAL_VRAM_SIZE', None) is None: + os.environ['MINERU_VIRTUAL_VRAM_SIZE']= str(get_virtual_vram_size()) + + if os.getenv('MINERU_MODEL_SOURCE', None) is None: + os.environ['MINERU_MODEL_SOURCE'] = model_source + + os.makedirs(output_dir, exist_ok=True) + + def parse_doc(path_list: list[Path]): + try: + file_name_list = [] + pdf_bytes_list = [] + lang_list = [] + for path in path_list: + file_name = str(Path(path).stem) + pdf_bytes = read_fn(path) + file_name_list.append(file_name) + pdf_bytes_list.append(pdf_bytes) + lang_list.append(lang) + do_parse( + output_dir=output_dir, + pdf_file_names=file_name_list, + pdf_bytes_list=pdf_bytes_list, + p_lang_list=lang_list, + backend=backend, + parse_method=method, + server_url=server_url, + start_page_id=start_page_id, + end_page_id=end_page_id + ) + except Exception as e: + logger.exception(e) + + if os.path.isdir(input_path): + doc_path_list = [] + for doc_path in Path(input_path).glob('*'): + if doc_path.suffix in pdf_suffixes + image_suffixes: + doc_path_list.append(doc_path) + parse_doc(doc_path_list) + else: + parse_doc([Path(input_path)]) + +if __name__ == '__main__': + main() diff --git a/mineru/cli/common.py b/mineru/cli/common.py new file mode 100644 index 0000000000000000000000000000000000000000..74fab6c00ed1374ff0dff06d3ec51e6014f325b2 --- /dev/null +++ b/mineru/cli/common.py @@ -0,0 +1,235 @@ +# Copyright (c) Opendatalab. All rights reserved. +import io +import json +import os +import copy +from pathlib import Path + +import pypdfium2 as pdfium +from loguru import logger + +from mineru.backend.pipeline.pipeline_middle_json_mkcontent import union_make as pipeline_union_make +from mineru.backend.pipeline.model_json_to_middle_json import result_to_middle_json as pipeline_result_to_middle_json +from mineru.backend.vlm.vlm_middle_json_mkcontent import union_make as vlm_union_make +from mineru.backend.vlm.vlm_analyze import doc_analyze as vlm_doc_analyze +from mineru.backend.pipeline.pipeline_analyze import doc_analyze as pipeline_doc_analyze +from mineru.data.data_reader_writer import FileBasedDataWriter +from mineru.utils.draw_bbox import draw_layout_bbox, draw_span_bbox +from mineru.utils.enum_class import MakeMode +from mineru.utils.pdf_image_tools import images_bytes_to_pdf_bytes + +pdf_suffixes = [".pdf"] +image_suffixes = [".png", ".jpeg", ".jpg"] + + +def read_fn(path): + if not isinstance(path, Path): + path = Path(path) + with open(str(path), "rb") as input_file: + file_bytes = input_file.read() + if path.suffix in image_suffixes: + return images_bytes_to_pdf_bytes(file_bytes) + elif path.suffix in pdf_suffixes: + return file_bytes + else: + raise Exception(f"Unknown file suffix: {path.suffix}") + + +def prepare_env(output_dir, pdf_file_name, parse_method): + local_md_dir = str(os.path.join(output_dir, pdf_file_name, parse_method)) + local_image_dir = os.path.join(str(local_md_dir), "images") + os.makedirs(local_image_dir, exist_ok=True) + os.makedirs(local_md_dir, exist_ok=True) + return local_image_dir, local_md_dir + + +def convert_pdf_bytes_to_bytes_by_pypdfium2(pdf_bytes, start_page_id=0, end_page_id=None): + + # 从字节数据加载PDF + pdf = pdfium.PdfDocument(pdf_bytes) + + # 确定结束页 + end_page_id = end_page_id if end_page_id is not None and end_page_id >= 0 else len(pdf) - 1 + if end_page_id > len(pdf) - 1: + logger.warning("end_page_id is out of range, use pdf_docs length") + end_page_id = len(pdf) - 1 + + # 创建一个新的PDF文档 + output_pdf = pdfium.PdfDocument.new() + + # 选择要导入的页面索引 + page_indices = list(range(start_page_id, end_page_id + 1)) + + # 从原PDF导入页面到新PDF + output_pdf.import_pages(pdf, page_indices) + + # 将新PDF保存到内存缓冲区 + output_buffer = io.BytesIO() + output_pdf.save(output_buffer) + + # 获取字节数据 + output_bytes = output_buffer.getvalue() + + pdf.close() # 关闭原PDF文档以释放资源 + output_pdf.close() # 关闭新PDF文档以释放资源 + + return output_bytes + + +def do_parse( + output_dir, + pdf_file_names: list[str], + pdf_bytes_list: list[bytes], + p_lang_list: list[str], + backend="pipeline", + parse_method="auto", + p_formula_enable=True, + p_table_enable=True, + server_url=None, + f_draw_layout_bbox=True, + f_draw_span_bbox=True, + f_dump_md=True, + f_dump_middle_json=True, + f_dump_model_output=True, + f_dump_orig_pdf=True, + f_dump_content_list=True, + f_make_md_mode=MakeMode.MM_MD, + start_page_id=0, + end_page_id=None, +): + + if backend == "pipeline": + for idx, pdf_bytes in enumerate(pdf_bytes_list): + new_pdf_bytes = convert_pdf_bytes_to_bytes_by_pypdfium2(pdf_bytes, start_page_id, end_page_id) + pdf_bytes_list[idx] = new_pdf_bytes + + infer_results, all_image_lists, all_pdf_docs, lang_list, ocr_enabled_list = pipeline_doc_analyze(pdf_bytes_list, p_lang_list, parse_method=parse_method, formula_enable=p_formula_enable,table_enable=p_table_enable) + + for idx, model_list in enumerate(infer_results): + model_json = copy.deepcopy(model_list) + pdf_file_name = pdf_file_names[idx] + local_image_dir, local_md_dir = prepare_env(output_dir, pdf_file_name, parse_method) + image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter(local_md_dir) + + images_list = all_image_lists[idx] + pdf_doc = all_pdf_docs[idx] + _lang = lang_list[idx] + _ocr_enable = ocr_enabled_list[idx] + middle_json = pipeline_result_to_middle_json(model_list, images_list, pdf_doc, image_writer, _lang, _ocr_enable, p_formula_enable) + + pdf_info = middle_json["pdf_info"] + + pdf_bytes = pdf_bytes_list[idx] + if f_draw_layout_bbox: + draw_layout_bbox(pdf_info, pdf_bytes, local_md_dir, f"{pdf_file_name}_layout.pdf") + + if f_draw_span_bbox: + draw_span_bbox(pdf_info, pdf_bytes, local_md_dir, f"{pdf_file_name}_span.pdf") + + if f_dump_orig_pdf: + md_writer.write( + f"{pdf_file_name}_origin.pdf", + pdf_bytes, + ) + + if f_dump_md: + image_dir = str(os.path.basename(local_image_dir)) + md_content_str = pipeline_union_make(pdf_info, f_make_md_mode, image_dir) + md_writer.write_string( + f"{pdf_file_name}.md", + md_content_str, + ) + + if f_dump_content_list: + image_dir = str(os.path.basename(local_image_dir)) + content_list = pipeline_union_make(pdf_info, MakeMode.CONTENT_LIST, image_dir) + md_writer.write_string( + f"{pdf_file_name}_content_list.json", + json.dumps(content_list, ensure_ascii=False, indent=4), + ) + + if f_dump_middle_json: + md_writer.write_string( + f"{pdf_file_name}_middle.json", + json.dumps(middle_json, ensure_ascii=False, indent=4), + ) + + if f_dump_model_output: + md_writer.write_string( + f"{pdf_file_name}_model.json", + json.dumps(model_json, ensure_ascii=False, indent=4), + ) + + logger.info(f"local output dir is {local_md_dir}") + else: + if backend.startswith("vlm-"): + backend = backend[4:] + + f_draw_span_bbox = False + parse_method = "vlm" + for idx, pdf_bytes in enumerate(pdf_bytes_list): + pdf_file_name = pdf_file_names[idx] + pdf_bytes = convert_pdf_bytes_to_bytes_by_pypdfium2(pdf_bytes, start_page_id, end_page_id) + local_image_dir, local_md_dir = prepare_env(output_dir, pdf_file_name, parse_method) + image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter(local_md_dir) + middle_json, infer_result = vlm_doc_analyze(pdf_bytes, image_writer=image_writer, backend=backend, server_url=server_url) + + pdf_info = middle_json["pdf_info"] + + if f_draw_layout_bbox: + draw_layout_bbox(pdf_info, pdf_bytes, local_md_dir, f"{pdf_file_name}_layout.pdf") + + if f_draw_span_bbox: + draw_span_bbox(pdf_info, pdf_bytes, local_md_dir, f"{pdf_file_name}_span.pdf") + + if f_dump_orig_pdf: + md_writer.write( + f"{pdf_file_name}_origin.pdf", + pdf_bytes, + ) + + if f_dump_md: + image_dir = str(os.path.basename(local_image_dir)) + md_content_str = vlm_union_make(pdf_info, f_make_md_mode, image_dir) + md_writer.write_string( + f"{pdf_file_name}.md", + md_content_str, + ) + + if f_dump_content_list: + image_dir = str(os.path.basename(local_image_dir)) + content_list = vlm_union_make(pdf_info, MakeMode.CONTENT_LIST, image_dir) + md_writer.write_string( + f"{pdf_file_name}_content_list.json", + json.dumps(content_list, ensure_ascii=False, indent=4), + ) + + if f_dump_middle_json: + md_writer.write_string( + f"{pdf_file_name}_middle.json", + json.dumps(middle_json, ensure_ascii=False, indent=4), + ) + + if f_dump_model_output: + model_output = ("\n" + "-" * 50 + "\n").join(infer_result) + md_writer.write_string( + f"{pdf_file_name}_model_output.txt", + model_output, + ) + + logger.info(f"local output dir is {local_md_dir}") + + + +if __name__ == "__main__": + # pdf_path = "../../demo/pdfs/demo3.pdf" + pdf_path = "C:/Users/zhaoxiaomeng/Downloads/4546d0e2-ba60-40a5-a17e-b68555cec741.pdf" + + try: + do_parse("./output", [Path(pdf_path).stem], [read_fn(Path(pdf_path))],["ch"], + end_page_id=10, + backend='vlm-huggingface' + # backend = 'pipeline' + ) + except Exception as e: + logger.exception(e) diff --git a/mineru/cli/models_download.py b/mineru/cli/models_download.py new file mode 100644 index 0000000000000000000000000000000000000000..0a1c82ac8a546c296b7d8b59f9ebdc865a96dc81 --- /dev/null +++ b/mineru/cli/models_download.py @@ -0,0 +1,148 @@ +import json +import os +import sys +import click +import requests + +from mineru.utils.enum_class import ModelPath +from mineru.utils.models_download_utils import auto_download_and_get_model_root_path + + +def download_json(url): + """下载JSON文件""" + response = requests.get(url) + response.raise_for_status() + return response.json() + + +def download_and_modify_json(url, local_filename, modifications): + """下载JSON并修改内容""" + if os.path.exists(local_filename): + data = json.load(open(local_filename)) + config_version = data.get('config_version', '0.0.0') + if config_version < '1.3.0': + data = download_json(url) + else: + data = download_json(url) + + # 修改内容 + for key, value in modifications.items(): + if key in data: + if isinstance(data[key], dict): + # 如果是字典,合并新值 + data[key].update(value) + else: + # 否则直接替换 + data[key] = value + + # 保存修改后的内容 + with open(local_filename, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=4) + + +def configure_model(model_dir, model_type): + """配置模型""" + # json_url = 'https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/mineru.template.json' + json_url = 'https://gcore.jsdelivr.net/gh/myhloli/Magic-PDF@dev/mineru.template.json' + config_file_name = 'mineru.json' + home_dir = os.path.expanduser('~') + config_file = os.path.join(home_dir, config_file_name) + + json_mods = { + 'models-dir': { + f'{model_type}': model_dir + } + } + + download_and_modify_json(json_url, config_file, json_mods) + print(f'The configuration file has been successfully configured, the path is: {config_file}') + + +@click.command() +@click.option( + '-s', + '--source', + 'model_source', + type=click.Choice(['huggingface', 'modelscope']), + help=""" + The source of the model repository. + """, + default=None, +) +@click.option( + '-m', + '--model_type', + 'model_type', + type=click.Choice(['pipeline', 'vlm', 'all']), + help=""" + The type of the model to download. + """, + default=None, +) +def download_models(model_source, model_type): + """Download MinerU model files. + + Supports downloading pipeline or VLM models from ModelScope or HuggingFace. + """ + # 如果未显式指定则交互式输入下载来源 + if model_source is None: + model_source = click.prompt( + "Please select the model download source: ", + type=click.Choice(['huggingface', 'modelscope']), + default='huggingface' + ) + + if os.getenv('MINERU_MODEL_SOURCE', None) is None: + os.environ['MINERU_MODEL_SOURCE'] = model_source + + # 如果未显式指定则交互式输入模型类型 + if model_type is None: + model_type = click.prompt( + "Please select the model type to download: ", + type=click.Choice(['pipeline', 'vlm', 'all']), + default='all' + ) + + click.echo(f"Downloading {model_type} model from {os.getenv('MINERU_MODEL_SOURCE', None)}...") + + def download_pipeline_models(): + """下载Pipeline模型""" + model_paths = [ + ModelPath.doclayout_yolo, + ModelPath.yolo_v8_mfd, + ModelPath.unimernet_small, + ModelPath.pytorch_paddle, + ModelPath.layout_reader, + ModelPath.slanet_plus + ] + download_finish_path = "" + for model_path in model_paths: + click.echo(f"Downloading model: {model_path}") + download_finish_path = auto_download_and_get_model_root_path(model_path, repo_mode='pipeline') + click.echo(f"Pipeline models downloaded successfully to: {download_finish_path}") + configure_model(download_finish_path, model_type) + + def download_vlm_models(): + """下载VLM模型""" + download_finish_path = auto_download_and_get_model_root_path("/", repo_mode='vlm') + click.echo(f"VLM models downloaded successfully to: {download_finish_path}") + configure_model(download_finish_path, model_type) + + try: + if model_type == 'pipeline': + download_pipeline_models() + elif model_type == 'vlm': + download_vlm_models() + elif model_type == 'all': + download_pipeline_models() + download_vlm_models() + else: + click.echo(f"Unsupported model type: {model_type}", err=True) + sys.exit(1) + + except Exception as e: + click.echo(f"Download failed: {str(e)}", err=True) + sys.exit(1) + +if __name__ == '__main__': + download_models() diff --git a/mineru/cli/vlm_sglang_server.py b/mineru/cli/vlm_sglang_server.py new file mode 100644 index 0000000000000000000000000000000000000000..0aa7b54bd3fc9ccc7df826bcaaf72339fe03e8bf --- /dev/null +++ b/mineru/cli/vlm_sglang_server.py @@ -0,0 +1,4 @@ +from ..model.vlm_sglang_model.server import main + +if __name__ == "__main__": + main() diff --git a/mineru/data/__init__.py b/mineru/data/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/data/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/mineru/data/data_reader_writer/__init__.py b/mineru/data/data_reader_writer/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..241f610b758acb0be53c8f2f40c1ec56d6e39185 --- /dev/null +++ b/mineru/data/data_reader_writer/__init__.py @@ -0,0 +1,17 @@ +from .base import DataReader, DataWriter +from .dummy import DummyDataWriter +from .filebase import FileBasedDataReader, FileBasedDataWriter +from .multi_bucket_s3 import MultiBucketS3DataReader, MultiBucketS3DataWriter +from .s3 import S3DataReader, S3DataWriter + +__all__ = [ + "DataReader", + "DataWriter", + "FileBasedDataReader", + "FileBasedDataWriter", + "S3DataReader", + "S3DataWriter", + "MultiBucketS3DataReader", + "MultiBucketS3DataWriter", + "DummyDataWriter", +] diff --git a/magic_pdf/data/data_reader_writer/base.py b/mineru/data/data_reader_writer/base.py similarity index 100% rename from magic_pdf/data/data_reader_writer/base.py rename to mineru/data/data_reader_writer/base.py diff --git a/mineru/data/data_reader_writer/dummy.py b/mineru/data/data_reader_writer/dummy.py new file mode 100644 index 0000000000000000000000000000000000000000..dbcf09c0356accd7822c4a773f85643339919a2b --- /dev/null +++ b/mineru/data/data_reader_writer/dummy.py @@ -0,0 +1,11 @@ +from .base import DataWriter + + +class DummyDataWriter(DataWriter): + def write(self, path: str, data: bytes) -> None: + """Dummy write method that does nothing.""" + pass + + def write_string(self, path: str, data: str) -> None: + """Dummy write_string method that does nothing.""" + pass diff --git a/magic_pdf/data/data_reader_writer/filebase.py b/mineru/data/data_reader_writer/filebase.py similarity index 96% rename from magic_pdf/data/data_reader_writer/filebase.py rename to mineru/data/data_reader_writer/filebase.py index ff098ea0826e207663a6f51a21a4214d951f91b4..67af8e630f6086598dff5dd241c512907fcbac17 100644 --- a/magic_pdf/data/data_reader_writer/filebase.py +++ b/mineru/data/data_reader_writer/filebase.py @@ -1,6 +1,6 @@ import os -from magic_pdf.data.data_reader_writer.base import DataReader, DataWriter +from .base import DataReader, DataWriter class FileBasedDataReader(DataReader): diff --git a/magic_pdf/data/data_reader_writer/multi_bucket_s3.py b/mineru/data/data_reader_writer/multi_bucket_s3.py similarity index 93% rename from magic_pdf/data/data_reader_writer/multi_bucket_s3.py rename to mineru/data/data_reader_writer/multi_bucket_s3.py index 525209f07db93a4dd0b8b4e17bd2a5ba2453c605..0a7703ae29dbbe49bae33366fd484eaea0a245d5 100644 --- a/magic_pdf/data/data_reader_writer/multi_bucket_s3.py +++ b/mineru/data/data_reader_writer/multi_bucket_s3.py @@ -1,10 +1,9 @@ -from magic_pdf.config.exceptions import InvalidConfig, InvalidParams -from magic_pdf.data.data_reader_writer.base import DataReader, DataWriter -from magic_pdf.data.io.s3 import S3Reader, S3Writer -from magic_pdf.data.schemas import S3Config -from magic_pdf.libs.path_utils import (parse_s3_range_params, parse_s3path, - remove_non_official_s3_args) +from ..utils.exceptions import InvalidConfig, InvalidParams +from .base import DataReader, DataWriter +from ..io.s3 import S3Reader, S3Writer +from ..utils.schemas import S3Config +from ..utils.path_utils import parse_s3_range_params, parse_s3path, remove_non_official_s3_args class MultiS3Mixin: diff --git a/magic_pdf/data/data_reader_writer/s3.py b/mineru/data/data_reader_writer/s3.py similarity index 93% rename from magic_pdf/data/data_reader_writer/s3.py rename to mineru/data/data_reader_writer/s3.py index 34ec43b7c1b52ef931a8b06febba12c11ac7ab82..d96343d94f8ed094ae40c1b9c283a48a59512998 100644 --- a/magic_pdf/data/data_reader_writer/s3.py +++ b/mineru/data/data_reader_writer/s3.py @@ -1,6 +1,5 @@ -from magic_pdf.data.data_reader_writer.multi_bucket_s3 import ( - MultiBucketS3DataReader, MultiBucketS3DataWriter) -from magic_pdf.data.schemas import S3Config +from .multi_bucket_s3 import MultiBucketS3DataReader, MultiBucketS3DataWriter +from ..utils.schemas import S3Config class S3DataReader(MultiBucketS3DataReader): diff --git a/mineru/data/io/__init__.py b/mineru/data/io/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2cf63072b4da6712fc056d5f1fca256102e1c024 --- /dev/null +++ b/mineru/data/io/__init__.py @@ -0,0 +1,6 @@ + +from .base import IOReader, IOWriter +from .http import HttpReader, HttpWriter +from .s3 import S3Reader, S3Writer + +__all__ = ['IOReader', 'IOWriter', 'HttpReader', 'HttpWriter', 'S3Reader', 'S3Writer'] \ No newline at end of file diff --git a/magic_pdf/data/io/base.py b/mineru/data/io/base.py similarity index 100% rename from magic_pdf/data/io/base.py rename to mineru/data/io/base.py diff --git a/magic_pdf/data/io/http.py b/mineru/data/io/http.py similarity index 94% rename from magic_pdf/data/io/http.py rename to mineru/data/io/http.py index 3b08271f05a8ad6e2163f1e357fe66ab4a713b48..f02e36ca8f27794bb58c406fab7ee613f910e869 100644 --- a/magic_pdf/data/io/http.py +++ b/mineru/data/io/http.py @@ -3,7 +3,7 @@ import io import requests -from magic_pdf.data.io.base import IOReader, IOWriter +from .base import IOReader, IOWriter class HttpReader(IOReader): diff --git a/magic_pdf/data/io/s3.py b/mineru/data/io/s3.py similarity index 98% rename from magic_pdf/data/io/s3.py rename to mineru/data/io/s3.py index 4222c73fecdeb99283fa2d0ef419d2f3cde06cb5..949054ee2e9da0fa649ac170920b879173fcac4c 100644 --- a/magic_pdf/data/io/s3.py +++ b/mineru/data/io/s3.py @@ -1,7 +1,7 @@ import boto3 from botocore.config import Config -from magic_pdf.data.io.base import IOReader, IOWriter +from ..io.base import IOReader, IOWriter class S3Reader(IOReader): diff --git a/mineru/data/utils/__init__.py b/mineru/data/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/data/utils/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/magic_pdf/config/exceptions.py b/mineru/data/utils/exceptions.py similarity index 88% rename from magic_pdf/config/exceptions.py rename to mineru/data/utils/exceptions.py index c0b7beda3409df0daaf63aac254f337186bc2999..0b0c52c642a90a17b7e79248b76e50d2fca9b52a 100644 --- a/magic_pdf/config/exceptions.py +++ b/mineru/data/utils/exceptions.py @@ -1,3 +1,4 @@ +# Copyright (c) Opendatalab. All rights reserved. class FileNotExisted(Exception): diff --git a/magic_pdf/libs/path_utils.py b/mineru/data/utils/path_utils.py similarity index 95% rename from magic_pdf/libs/path_utils.py rename to mineru/data/utils/path_utils.py index 15fff01b5a698fbd6b1df11d9608b9ef12ffc715..fc321f6f005b757343786865d8736c98b78a80d4 100644 --- a/magic_pdf/libs/path_utils.py +++ b/mineru/data/utils/path_utils.py @@ -1,3 +1,4 @@ +# Copyright (c) Opendatalab. All rights reserved. def remove_non_official_s3_args(s3path): diff --git a/magic_pdf/data/schemas.py b/mineru/data/utils/schemas.py similarity index 92% rename from magic_pdf/data/schemas.py rename to mineru/data/utils/schemas.py index c2efb46aac565a434bbbd50568c295ca2776db2e..00634735f8c78cd96a59ade1cfdcfe00449bbfe7 100644 --- a/magic_pdf/data/schemas.py +++ b/mineru/data/utils/schemas.py @@ -1,3 +1,4 @@ +# Copyright (c) Opendatalab. All rights reserved. from pydantic import BaseModel, Field diff --git a/mineru/model/__init__.py b/mineru/model/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/model/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/mineru/model/layout/__init__.py b/mineru/model/layout/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/model/layout/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/magic_pdf/model/sub_modules/layout/doclayout_yolo/DocLayoutYOLO.py b/mineru/model/layout/doclayout_yolo.py similarity index 100% rename from magic_pdf/model/sub_modules/layout/doclayout_yolo/DocLayoutYOLO.py rename to mineru/model/layout/doclayout_yolo.py diff --git a/mineru/model/mfd/__init__.py b/mineru/model/mfd/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/model/mfd/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/magic_pdf/model/sub_modules/mfd/yolov8/YOLOv8.py b/mineru/model/mfd/yolo_v8.py similarity index 100% rename from magic_pdf/model/sub_modules/mfd/yolov8/YOLOv8.py rename to mineru/model/mfd/yolo_v8.py diff --git a/mineru/model/mfr/__init__.py b/mineru/model/mfr/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/model/mfr/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/Unimernet.py b/mineru/model/mfr/unimernet/Unimernet.py similarity index 96% rename from magic_pdf/model/sub_modules/mfr/unimernet/Unimernet.py rename to mineru/model/mfr/unimernet/Unimernet.py index 6c3a1e1d8a58d5e0f4e178875803df85c123e0d0..845a7bfc8263a867b085a41199503e74f5b03951 100644 --- a/magic_pdf/model/sub_modules/mfr/unimernet/Unimernet.py +++ b/mineru/model/mfr/unimernet/Unimernet.py @@ -19,7 +19,7 @@ class MathDataset(Dataset): class UnimernetModel(object): - def __init__(self, weight_dir, cfg_path, _device_="cpu"): + def __init__(self, weight_dir, _device_="cpu"): from .unimernet_hf import UnimernetModel if _device_.startswith("mps"): self.model = UnimernetModel.from_pretrained(weight_dir, attn_implementation="eager") @@ -70,7 +70,7 @@ class UnimernetModel(object): # Collect images with their original indices for image_index in range(len(images_mfd_res)): mfd_res = images_mfd_res[image_index] - np_array_image = images[image_index] + pil_img = images[image_index] formula_list = [] for idx, (xyxy, conf, cla) in enumerate(zip( @@ -84,7 +84,7 @@ class UnimernetModel(object): "latex": "", } formula_list.append(new_item) - bbox_img = np_array_image[ymin:ymax, xmin:xmax] + bbox_img = pil_img.crop((xmin, ymin, xmax, ymax)) area = (xmax - xmin) * (ymax - ymin) curr_idx = len(mf_image_list) diff --git a/magic_pdf/__init__.py b/mineru/model/mfr/unimernet/__init__.py similarity index 100% rename from magic_pdf/__init__.py rename to mineru/model/mfr/unimernet/__init__.py diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/__init__.py b/mineru/model/mfr/unimernet/unimernet_hf/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/__init__.py rename to mineru/model/mfr/unimernet/unimernet_hf/__init__.py diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/modeling_unimernet.py b/mineru/model/mfr/unimernet/unimernet_hf/modeling_unimernet.py similarity index 99% rename from magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/modeling_unimernet.py rename to mineru/model/mfr/unimernet/unimernet_hf/modeling_unimernet.py index a4a9bbb931b5dc12786babe3731d00586879de46..2c451c7a400a5847673b6a93103e8113c2475b76 100644 --- a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/modeling_unimernet.py +++ b/mineru/model/mfr/unimernet/unimernet_hf/modeling_unimernet.py @@ -374,6 +374,10 @@ def latex_rm_whitespace(s: str): # \qquad后补空格 s = QQUAD_PATTERN.sub(r'\\qquad ', s) + # 如果字符串以反斜杠结尾,去掉最后的反斜杠 + while s.endswith('\\'): + s = s[:-1] + return s diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_mbart/__init__.py b/mineru/model/mfr/unimernet/unimernet_hf/unimer_mbart/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_mbart/__init__.py rename to mineru/model/mfr/unimernet/unimernet_hf/unimer_mbart/__init__.py diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_mbart/configuration_unimer_mbart.py b/mineru/model/mfr/unimernet/unimernet_hf/unimer_mbart/configuration_unimer_mbart.py similarity index 100% rename from magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_mbart/configuration_unimer_mbart.py rename to mineru/model/mfr/unimernet/unimernet_hf/unimer_mbart/configuration_unimer_mbart.py diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_mbart/modeling_unimer_mbart.py b/mineru/model/mfr/unimernet/unimernet_hf/unimer_mbart/modeling_unimer_mbart.py similarity index 100% rename from magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_mbart/modeling_unimer_mbart.py rename to mineru/model/mfr/unimernet/unimernet_hf/unimer_mbart/modeling_unimer_mbart.py diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_mbart/tokenization_unimer_mbart.py b/mineru/model/mfr/unimernet/unimernet_hf/unimer_mbart/tokenization_unimer_mbart.py similarity index 100% rename from magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_mbart/tokenization_unimer_mbart.py rename to mineru/model/mfr/unimernet/unimernet_hf/unimer_mbart/tokenization_unimer_mbart.py diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_swin/__init__.py b/mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_swin/__init__.py rename to mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/__init__.py diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_swin/configuration_unimer_swin.py b/mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/configuration_unimer_swin.py similarity index 100% rename from magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_swin/configuration_unimer_swin.py rename to mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/configuration_unimer_swin.py diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_swin/image_processing_unimer_swin.py b/mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/image_processing_unimer_swin.py similarity index 50% rename from magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_swin/image_processing_unimer_swin.py rename to mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/image_processing_unimer_swin.py index a16d2433751d294bf1aed2022c466cc6dbaef15b..98d1deeebcad8667e3cf86758eb3405a426d2c7e 100644 --- a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_swin/image_processing_unimer_swin.py +++ b/mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/image_processing_unimer_swin.py @@ -1,8 +1,10 @@ +from PIL import Image, ImageOps from transformers.image_processing_utils import BaseImageProcessor import numpy as np import cv2 import albumentations as alb from albumentations.pytorch import ToTensorV2 +from torchvision.transforms.functional import resize # TODO: dereference cv2 if possible @@ -27,6 +29,21 @@ class UnimerSwinImageProcessor(BaseImageProcessor): image = self.prepare_input(item) return self.transform(image=image)['image'][:1] + @staticmethod + def crop_margin(img: Image.Image) -> Image.Image: + data = np.array(img.convert("L")) + data = data.astype(np.uint8) + max_val = data.max() + min_val = data.min() + if max_val == min_val: + return img + data = (data - min_val) / (max_val - min_val) * 255 + gray = 255 * (data < 200).astype(np.uint8) + + coords = cv2.findNonZero(gray) # Find all non-zero points (text) + a, b, w, h = cv2.boundingRect(coords) # Find minimum spanning bounding box + return img.crop((a, b, w + a, h + b)) + @staticmethod def crop_margin_numpy(img: np.ndarray) -> np.ndarray: """Crop margins of image using NumPy operations""" @@ -60,48 +77,73 @@ class UnimerSwinImageProcessor(BaseImageProcessor): if img is None: return None - # try: - # img = self.crop_margin_numpy(img) - # except Exception: - # # might throw an error for broken files - # return None + # Handle numpy array + elif isinstance(img, np.ndarray): + try: + img = self.crop_margin_numpy(img) + except Exception: + # might throw an error for broken files + return None - if img.shape[0] == 0 or img.shape[1] == 0: - return None + if img.shape[0] == 0 or img.shape[1] == 0: + return None - # Get current dimensions - h, w = img.shape[:2] - target_h, target_w = self.input_size + # Get current dimensions + h, w = img.shape[:2] + target_h, target_w = self.input_size - # Calculate scale to preserve aspect ratio (equivalent to resize + thumbnail) - scale = min(target_h / h, target_w / w) + # Calculate scale to preserve aspect ratio (equivalent to resize + thumbnail) + scale = min(target_h / h, target_w / w) - # Calculate new dimensions - new_h, new_w = int(h * scale), int(w * scale) + # Calculate new dimensions + new_h, new_w = int(h * scale), int(w * scale) - # Resize the image while preserving aspect ratio - resized_img = cv2.resize(img, (new_w, new_h)) + # Resize the image while preserving aspect ratio + resized_img = cv2.resize(img, (new_w, new_h)) - # Calculate padding values using the existing method - delta_width = target_w - new_w - delta_height = target_h - new_h + # Calculate padding values using the existing method + delta_width = target_w - new_w + delta_height = target_h - new_h - pad_width, pad_height = self._get_padding_values(new_w, new_h, random_padding) + pad_width, pad_height = self._get_padding_values(new_w, new_h, random_padding) - # Apply padding (convert PIL padding format to OpenCV format) - padding_color = [0, 0, 0] if len(img.shape) == 3 else [0] - - padded_img = cv2.copyMakeBorder( - resized_img, - pad_height, # top - delta_height - pad_height, # bottom - pad_width, # left - delta_width - pad_width, # right - cv2.BORDER_CONSTANT, - value=padding_color - ) + # Apply padding (convert PIL padding format to OpenCV format) + padding_color = [0, 0, 0] if len(img.shape) == 3 else [0] + + padded_img = cv2.copyMakeBorder( + resized_img, + pad_height, # top + delta_height - pad_height, # bottom + pad_width, # left + delta_width - pad_width, # right + cv2.BORDER_CONSTANT, + value=padding_color + ) - return padded_img + return padded_img + + # Handle PIL Image + elif isinstance(img, Image.Image): + try: + img = self.crop_margin(img.convert("RGB")) + except OSError: + # might throw an error for broken files + return None + + if img.height == 0 or img.width == 0: + return None + + # Resize while preserving aspect ratio + img = resize(img, min(self.input_size)) + img.thumbnail((self.input_size[1], self.input_size[0])) + new_w, new_h = img.width, img.height + + # Calculate and apply padding + padding = self._calculate_padding(new_w, new_h, random_padding) + return np.array(ImageOps.expand(img, padding)) + + else: + return None def _calculate_padding(self, new_w, new_h, random_padding): """Calculate padding values for PIL images""" diff --git a/magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_swin/modeling_unimer_swin.py b/mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/modeling_unimer_swin.py similarity index 100% rename from magic_pdf/model/sub_modules/mfr/unimernet/unimernet_hf/unimer_swin/modeling_unimer_swin.py rename to mineru/model/mfr/unimernet/unimernet_hf/unimer_swin/modeling_unimer_swin.py diff --git a/mineru/model/ocr/__init__.py b/mineru/model/ocr/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/model/ocr/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/mineru/model/ocr/paddleocr2pytorch/__init__.py b/mineru/model/ocr/paddleocr2pytorch/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/model/ocr/paddleocr2pytorch/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorch_paddle.py b/mineru/model/ocr/paddleocr2pytorch/pytorch_paddle.py similarity index 88% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorch_paddle.py rename to mineru/model/ocr/paddleocr2pytorch/pytorch_paddle.py index 448bfda9287fb2ac63ba0ef92b6552fe21bb7680..3f5095d459910c5a72567be4a7bf5ceb2f327754 100644 --- a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorch_paddle.py +++ b/mineru/model/ocr/paddleocr2pytorch/pytorch_paddle.py @@ -1,6 +1,6 @@ # Copyright (c) Opendatalab. All rights reserved. import copy -import os.path +import os import warnings from pathlib import Path @@ -9,8 +9,10 @@ import numpy as np import yaml from loguru import logger -from magic_pdf.libs.config_reader import get_device, get_local_models_dir -from .ocr_utils import check_img, preprocess_image, sorted_boxes, merge_det_boxes, update_det_boxes, get_rotate_crop_image +from mineru.utils.config_reader import get_device +from mineru.utils.enum_class import ModelPath +from mineru.utils.models_download_utils import auto_download_and_get_model_root_path +from ....utils.ocr_utils import check_img, preprocess_image, sorted_boxes, merge_det_boxes, update_det_boxes, get_rotate_crop_image from .tools.infer.predict_system import TextSystem from .tools.infer import pytorchocr_utility as utility import argparse @@ -55,7 +57,7 @@ class PytorchPaddleOCR(TextSystem): self.lang = kwargs.get('lang', 'ch') device = get_device() - if device == 'cpu' and self.lang in ['ch', 'ch_server']: + if device == 'cpu' and self.lang in ['ch', 'ch_server', 'japan', 'chinese_cht']: logger.warning("The current device in use is CPU. To ensure the speed of parsing, the language is automatically switched to ch_lite.") self.lang = 'ch_lite' @@ -74,9 +76,14 @@ class PytorchPaddleOCR(TextSystem): with open(models_config_path) as file: config = yaml.safe_load(file) det, rec, dict_file = get_model_params(self.lang, config) - ocr_models_dir = os.path.join(get_local_models_dir(), 'OCR', 'paddleocr_torch') - kwargs['det_model_path'] = os.path.join(ocr_models_dir, det) - kwargs['rec_model_path'] = os.path.join(ocr_models_dir, rec) + ocr_models_dir = ModelPath.pytorch_paddle + + det_model_path = f"{ocr_models_dir}/{det}" + det_model_path = os.path.join(auto_download_and_get_model_root_path(det_model_path), det_model_path) + rec_model_path = f"{ocr_models_dir}/{rec}" + rec_model_path = os.path.join(auto_download_and_get_model_root_path(rec_model_path), rec_model_path) + kwargs['det_model_path'] = det_model_path + kwargs['rec_model_path'] = rec_model_path kwargs['rec_char_dict_path'] = os.path.join(root_dir, 'pytorchocr', 'utils', 'resources', 'dict', dict_file) # kwargs['rec_batch_num'] = 8 diff --git a/magic_pdf/config/__init__.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/__init__.py old mode 100644 new mode 100755 similarity index 100% rename from magic_pdf/config/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/__init__.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/base_ocr_v20.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/base_ocr_v20.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/base_ocr_v20.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/base_ocr_v20.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/data/__init__.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/data/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/data/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/data/__init__.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/data/imaug/__init__.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/data/imaug/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/data/imaug/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/data/imaug/__init__.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/data/imaug/operators.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/data/imaug/operators.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/data/imaug/operators.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/data/imaug/operators.py diff --git a/magic_pdf/data/__init__.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/__init__.py similarity index 100% rename from magic_pdf/data/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/__init__.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/architectures/__init__.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/architectures/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/architectures/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/architectures/__init__.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/architectures/base_model.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/architectures/base_model.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/architectures/base_model.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/architectures/base_model.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/__init__.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/__init__.py similarity index 96% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/__init__.py index 7f437a2388b1640995e0909595fcb1eaf6544dff..e4715ee7a7da16f90056381e1ff6f9112b68cf1c 100644 --- a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/__init__.py +++ b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/__init__.py @@ -20,6 +20,7 @@ def build_backbone(config, model_type): from .det_mobilenet_v3 import MobileNetV3 from .rec_hgnet import PPHGNet_small from .rec_lcnetv3 import PPLCNetV3 + from .rec_pphgnetv2 import PPHGNetV2_B4 support_dict = [ "MobileNetV3", @@ -28,6 +29,7 @@ def build_backbone(config, model_type): "ResNet_SAST", "PPLCNetV3", "PPHGNet_small", + 'PPHGNetV2_B4', ] elif model_type == "rec" or model_type == "cls": from .rec_hgnet import PPHGNet_small diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/det_mobilenet_v3.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/det_mobilenet_v3.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/det_mobilenet_v3.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/det_mobilenet_v3.py diff --git a/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_donut_swin.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_donut_swin.py new file mode 100644 index 0000000000000000000000000000000000000000..73bb3950786366a897a4a891f7547deda167ed82 --- /dev/null +++ b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_donut_swin.py @@ -0,0 +1,1277 @@ +import collections.abc +from collections import OrderedDict +import math +from dataclasses import dataclass +from typing import Optional, Tuple, Union + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class DonutSwinConfig(object): + model_type = "donut-swin" + + attribute_map = { + "num_attention_heads": "num_heads", + "num_hidden_layers": "num_layers", + } + + def __init__( + self, + image_size=224, + patch_size=4, + num_channels=3, + embed_dim=96, + depths=[2, 2, 6, 2], + num_heads=[3, 6, 12, 24], + window_size=7, + mlp_ratio=4.0, + qkv_bias=True, + hidden_dropout_prob=0.0, + attention_probs_dropout_prob=0.0, + drop_path_rate=0.1, + hidden_act="gelu", + use_absolute_embeddings=False, + initializer_range=0.02, + layer_norm_eps=1e-5, + **kwargs, + ): + super().__init__() + + self.image_size = image_size + self.patch_size = patch_size + self.num_channels = num_channels + self.embed_dim = embed_dim + self.depths = depths + self.num_layers = len(depths) + self.num_heads = num_heads + self.window_size = window_size + self.mlp_ratio = mlp_ratio + self.qkv_bias = qkv_bias + self.hidden_dropout_prob = hidden_dropout_prob + self.attention_probs_dropout_prob = attention_probs_dropout_prob + self.drop_path_rate = drop_path_rate + self.hidden_act = hidden_act + self.use_absolute_embeddings = use_absolute_embeddings + self.layer_norm_eps = layer_norm_eps + self.initializer_range = initializer_range + self.hidden_size = int(embed_dim * 2 ** (len(depths) - 1)) + + for key, value in kwargs.items(): + try: + setattr(self, key, value) + except AttributeError as err: + print(f"Can't set {key} with value {value} for {self}") + raise err + + +@dataclass +# Copied from transformers.models.swin.modeling_swin.SwinEncoderOutput with Swin->DonutSwin +class DonutSwinEncoderOutput(OrderedDict): + last_hidden_state = None + hidden_states = None + attentions = None + reshaped_hidden_states = None + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def __getitem__(self, k): + if isinstance(k, str): + inner_dict = dict(self.items()) + return inner_dict[k] + else: + return self.to_tuple()[k] + + def __setattr__(self, name, value): + if name in self.keys() and value is not None: + super().__setitem__(name, value) + super().__setattr__(name, value) + + def __setitem__(self, key, value): + super().__setitem__(key, value) + super().__setattr__(key, value) + + def to_tuple(self): + """ + Convert self to a tuple containing all the attributes/keys that are not `None`. + """ + return tuple(self[k] for k in self.keys()) + + +@dataclass +# Copied from transformers.models.swin.modeling_swin.SwinModelOutput with Swin->DonutSwin +class DonutSwinModelOutput(OrderedDict): + last_hidden_state = None + pooler_output = None + hidden_states = None + attentions = None + reshaped_hidden_states = None + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def __getitem__(self, k): + if isinstance(k, str): + inner_dict = dict(self.items()) + return inner_dict[k] + else: + return self.to_tuple()[k] + + def __setattr__(self, name, value): + if name in self.keys() and value is not None: + super().__setitem__(name, value) + super().__setattr__(name, value) + + def __setitem__(self, key, value): + super().__setitem__(key, value) + super().__setattr__(key, value) + + def to_tuple(self): + """ + Convert self to a tuple containing all the attributes/keys that are not `None`. + """ + return tuple(self[k] for k in self.keys()) + + +# Copied from transformers.models.swin.modeling_swin.window_partition +def window_partition(input_feature, window_size): + """ + Partitions the given input into windows. + """ + batch_size, height, width, num_channels = input_feature.shape + input_feature = input_feature.reshape( + [ + batch_size, + height // window_size, + window_size, + width // window_size, + window_size, + num_channels, + ] + ) + windows = input_feature.transpose([0, 1, 3, 2, 4, 5]).reshape( + [-1, window_size, window_size, num_channels] + ) + return windows + + +# Copied from transformers.models.swin.modeling_swin.window_reverse +def window_reverse(windows, window_size, height, width): + """ + Merges windows to produce higher resolution features. + """ + num_channels = windows.shape[-1] + windows = windows.reshape( + [ + -1, + height // window_size, + width // window_size, + window_size, + window_size, + num_channels, + ] + ) + windows = windows.transpose([0, 1, 3, 2, 4, 5]).reshape( + [-1, height, width, num_channels] + ) + return windows + + +# Copied from transformers.models.swin.modeling_swin.SwinEmbeddings with Swin->DonutSwin +class DonutSwinEmbeddings(nn.Module): + """ + Construct the patch and position embeddings. Optionally, also the mask token. + """ + + def __init__(self, config, use_mask_token=False): + super().__init__() + + self.patch_embeddings = DonutSwinPatchEmbeddings(config) + num_patches = self.patch_embeddings.num_patches + self.patch_grid = self.patch_embeddings.grid_size + if use_mask_token: + # self.mask_token = paddle.create_parameter( + # [1, 1, config.embed_dim], dtype="float32" + # ) + self.mask_token = nn.Parameter( + nn.init.xavier_uniform_(torch.zeros(1, 1, config.embed_dim).to(torch.float32)) + ) + nn.init.zeros_(self.mask_token) + else: + self.mask_token = None + if config.use_absolute_embeddings: + # self.position_embeddings = paddle.create_parameter( + # [1, num_patches + 1, config.embed_dim], dtype="float32" + # ) + self.position_embeddings = nn.Parameter( + nn.init.xavier_uniform_(torch.zeros(1, num_patches + 1, config.embed_dim).to(torch.float32)) + ) + nn.init.zeros_(self.position_embedding) + else: + self.position_embeddings = None + + self.norm = nn.LayerNorm(config.embed_dim) + self.dropout = nn.Dropout(config.hidden_dropout_prob) + + def forward(self, pixel_values, bool_masked_pos=None): + + embeddings, output_dimensions = self.patch_embeddings(pixel_values) + embeddings = self.norm(embeddings) + + batch_size, seq_len, _ = embeddings.shape + + if bool_masked_pos is not None: + mask_tokens = self.mask_token.expand(batch_size, seq_len, -1) + mask = bool_masked_pos.unsqueeze(-1).type_as(mask_tokens) + embeddings = embeddings * (1.0 - mask) + mask_tokens * mask + + if self.position_embeddings is not None: + embeddings = embeddings + self.position_embeddings + embeddings = self.dropout(embeddings) + return embeddings, output_dimensions + + +class MyConv2d(nn.Conv2d): + def __init__( + self, + in_channel, + out_channels, + kernel_size, + stride=1, + padding="SAME", + dilation=1, + groups=1, + bias_attr=False, + eps=1e-6, + ): + super().__init__( + in_channel, + out_channels, + kernel_size, + stride=stride, + padding=padding, + dilation=dilation, + groups=groups, + bias_attr=bias_attr, + ) + # self.weight = paddle.create_parameter( + # [out_channels, in_channel, kernel_size[0], kernel_size[1]], dtype="float32" + # ) + self.weight = torch.Parameter( + nn.init.xavier_uniform_( + torch.zeros(out_channels, in_channel, kernel_size[0], kernel_size[1]).to(torch.float32) + ) + ) + # self.bias = paddle.create_parameter([out_channels], dtype="float32") + self.bias = torch.Parameter( + nn.init.xavier_uniform_( + torch.zeros(out_channels).to(torch.float32) + ) + ) + nn.init.ones_(self.weight) + nn.init.zeros_(self.bias) + + def forward(self, x): + x = F.conv2d( + x, + self.weight, + self.bias, + self._stride, + self._padding, + self._dilation, + self._groups, + ) + return x + + +# Copied from transformers.models.swin.modeling_swin.SwinPatchEmbeddings +class DonutSwinPatchEmbeddings(nn.Module): + """ + This class turns `pixel_values` of shape `(batch_size, num_channels, height, width)` into the initial + `hidden_states` (patch embeddings) of shape `(batch_size, seq_length, hidden_size)` to be consumed by a + Transformer. + """ + + def __init__(self, config): + super().__init__() + image_size, patch_size = config.image_size, config.patch_size + num_channels, hidden_size = config.num_channels, config.embed_dim + image_size = ( + image_size + if isinstance(image_size, collections.abc.Iterable) + else (image_size, image_size) + ) + patch_size = ( + patch_size + if isinstance(patch_size, collections.abc.Iterable) + else (patch_size, patch_size) + ) + num_patches = (image_size[1] // patch_size[1]) * ( + image_size[0] // patch_size[0] + ) + self.image_size = image_size + self.patch_size = patch_size + self.num_channels = num_channels + self.num_patches = num_patches + self.is_export = config.is_export + self.grid_size = ( + image_size[0] // patch_size[0], + image_size[1] // patch_size[1], + ) + self.projection = nn.Conv2D( + num_channels, hidden_size, kernel_size=patch_size, stride=patch_size + ) + + def maybe_pad(self, pixel_values, height, width): + if width % self.patch_size[1] != 0: + pad_values = (0, self.patch_size[1] - width % self.patch_size[1]) + if self.is_export: + pad_values = torch.tensor(pad_values, dtype=torch.int32) + pixel_values = nn.functional.pad(pixel_values, pad_values) + if height % self.patch_size[0] != 0: + pad_values = (0, 0, 0, self.patch_size[0] - height % self.patch_size[0]) + if self.is_export: + pad_values = torch.tensor(pad_values, dtype=torch.int32) + pixel_values = nn.functional.pad(pixel_values, pad_values) + return pixel_values + + def forward(self, pixel_values) -> Tuple[torch.Tensor, Tuple[int]]: + _, num_channels, height, width = pixel_values.shape + if num_channels != self.num_channels: + raise ValueError( + "Make sure that the channel dimension of the pixel values match with the one set in the configuration." + ) + pixel_values = self.maybe_pad(pixel_values, height, width) + embeddings = self.projection(pixel_values) + + _, _, height, width = embeddings.shape + output_dimensions = (height, width) + embeddings = embeddings.flatten(2).transpose([0, 2, 1]) + + return embeddings, output_dimensions + + +# Copied from transformers.models.swin.modeling_swin.SwinPatchMerging +class DonutSwinPatchMerging(nn.Module): + """ + Patch Merging Layer. + + Args: + input_resolution (`Tuple[int]`): + Resolution of input feature. + dim (`int`): + Number of input channels. + norm_layer (`nn.Module`, *optional*, defaults to `nn.LayerNorm`): + Normalization layer class. + """ + + def __init__( + self, + input_resolution: Tuple[int], + dim: int, + norm_layer: nn.Module = nn.LayerNorm, + is_export=False, + ): + super().__init__() + self.input_resolution = input_resolution + self.dim = dim + self.reduction = nn.Linear(4 * dim, 2 * dim, bias_attr=False) + self.norm = norm_layer(4 * dim) + self.is_export = is_export + + def maybe_pad(self, input_feature, height, width): + should_pad = (height % 2 == 1) or (width % 2 == 1) + if should_pad: + pad_values = (0, 0, 0, width % 2, 0, height % 2) + if self.is_export: + pad_values = torch.tensor(pad_values, dtype=torch.int32) + input_feature = nn.functional.pad(input_feature, pad_values) + + return input_feature + + def forward( + self, input_feature: torch.Tensor, input_dimensions: Tuple[int, int] + ) -> torch.Tensor: + height, width = input_dimensions + batch_size, dim, num_channels = input_feature.shape + + input_feature = input_feature.reshape([batch_size, height, width, num_channels]) + + input_feature = self.maybe_pad(input_feature, height, width) + input_feature_0 = input_feature[:, 0::2, 0::2, :] + input_feature_1 = input_feature[:, 1::2, 0::2, :] + input_feature_2 = input_feature[:, 0::2, 1::2, :] + input_feature_3 = input_feature[:, 1::2, 1::2, :] + input_feature = torch.cat( + [input_feature_0, input_feature_1, input_feature_2, input_feature_3], -1 + ) + input_feature = input_feature.reshape( + [batch_size, -1, 4 * num_channels] + ) # batch_size height/2*width/2 4*C + + input_feature = self.norm(input_feature) + input_feature = self.reduction(input_feature) + + return input_feature + + +# Copied from transformers.models.beit.modeling_beit.drop_path +def drop_path( + input: torch.Tensor, drop_prob: float = 0.0, training: bool = False +) -> torch.Tensor: + if drop_prob == 0.0 or not training: + return input + keep_prob = 1 - drop_prob + shape = (input.shape[0],) + (1,) * ( + input.ndim - 1 + ) # work with diff dim tensors, not just 2D ConvNets + random_tensor = keep_prob + torch.rand( + shape, + dtype=input.dtype, + ) + random_tensor.floor_() # binarize + output = input / keep_prob * random_tensor + return output + + +# Copied from transformers.models.swin.modeling_swin.SwinDropPath +class DonutSwinDropPath(nn.Module): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).""" + + def __init__(self, drop_prob: Optional[float] = None) -> None: + super().__init__() + self.drop_prob = drop_prob + + def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: + return drop_path(hidden_states, self.drop_prob, self.training) + + def extra_repr(self) -> str: + return "p={}".format(self.drop_prob) + + +class DonutSwinSelfAttention(nn.Module): + def __init__(self, config, dim, num_heads, window_size): + super().__init__() + if dim % num_heads != 0: + raise ValueError( + f"The hidden size ({dim}) is not a multiple of the number of attention heads ({num_heads})" + ) + + self.num_attention_heads = num_heads + self.attention_head_size = int(dim / num_heads) + self.all_head_size = self.num_attention_heads * self.attention_head_size + self.window_size = ( + window_size + if isinstance(window_size, collections.abc.Iterable) + else (window_size, window_size) + ) + # self.relative_position_bias_table = paddle.create_parameter( + # [(2 * self.window_size[0] - 1) * (2 * self.window_size[1] - 1), num_heads], + # dtype="float32", + # ) + self.relative_position_bias_table = torch.Parameter( + nn.init.xavier_normal_( + torch.zeros((2 * self.window_size[0] - 1) * (2 * self.window_size[1] - 1), num_heads).to(torch.float32) + ) + ) + + nn.init.zeros_(self.relative_position_bias_table) + + # get pair-wise relative position index for each token inside the window + coords_h = torch.arange(self.window_size[0]) + coords_w = torch.arange(self.window_size[1]) + coords = torch.stack(torch.meshgrid(coords_h, coords_w, indexing="ij")) + coords_flatten = torch.flatten(coords, 1) + relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] + relative_coords = relative_coords.transpose([1, 2, 0]) + relative_coords[:, :, 0] += self.window_size[0] - 1 + relative_coords[:, :, 1] += self.window_size[1] - 1 + relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1 + relative_position_index = relative_coords.sum(-1) + self.register_buffer("relative_position_index", relative_position_index) + + self.query = nn.Linear( + self.all_head_size, self.all_head_size, bias_attr=config.qkv_bias + ) + self.key = nn.Linear( + self.all_head_size, self.all_head_size, bias_attr=config.qkv_bias + ) + self.value = nn.Linear( + self.all_head_size, self.all_head_size, bias_attr=config.qkv_bias + ) + + self.dropout = nn.Dropout(config.attention_probs_dropout_prob) + + def transpose_for_scores(self, x): + new_x_shape = x.shape[:-1] + [ + self.num_attention_heads, + self.attention_head_size, + ] + x = x.reshape(new_x_shape) + return x.transpose([0, 2, 1, 3]) + + def forward( + self, + hidden_states: torch.Tensor, + attention_mask=None, + head_mask=None, + output_attentions=False, + ) -> Tuple[torch.Tensor]: + batch_size, dim, num_channels = hidden_states.shape + mixed_query_layer = self.query(hidden_states) + key_layer = self.transpose_for_scores(self.key(hidden_states)) + value_layer = self.transpose_for_scores(self.value(hidden_states)) + query_layer = self.transpose_for_scores(mixed_query_layer) + + # Take the dot product between "query" and "key" to get the raw attention scores. + attention_scores = torch.matmul(query_layer, key_layer.transpose([0, 1, 3, 2])) + + attention_scores = attention_scores / math.sqrt(self.attention_head_size) + + relative_position_bias = self.relative_position_bias_table[ + self.relative_position_index.reshape([-1]) + ] + relative_position_bias = relative_position_bias.reshape( + [ + self.window_size[0] * self.window_size[1], + self.window_size[0] * self.window_size[1], + -1, + ] + ) + + relative_position_bias = relative_position_bias.transpose([2, 0, 1]) + attention_scores = attention_scores + relative_position_bias.unsqueeze(0) + + if attention_mask is not None: + # Apply the attention mask is (precomputed for all layers in DonutSwinModel forward() function) + mask_shape = attention_mask.shape[0] + attention_scores = attention_scores.reshape( + [ + batch_size // mask_shape, + mask_shape, + self.num_attention_heads, + dim, + dim, + ] + ) + attention_scores = attention_scores + attention_mask.unsqueeze(1).unsqueeze( + 0 + ) + attention_scores = attention_scores.reshape( + [-1, self.num_attention_heads, dim, dim] + ) + + # Normalize the attention scores to probabilities. + attention_probs = nn.functional.softmax(attention_scores, axis=-1) + + # This is actually dropping out entire tokens to attend to, which might + # seem a bit unusual, but is taken from the original Transformer paper. + attention_probs = self.dropout(attention_probs) + + # Mask heads if we want to + if head_mask is not None: + attention_probs = attention_probs * head_mask + + context_layer = torch.matmul(attention_probs, value_layer) + context_layer = context_layer.transpose([0, 2, 1, 3]) + new_context_layer_shape = tuple(context_layer.shape[:-2]) + ( + self.all_head_size, + ) + context_layer = context_layer.reshape(new_context_layer_shape) + outputs = ( + (context_layer, attention_probs) if output_attentions else (context_layer,) + ) + return outputs + + +# Copied from transformers.models.swin.modeling_swin.SwinSelfOutput +class DonutSwinSelfOutput(nn.Module): + def __init__(self, config, dim): + super().__init__() + self.dense = nn.Linear(dim, dim) + self.dropout = nn.Dropout(config.attention_probs_dropout_prob) + + def forward( + self, hidden_states: torch.Tensor, input_tensor: torch.Tensor + ) -> torch.Tensor: + hidden_states = self.dense(hidden_states) + hidden_states = self.dropout(hidden_states) + + return hidden_states + + +# Copied from transformers.models.swin.modeling_swin.SwinAttention with Swin->DonutSwin +class DonutSwinAttention(nn.Module): + def __init__(self, config, dim, num_heads, window_size): + super().__init__() + self.self = DonutSwinSelfAttention(config, dim, num_heads, window_size) + self.output = DonutSwinSelfOutput(config, dim) + self.pruned_heads = set() + + def forward( + self, + hidden_states: torch.Tensor, + attention_mask=None, + head_mask=None, + output_attentions=False, + ) -> Tuple[torch.Tensor]: + self_outputs = self.self( + hidden_states, attention_mask, head_mask, output_attentions + ) + attention_output = self.output(self_outputs[0], hidden_states) + outputs = (attention_output,) + self_outputs[ + 1: + ] # add attentions if we output them + return outputs + + +# Copied from transformers.models.swin.modeling_swin.SwinIntermediate +class DonutSwinIntermediate(nn.Module): + def __init__(self, config, dim): + super().__init__() + self.dense = nn.Linear(dim, int(config.mlp_ratio * dim)) + self.intermediate_act_fn = F.gelu + + def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: + hidden_states = self.dense(hidden_states) + hidden_states = self.intermediate_act_fn(hidden_states) + return hidden_states + + +# Copied from transformers.models.swin.modeling_swin.SwinOutput +class DonutSwinOutput(nn.Module): + def __init__(self, config, dim): + super().__init__() + self.dense = nn.Linear(int(config.mlp_ratio * dim), dim) + self.dropout = nn.Dropout(config.hidden_dropout_prob) + + def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: + hidden_states = self.dense(hidden_states) + hidden_states = self.dropout(hidden_states) + return hidden_states + + +# Copied from transformers.models.swin.modeling_swin.SwinLayer with Swin->DonutSwin +class DonutSwinLayer(nn.Module): + def __init__(self, config, dim, input_resolution, num_heads, shift_size=0): + super().__init__() + self.chunk_size_feed_forward = config.chunk_size_feed_forward + self.shift_size = shift_size + self.window_size = config.window_size + self.input_resolution = input_resolution + self.layernorm_before = nn.LayerNorm(dim, eps=config.layer_norm_eps) + self.attention = DonutSwinAttention( + config, dim, num_heads, window_size=self.window_size + ) + self.drop_path = ( + DonutSwinDropPath(config.drop_path_rate) + if config.drop_path_rate > 0.0 + else nn.Identity() + ) + self.layernorm_after = nn.LayerNorm(dim, eps=config.layer_norm_eps) + self.intermediate = DonutSwinIntermediate(config, dim) + self.output = DonutSwinOutput(config, dim) + self.is_export = config.is_export + + def set_shift_and_window_size(self, input_resolution): + if min(input_resolution) <= self.window_size: + # if window size is larger than input resolution, we don't partition windows + self.shift_size = 0 + self.window_size = min(input_resolution) + + def get_attn_mask_export(self, height, width, dtype): + + attn_mask = None + height_slices = ( + slice(0, -self.window_size), + slice(-self.window_size, -self.shift_size), + slice(-self.shift_size, None), + ) + width_slices = ( + slice(0, -self.window_size), + slice(-self.window_size, -self.shift_size), + slice(-self.shift_size, None), + ) + img_mask = torch.zeros((1, height, width, 1), dtype=dtype) + count = 0 + for height_slice in height_slices: + for width_slice in width_slices: + if self.shift_size > 0: + img_mask[:, height_slice, width_slice, :] = count + count += 1 + if torch.Tensor(self.shift_size > 0).to(torch.bool): + # calculate attention mask for SW-MSA + mask_windows = window_partition(img_mask, self.window_size) + mask_windows = mask_windows.reshape( + [-1, self.window_size * self.window_size] + ) + attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2) + attn_mask = attn_mask.masked_fill( + attn_mask != 0, float(-100.0) + ).masked_fill(attn_mask == 0, float(0.0)) + + return attn_mask + + def get_attn_mask(self, height, width, dtype): + if self.shift_size > 0: + # calculate attention mask for SW-MSA + img_mask = torch.zeros((1, height, width, 1), dtype=dtype) + height_slices = ( + slice(0, -self.window_size), + slice(-self.window_size, -self.shift_size), + slice(-self.shift_size, None), + ) + width_slices = ( + slice(0, -self.window_size), + slice(-self.window_size, -self.shift_size), + slice(-self.shift_size, None), + ) + + count = 0 + for height_slice in height_slices: + for width_slice in width_slices: + img_mask[:, height_slice, width_slice, :] = count + count += 1 + + mask_windows = window_partition(img_mask, self.window_size) + mask_windows = mask_windows.reshape( + [-1, self.window_size * self.window_size] + ) + attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2) + attn_mask = attn_mask.masked_fill( + attn_mask != 0, float(-100.0) + ).masked_fill(attn_mask == 0, float(0.0)) + else: + attn_mask = None + return attn_mask + + def maybe_pad(self, hidden_states, height, width): + pad_right = (self.window_size - width % self.window_size) % self.window_size + pad_bottom = (self.window_size - height % self.window_size) % self.window_size + pad_values = (0, 0, 0, pad_bottom, 0, pad_right, 0, 0) + hidden_states = nn.functional.pad(hidden_states, pad_values) + return hidden_states, pad_values + + def forward( + self, + hidden_states: torch.Tensor, + input_dimensions: Tuple[int, int], + head_mask=None, + output_attentions=False, + always_partition=False, + ) -> Tuple[torch.Tensor, torch.Tensor]: + if not always_partition: + self.set_shift_and_window_size(input_dimensions) + else: + pass + height, width = input_dimensions + batch_size, _, channels = hidden_states.shape + shortcut = hidden_states + + hidden_states = self.layernorm_before(hidden_states) + + hidden_states = hidden_states.reshape([batch_size, height, width, channels]) + + # pad hidden_states to multiples of window size + hidden_states, pad_values = self.maybe_pad(hidden_states, height, width) + + _, height_pad, width_pad, _ = hidden_states.shape + + # cyclic shift + if self.shift_size > 0: + shift_value = (-self.shift_size, -self.shift_size) + if self.is_export: + shift_value = torch.tensor(shift_value, dtype=torch.int32) + shifted_hidden_states = torch.roll( + hidden_states, shifts=shift_value, dims=(1, 2) + ) + else: + shifted_hidden_states = hidden_states + + # partition windows + hidden_states_windows = window_partition( + shifted_hidden_states, self.window_size + ) + hidden_states_windows = hidden_states_windows.reshape( + [-1, self.window_size * self.window_size, channels] + ) + attn_mask = self.get_attn_mask(height_pad, width_pad, dtype=hidden_states.dtype) + + attention_outputs = self.attention( + hidden_states_windows, + attn_mask, + head_mask, + output_attentions=output_attentions, + ) + attention_output = attention_outputs[0] + + attention_windows = attention_output.reshape( + [-1, self.window_size, self.window_size, channels] + ) + shifted_windows = window_reverse( + attention_windows, self.window_size, height_pad, width_pad + ) + # reverse cyclic shift + if self.shift_size > 0: + shift_value = (self.shift_size, self.shift_size) + if self.is_export: + shift_value = torch.tensor(shift_value, dtype=torch.int32) + attention_windows = torch.roll( + shifted_windows, shifts=shift_value, dims=(1, 2) + ) + else: + attention_windows = shifted_windows + + was_padded = pad_values[3] > 0 or pad_values[5] > 0 + if was_padded: + attention_windows = attention_windows[:, :height, :width, :].contiguous() + + attention_windows = attention_windows.reshape( + [batch_size, height * width, channels] + ) + hidden_states = shortcut + self.drop_path(attention_windows) + layer_output = self.layernorm_after(hidden_states) + layer_output = self.intermediate(layer_output) + layer_output = hidden_states + self.output(layer_output) + layer_outputs = ( + (layer_output, attention_outputs[1]) + if output_attentions + else (layer_output,) + ) + return layer_outputs + + +# Copied from transformers.models.swin.modeling_swin.SwinStage with Swin->DonutSwin +class DonutSwinStage(nn.Module): + def __init__( + self, config, dim, input_resolution, depth, num_heads, drop_path, downsample + ): + super().__init__() + self.config = config + self.dim = dim + self.blocks = nn.ModuleList( + [ + DonutSwinLayer( + config=config, + dim=dim, + input_resolution=input_resolution, + num_heads=num_heads, + shift_size=0 if (i % 2 == 0) else config.window_size // 2, + ) + for i in range(depth) + ] + ) + self.is_export = config.is_export + + # patch merging layer + if downsample is not None: + self.downsample = downsample( + input_resolution, + dim=dim, + norm_layer=nn.LayerNorm, + is_export=self.is_export, + ) + else: + self.downsample = None + + self.pointing = False + + def forward( + self, + hidden_states: torch.Tensor, + input_dimensions: Tuple[int, int], + head_mask=None, + output_attentions=False, + always_partition=False, + ) -> Tuple[torch.Tensor]: + height, width = input_dimensions + + for i, layer_module in enumerate(self.blocks): + layer_head_mask = head_mask[i] if head_mask is not None else None + + layer_outputs = layer_module( + hidden_states, + input_dimensions, + layer_head_mask, + output_attentions, + always_partition, + ) + + hidden_states = layer_outputs[0] + + hidden_states_before_downsampling = hidden_states + if self.downsample is not None: + height_downsampled, width_downsampled = (height + 1) // 2, (width + 1) // 2 + output_dimensions = (height, width, height_downsampled, width_downsampled) + hidden_states = self.downsample( + hidden_states_before_downsampling, input_dimensions + ) + else: + output_dimensions = (height, width, height, width) + + stage_outputs = ( + hidden_states, + hidden_states_before_downsampling, + output_dimensions, + ) + + if output_attentions: + stage_outputs += layer_outputs[1:] + return stage_outputs + + +# Copied from transformers.models.swin.modeling_swin.SwinEncoder with Swin->DonutSwin +class DonutSwinEncoder(nn.Module): + def __init__(self, config, grid_size): + super().__init__() + self.num_layers = len(config.depths) + self.config = config + dpr = [ + x.item() + for x in torch.linspace(0, config.drop_path_rate, sum(config.depths)) + ] + self.layers = nn.ModuleList( + [ + DonutSwinStage( + config=config, + dim=int(config.embed_dim * 2**i_layer), + input_resolution=( + grid_size[0] // (2**i_layer), + grid_size[1] // (2**i_layer), + ), + depth=config.depths[i_layer], + num_heads=config.num_heads[i_layer], + drop_path=dpr[ + sum(config.depths[:i_layer]) : sum(config.depths[: i_layer + 1]) + ], + downsample=( + DonutSwinPatchMerging + if (i_layer < self.num_layers - 1) + else None + ), + ) + for i_layer in range(self.num_layers) + ] + ) + + self.gradient_checkpointing = False + + def forward( + self, + hidden_states: torch.Tensor, + input_dimensions: Tuple[int, int], + head_mask=None, + output_attentions=False, + output_hidden_states=False, + output_hidden_states_before_downsampling=False, + always_partition=False, + return_dict=True, + ): + all_hidden_states = () if output_hidden_states else None + all_reshaped_hidden_states = () if output_hidden_states else None + all_self_attentions = () if output_attentions else None + + if output_hidden_states: + batch_size, _, hidden_size = hidden_states.shape + reshaped_hidden_state = hidden_states.view( + batch_size, *input_dimensions, hidden_size + ) + reshaped_hidden_state = reshaped_hidden_state.permute(0, 3, 1, 2) + all_hidden_states += (hidden_states,) + all_reshaped_hidden_states += (reshaped_hidden_state,) + + for i, layer_module in enumerate(self.layers): + layer_head_mask = head_mask[i] if head_mask is not None else None + + if self.gradient_checkpointing and self.training: + layer_outputs = self._gradient_checkpointing_func( + layer_module.__call__, + hidden_states, + input_dimensions, + layer_head_mask, + output_attentions, + always_partition, + ) + else: + layer_outputs = layer_module( + hidden_states, + input_dimensions, + layer_head_mask, + output_attentions, + always_partition, + ) + + hidden_states = layer_outputs[0] + + hidden_states_before_downsampling = layer_outputs[1] + output_dimensions = layer_outputs[2] + + input_dimensions = (output_dimensions[-2], output_dimensions[-1]) + + if output_hidden_states and output_hidden_states_before_downsampling: + batch_size, _, hidden_size = hidden_states_before_downsampling.shape + reshaped_hidden_state = hidden_states_before_downsampling.reshape( + [ + batch_size, + *(output_dimensions[0], output_dimensions[1]), + hidden_size, + ] + ) + reshaped_hidden_state = reshaped_hidden_state.transpose([0, 3, 1, 2]) + all_hidden_states += (hidden_states_before_downsampling,) + all_reshaped_hidden_states += (reshaped_hidden_state,) + elif output_hidden_states and not output_hidden_states_before_downsampling: + batch_size, _, hidden_size = hidden_states.shape + reshaped_hidden_state = hidden_states.reshape( + [batch_size, *input_dimensions, hidden_size] + ) + reshaped_hidden_state = reshaped_hidden_state.transpose([0, 3, 1, 2]) + all_hidden_states += (hidden_states,) + all_reshaped_hidden_states += (reshaped_hidden_state,) + + if output_attentions: + all_self_attentions += layer_outputs[3:] + + if not return_dict: + return tuple( + v + for v in [hidden_states, all_hidden_states, all_self_attentions] + if v is not None + ) + + return DonutSwinEncoderOutput( + last_hidden_state=hidden_states, + hidden_states=all_hidden_states, + attentions=all_self_attentions, + reshaped_hidden_states=all_reshaped_hidden_states, + ) + + +class DonutSwinPreTrainedModel(nn.Module): + """ + An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained + models. + """ + + config_class = DonutSwinConfig + base_model_prefix = "swin" + main_input_name = "pixel_values" + supports_gradient_checkpointing = True + + def _init_weights(self, module): + """Initialize the weights""" + if isinstance(module, (nn.Linear, nn.Conv2D)): + # normal_ = Normal(mean=0.0, std=self.config.initializer_range) + nn.init.normal_(module.weight, mean=0.0, std=self.config.initializer_range) + if module.bias is not None: + nn.init.zeros_(module.bias) + elif isinstance(module, nn.LayerNorm): + nn.init.zeros_(module.bias) + nn.init.ones_(module.weight) + + def _initialize_weights(self, module): + """ + Initialize the weights if they are not already initialized. + """ + if getattr(module, "_is_hf_initialized", False): + return + self._init_weights(module) + + def post_init(self): + self.apply(self._initialize_weights) + + def get_head_mask(self, head_mask, num_hidden_layers, is_attention_chunked=False): + if head_mask is not None: + head_mask = self._convert_head_mask_to_5d(head_mask, num_hidden_layers) + if is_attention_chunked is True: + head_mask = head_mask.unsqueeze(-1) + else: + head_mask = [None] * num_hidden_layers + + return head_mask + + +class DonutSwinModel(DonutSwinPreTrainedModel): + def __init__( + self, + in_channels=3, + hidden_size=1024, + num_layers=4, + num_heads=[4, 8, 16, 32], + add_pooling_layer=True, + use_mask_token=False, + is_export=False, + ): + super().__init__() + donut_swin_config = { + "return_dict": True, + "output_hidden_states": False, + "output_attentions": False, + "use_bfloat16": False, + "tf_legacy_loss": False, + "pruned_heads": {}, + "tie_word_embeddings": True, + "chunk_size_feed_forward": 0, + "is_encoder_decoder": False, + "is_decoder": False, + "cross_attention_hidden_size": None, + "add_cross_attention": False, + "tie_encoder_decoder": False, + "max_length": 20, + "min_length": 0, + "do_sample": False, + "early_stopping": False, + "num_beams": 1, + "num_beam_groups": 1, + "diversity_penalty": 0.0, + "temperature": 1.0, + "top_k": 50, + "top_p": 1.0, + "typical_p": 1.0, + "repetition_penalty": 1.0, + "length_penalty": 1.0, + "no_repeat_ngram_size": 0, + "encoder_no_repeat_ngram_size": 0, + "bad_words_ids": None, + "num_return_sequences": 1, + "output_scores": False, + "return_dict_in_generate": False, + "forced_bos_token_id": None, + "forced_eos_token_id": None, + "remove_invalid_values": False, + "exponential_decay_length_penalty": None, + "suppress_tokens": None, + "begin_suppress_tokens": None, + "architectures": None, + "finetuning_task": None, + "id2label": {0: "LABEL_0", 1: "LABEL_1"}, + "label2id": {"LABEL_0": 0, "LABEL_1": 1}, + "tokenizer_class": None, + "prefix": None, + "bos_token_id": None, + "pad_token_id": None, + "eos_token_id": None, + "sep_token_id": None, + "decoder_start_token_id": None, + "task_specific_params": None, + "problem_type": None, + "_name_or_path": "", + "_commit_hash": None, + "_attn_implementation_internal": None, + "transformers_version": None, + "hidden_size": hidden_size, + "num_layers": num_layers, + "path_norm": True, + "use_2d_embeddings": False, + "image_size": [420, 420], + "patch_size": 4, + "num_channels": in_channels, + "embed_dim": 128, + "depths": [2, 2, 14, 2], + "num_heads": num_heads, + "window_size": 5, + "mlp_ratio": 4.0, + "qkv_bias": True, + "hidden_dropout_prob": 0.0, + "attention_probs_dropout_prob": 0.0, + "drop_path_rate": 0.1, + "hidden_act": "gelu", + "use_absolute_embeddings": False, + "layer_norm_eps": 1e-05, + "initializer_range": 0.02, + "is_export": is_export, + } + + config = DonutSwinConfig(**donut_swin_config) + self.config = config + self.num_layers = len(config.depths) + self.num_features = int(config.embed_dim * 2 ** (self.num_layers - 1)) + + self.embeddings = DonutSwinEmbeddings(config, use_mask_token=use_mask_token) + self.encoder = DonutSwinEncoder(config, self.embeddings.patch_grid) + + self.pooler = nn.AdaptiveAvgPool1D(1) if add_pooling_layer else None + self.out_channels = hidden_size + self.post_init() + + def get_input_embeddings(self): + return self.embeddings.patch_embeddings + + def forward( + self, + input_data=None, + bool_masked_pos=None, + head_mask=None, + output_attentions=None, + output_hidden_states=None, + return_dict=None, + ) -> Union[Tuple, DonutSwinModelOutput]: + r""" + bool_masked_pos (`paddle.BoolTensor` of shape `(batch_size, num_patches)`): + Boolean masked positions. Indicates which patches are masked (1) and which aren't (0). + """ + if self.training: + pixel_values, label, attention_mask = input_data + else: + if isinstance(input_data, list): + pixel_values = input_data[0] + else: + pixel_values = input_data + output_attentions = ( + output_attentions + if output_attentions is not None + else self.config.output_attentions + ) + output_hidden_states = ( + output_hidden_states + if output_hidden_states is not None + else self.config.output_hidden_states + ) + return_dict = ( + return_dict if return_dict is not None else self.config.return_dict + ) + + if pixel_values is None: + raise ValueError("You have to specify pixel_values") + num_channels = pixel_values.shape[1] + if num_channels == 1: + pixel_values = torch.repeat_interleave(pixel_values, repeats=3, dim=1) + + head_mask = self.get_head_mask(head_mask, len(self.config.depths)) + + embedding_output, input_dimensions = self.embeddings( + pixel_values, bool_masked_pos=bool_masked_pos + ) + + encoder_outputs = self.encoder( + embedding_output, + input_dimensions, + head_mask=head_mask, + output_attentions=output_attentions, + output_hidden_states=output_hidden_states, + return_dict=return_dict, + ) + sequence_output = encoder_outputs[0] + + pooled_output = None + if self.pooler is not None: + pooled_output = self.pooler(sequence_output.transpose([0, 2, 1])) + pooled_output = torch.flatten(pooled_output, 1) + + if not return_dict: + output = (sequence_output, pooled_output) + encoder_outputs[1:] + return output + + donut_swin_output = DonutSwinModelOutput( + last_hidden_state=sequence_output, + pooler_output=pooled_output, + hidden_states=encoder_outputs.hidden_states, + attentions=encoder_outputs.attentions, + reshaped_hidden_states=encoder_outputs.reshaped_hidden_states, + ) + if self.training: + return donut_swin_output, label, attention_mask + else: + return donut_swin_output \ No newline at end of file diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_hgnet.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_hgnet.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_hgnet.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_hgnet.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_lcnetv3.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_lcnetv3.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_lcnetv3.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_lcnetv3.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_mobilenet_v3.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_mobilenet_v3.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_mobilenet_v3.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_mobilenet_v3.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_mv1_enhance.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_mv1_enhance.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_mv1_enhance.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_mv1_enhance.py diff --git a/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_pphgnetv2.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_pphgnetv2.py new file mode 100644 index 0000000000000000000000000000000000000000..cf976c53a4aae718e88e6a2f42b743f85cc3f433 --- /dev/null +++ b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_pphgnetv2.py @@ -0,0 +1,1642 @@ +import math +import torch +import torch.nn as nn +import torch.nn.functional as F +import numpy as np +from .rec_donut_swin import DonutSwinModelOutput +from typing import List, Dict, Union, Callable + + +class IdentityBasedConv1x1(nn.Conv2d): + def __init__(self, channels, groups=1): + super(IdentityBasedConv1x1, self).__init__( + in_channels=channels, + out_channels=channels, + kernel_size=1, + stride=1, + padding=0, + groups=groups, + bias_attr=False, + ) + + assert channels % groups == 0 + input_dim = channels // groups + id_value = np.zeros((channels, input_dim, 1, 1)) + for i in range(channels): + id_value[i, i % input_dim, 0, 0] = 1 + self.id_tensor = torch.Tensor(id_value) + self.weight.set_value(torch.zeros_like(self.weight)) + + def forward(self, input): + kernel = self.weight + self.id_tensor + result = F.conv2d( + input, + kernel, + None, + stride=1, + padding=0, + dilation=self._dilation, + groups=self._groups, + ) + return result + + def get_actual_kernel(self): + return self.weight + self.id_tensor + + +class BNAndPad(nn.Module): + def __init__( + self, + pad_pixels, + num_features, + epsilon=1e-5, + momentum=0.1, + last_conv_bias=None, + bn=nn.BatchNorm2d, + ): + super().__init__() + self.bn = bn(num_features, momentum=momentum, epsilon=epsilon) + self.pad_pixels = pad_pixels + self.last_conv_bias = last_conv_bias + + def forward(self, input): + output = self.bn(input) + if self.pad_pixels > 0: + bias = -self.bn._mean + if self.last_conv_bias is not None: + bias += self.last_conv_bias + pad_values = self.bn.bias + self.bn.weight * ( + bias / torch.sqrt(self.bn._variance + self.bn._epsilon) + ) + """ pad """ + # TODO: n,h,w,c format is not supported yet + n, c, h, w = output.shape + values = pad_values.reshape([1, -1, 1, 1]) + w_values = values.expand([n, -1, self.pad_pixels, w]) + x = torch.cat([w_values, output, w_values], dim=2) + h = h + self.pad_pixels * 2 + h_values = values.expand([n, -1, h, self.pad_pixels]) + x = torch.cat([h_values, x, h_values], dim=3) + output = x + return output + + @property + def weight(self): + return self.bn.weight + + @property + def bias(self): + return self.bn.bias + + @property + def _mean(self): + return self.bn._mean + + @property + def _variance(self): + return self.bn._variance + + @property + def _epsilon(self): + return self.bn._epsilon + + +def conv_bn( + in_channels, + out_channels, + kernel_size, + stride=1, + padding=0, + dilation=1, + groups=1, + padding_mode="zeros", +): + conv_layer = nn.Conv2d( + in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=padding, + dilation=dilation, + groups=groups, + bias_attr=False, + padding_mode=padding_mode, + ) + bn_layer = nn.BatchNorm2D(num_features=out_channels) + se = nn.Sequential() + se.add_sublayer("conv", conv_layer) + se.add_sublayer("bn", bn_layer) + return se + + +def transI_fusebn(kernel, bn): + gamma = bn.weight + std = (bn._variance + bn._epsilon).sqrt() + return ( + kernel * ((gamma / std).reshape([-1, 1, 1, 1])), + bn.bias - bn._mean * gamma / std, + ) + + +def transII_addbranch(kernels, biases): + return sum(kernels), sum(biases) + + +def transIII_1x1_kxk(k1, b1, k2, b2, groups): + if groups == 1: + k = F.conv2d(k2, k1.transpose([1, 0, 2, 3])) + b_hat = (k2 * b1.reshape([1, -1, 1, 1])).sum((1, 2, 3)) + else: + k_slices = [] + b_slices = [] + k1_T = k1.transpose([1, 0, 2, 3]) + k1_group_width = k1.shape[0] // groups + k2_group_width = k2.shape[0] // groups + for g in range(groups): + k1_T_slice = k1_T[:, g * k1_group_width : (g + 1) * k1_group_width, :, :] + k2_slice = k2[g * k2_group_width : (g + 1) * k2_group_width, :, :, :] + k_slices.append(F.conv2d(k2_slice, k1_T_slice)) + b_slices.append( + ( + k2_slice + * b1[g * k1_group_width : (g + 1) * k1_group_width].reshape( + [1, -1, 1, 1] + ) + ).sum((1, 2, 3)) + ) + k, b_hat = transIV_depthconcat(k_slices, b_slices) + return k, b_hat + b2 + + +def transIV_depthconcat(kernels, biases): + return torch.cat(kernels, dim=0), torch.cat(biases) + + +def transV_avg(channels, kernel_size, groups): + input_dim = channels // groups + k = torch.zeros((channels, input_dim, kernel_size, kernel_size)) + k[np.arange(channels), np.tile(np.arange(input_dim), groups), :, :] = ( + 1.0 / kernel_size**2 + ) + return k + + +def transVI_multiscale(kernel, target_kernel_size): + H_pixels_to_pad = (target_kernel_size - kernel.shape[2]) // 2 + W_pixels_to_pad = (target_kernel_size - kernel.shape[3]) // 2 + return F.pad( + kernel, [H_pixels_to_pad, H_pixels_to_pad, W_pixels_to_pad, W_pixels_to_pad] + ) + + +class DiverseBranchBlock(nn.Module): + def __init__( + self, + num_channels, + num_filters, + filter_size, + stride=1, + groups=1, + act=None, + is_repped=False, + single_init=False, + **kwargs, + ): + super().__init__() + + padding = (filter_size - 1) // 2 + dilation = 1 + + in_channels = num_channels + out_channels = num_filters + kernel_size = filter_size + internal_channels_1x1_3x3 = None + nonlinear = act + + self.is_repped = is_repped + + if nonlinear is None: + self.nonlinear = nn.Identity() + else: + self.nonlinear = nn.ReLU() + + self.kernel_size = kernel_size + self.out_channels = out_channels + self.groups = groups + assert padding == kernel_size // 2 + + if is_repped: + self.dbb_reparam = nn.Conv2d( + in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=padding, + dilation=dilation, + groups=groups, + bias=True, + ) + else: + self.dbb_origin = conv_bn( + in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=padding, + dilation=dilation, + groups=groups, + ) + + self.dbb_avg = nn.Sequential() + if groups < out_channels: + self.dbb_avg.add_sublayer( + "conv", + nn.Conv2d( + in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + stride=1, + padding=0, + groups=groups, + bias=False, + ), + ) + self.dbb_avg.add_sublayer( + "bn", BNAndPad(pad_pixels=padding, num_features=out_channels) + ) + self.dbb_avg.add_sublayer( + "avg", + nn.AvgPool2D(kernel_size=kernel_size, stride=stride, padding=0), + ) + self.dbb_1x1 = conv_bn( + in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + stride=stride, + padding=0, + groups=groups, + ) + else: + self.dbb_avg.add_sublayer( + "avg", + nn.AvgPool2D( + kernel_size=kernel_size, stride=stride, padding=padding + ), + ) + + self.dbb_avg.add_sublayer("avgbn", nn.BatchNorm2D(out_channels)) + + if internal_channels_1x1_3x3 is None: + internal_channels_1x1_3x3 = ( + in_channels if groups < out_channels else 2 * in_channels + ) # For mobilenet, it is better to have 2X internal channels + + self.dbb_1x1_kxk = nn.Sequential() + if internal_channels_1x1_3x3 == in_channels: + self.dbb_1x1_kxk.add_sublayer( + "idconv1", IdentityBasedConv1x1(channels=in_channels, groups=groups) + ) + else: + self.dbb_1x1_kxk.add_sublayer( + "conv1", + nn.Conv2d( + in_channels=in_channels, + out_channels=internal_channels_1x1_3x3, + kernel_size=1, + stride=1, + padding=0, + groups=groups, + bias=False, + ), + ) + self.dbb_1x1_kxk.add_sublayer( + "bn1", + BNAndPad(pad_pixels=padding, num_features=internal_channels_1x1_3x3), + ) + self.dbb_1x1_kxk.add_sublayer( + "conv2", + nn.Conv2d( + in_channels=internal_channels_1x1_3x3, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=0, + groups=groups, + bias=False, + ), + ) + self.dbb_1x1_kxk.add_sublayer("bn2", nn.BatchNorm2D(out_channels)) + + # The experiments reported in the paper used the default initialization of bn.weight (all as 1). But changing the initialization may be useful in some cases. + if single_init: + # Initialize the bn.weight of dbb_origin as 1 and others as 0. This is not the default setting. + self.single_init() + + def forward(self, inputs): + if self.is_repped: + return self.nonlinear(self.dbb_reparam(inputs)) + + out = self.dbb_origin(inputs) + if hasattr(self, "dbb_1x1"): + out += self.dbb_1x1(inputs) + out += self.dbb_avg(inputs) + out += self.dbb_1x1_kxk(inputs) + return self.nonlinear(out) + + def init_gamma(self, gamma_value): + if hasattr(self, "dbb_origin"): + torch.nn.init.constant_(self.dbb_origin.bn.weight, gamma_value) + if hasattr(self, "dbb_1x1"): + torch.nn.init.constant_(self.dbb_1x1.bn.weight, gamma_value) + if hasattr(self, "dbb_avg"): + torch.nn.init.constant_(self.dbb_avg.avgbn.weight, gamma_value) + if hasattr(self, "dbb_1x1_kxk"): + torch.nn.init.constant_(self.dbb_1x1_kxk.bn2.weight, gamma_value) + + def single_init(self): + self.init_gamma(0.0) + if hasattr(self, "dbb_origin"): + torch.nn.init.constant_(self.dbb_origin.bn.weight, 1.0) + + def get_equivalent_kernel_bias(self): + k_origin, b_origin = transI_fusebn( + self.dbb_origin.conv.weight, self.dbb_origin.bn + ) + + if hasattr(self, "dbb_1x1"): + k_1x1, b_1x1 = transI_fusebn(self.dbb_1x1.conv.weight, self.dbb_1x1.bn) + k_1x1 = transVI_multiscale(k_1x1, self.kernel_size) + else: + k_1x1, b_1x1 = 0, 0 + + if hasattr(self.dbb_1x1_kxk, "idconv1"): + k_1x1_kxk_first = self.dbb_1x1_kxk.idconv1.get_actual_kernel() + else: + k_1x1_kxk_first = self.dbb_1x1_kxk.conv1.weight + k_1x1_kxk_first, b_1x1_kxk_first = transI_fusebn( + k_1x1_kxk_first, self.dbb_1x1_kxk.bn1 + ) + k_1x1_kxk_second, b_1x1_kxk_second = transI_fusebn( + self.dbb_1x1_kxk.conv2.weight, self.dbb_1x1_kxk.bn2 + ) + k_1x1_kxk_merged, b_1x1_kxk_merged = transIII_1x1_kxk( + k_1x1_kxk_first, + b_1x1_kxk_first, + k_1x1_kxk_second, + b_1x1_kxk_second, + groups=self.groups, + ) + + k_avg = transV_avg(self.out_channels, self.kernel_size, self.groups) + k_1x1_avg_second, b_1x1_avg_second = transI_fusebn(k_avg, self.dbb_avg.avgbn) + if hasattr(self.dbb_avg, "conv"): + k_1x1_avg_first, b_1x1_avg_first = transI_fusebn( + self.dbb_avg.conv.weight, self.dbb_avg.bn + ) + k_1x1_avg_merged, b_1x1_avg_merged = transIII_1x1_kxk( + k_1x1_avg_first, + b_1x1_avg_first, + k_1x1_avg_second, + b_1x1_avg_second, + groups=self.groups, + ) + else: + k_1x1_avg_merged, b_1x1_avg_merged = k_1x1_avg_second, b_1x1_avg_second + + return transII_addbranch( + (k_origin, k_1x1, k_1x1_kxk_merged, k_1x1_avg_merged), + (b_origin, b_1x1, b_1x1_kxk_merged, b_1x1_avg_merged), + ) + + def re_parameterize(self): + if self.is_repped: + return + + kernel, bias = self.get_equivalent_kernel_bias() + self.dbb_reparam = nn.Conv2d( + in_channels=self.dbb_origin.conv._in_channels, + out_channels=self.dbb_origin.conv._out_channels, + kernel_size=self.dbb_origin.conv._kernel_size, + stride=self.dbb_origin.conv._stride, + padding=self.dbb_origin.conv._padding, + dilation=self.dbb_origin.conv._dilation, + groups=self.dbb_origin.conv._groups, + bias=True, + ) + + self.dbb_reparam.weight.set_value(kernel) + self.dbb_reparam.bias.set_value(bias) + + self.__delattr__("dbb_origin") + self.__delattr__("dbb_avg") + if hasattr(self, "dbb_1x1"): + self.__delattr__("dbb_1x1") + self.__delattr__("dbb_1x1_kxk") + self.is_repped = True + + +class Identity(nn.Module): + def __init__(self): + super(Identity, self).__init__() + + def forward(self, inputs): + return inputs + + +class TheseusLayer(nn.Module): + def __init__(self, *args, **kwargs): + super().__init__() + self.res_dict = {} + # self.res_name = self.full_name() + self.res_name = self.__class__.__name__.lower() + self.pruner = None + self.quanter = None + + self.init_net(*args, **kwargs) + + def _return_dict_hook(self, layer, input, output): + res_dict = {"logits": output} + # 'list' is needed to avoid error raised by popping self.res_dict + for res_key in list(self.res_dict): + # clear the res_dict because the forward process may change according to input + res_dict[res_key] = self.res_dict.pop(res_key) + return res_dict + + def init_net( + self, + stages_pattern=None, + return_patterns=None, + return_stages=None, + freeze_befor=None, + stop_after=None, + *args, + **kwargs, + ): + # init the output of net + if return_patterns or return_stages: + if return_patterns and return_stages: + msg = f"The 'return_patterns' would be ignored when 'return_stages' is set." + + return_stages = None + + if return_stages is True: + return_patterns = stages_pattern + + # return_stages is int or bool + if type(return_stages) is int: + return_stages = [return_stages] + if isinstance(return_stages, list): + if max(return_stages) > len(stages_pattern) or min(return_stages) < 0: + msg = f"The 'return_stages' set error. Illegal value(s) have been ignored. The stages' pattern list is {stages_pattern}." + + return_stages = [ + val + for val in return_stages + if val >= 0 and val < len(stages_pattern) + ] + return_patterns = [stages_pattern[i] for i in return_stages] + + if return_patterns: + # call update_res function after the __init__ of the object has completed execution, that is, the constructing of layer or model has been completed. + def update_res_hook(layer, input): + self.update_res(return_patterns) + + self.register_forward_pre_hook(update_res_hook) + + # freeze subnet + if freeze_befor is not None: + self.freeze_befor(freeze_befor) + + # set subnet to Identity + if stop_after is not None: + self.stop_after(stop_after) + + def init_res(self, stages_pattern, return_patterns=None, return_stages=None): + + if return_patterns and return_stages: + return_stages = None + + if return_stages is True: + return_patterns = stages_pattern + # return_stages is int or bool + if type(return_stages) is int: + return_stages = [return_stages] + if isinstance(return_stages, list): + if max(return_stages) > len(stages_pattern) or min(return_stages) < 0: + return_stages = [ + val + for val in return_stages + if val >= 0 and val < len(stages_pattern) + ] + return_patterns = [stages_pattern[i] for i in return_stages] + + if return_patterns: + self.update_res(return_patterns) + + def replace_sub(self, *args, **kwargs) -> None: + msg = "The function 'replace_sub()' is deprecated, please use 'upgrade_sublayer()' instead." + raise DeprecationWarning(msg) + + def upgrade_sublayer( + self, + layer_name_pattern: Union[str, List[str]], + handle_func: Callable[[nn.Module, str], nn.Module], + ) -> Dict[str, nn.Module]: + """use 'handle_func' to modify the sub-layer(s) specified by 'layer_name_pattern'. + + Args: + layer_name_pattern (Union[str, List[str]]): The name of layer to be modified by 'handle_func'. + handle_func (Callable[[nn.Module, str], nn.Module]): The function to modify target layer specified by 'layer_name_pattern'. The formal params are the layer(nn.Module) and pattern(str) that is (a member of) layer_name_pattern (when layer_name_pattern is List type). And the return is the layer processed. + + Returns: + Dict[str, nn.Module]: The key is the pattern and corresponding value is the result returned by 'handle_func()'. + + Examples: + + from paddle import nn + import paddleclas + + def rep_func(layer: nn.Module, pattern: str): + new_layer = nn.Conv2d( + in_channels=layer._in_channels, + out_channels=layer._out_channels, + kernel_size=5, + padding=2 + ) + return new_layer + + net = paddleclas.MobileNetV1() + res = net.upgrade_sublayer(layer_name_pattern=["blocks[11].depthwise_conv.conv", "blocks[12].depthwise_conv.conv"], handle_func=rep_func) + print(res) + # {'blocks[11].depthwise_conv.conv': the corresponding new_layer, 'blocks[12].depthwise_conv.conv': the corresponding new_layer} + """ + + if not isinstance(layer_name_pattern, list): + layer_name_pattern = [layer_name_pattern] + + hit_layer_pattern_list = [] + for pattern in layer_name_pattern: + # parse pattern to find target layer and its parent + layer_list = parse_pattern_str(pattern=pattern, parent_layer=self) + if not layer_list: + continue + + sub_layer_parent = layer_list[-2]["layer"] if len(layer_list) > 1 else self + sub_layer = layer_list[-1]["layer"] + sub_layer_name = layer_list[-1]["name"] + sub_layer_index_list = layer_list[-1]["index_list"] + + new_sub_layer = handle_func(sub_layer, pattern) + + if sub_layer_index_list: + if len(sub_layer_index_list) > 1: + sub_layer_parent = getattr(sub_layer_parent, sub_layer_name)[ + sub_layer_index_list[0] + ] + for sub_layer_index in sub_layer_index_list[1:-1]: + sub_layer_parent = sub_layer_parent[sub_layer_index] + sub_layer_parent[sub_layer_index_list[-1]] = new_sub_layer + else: + getattr(sub_layer_parent, sub_layer_name)[ + sub_layer_index_list[0] + ] = new_sub_layer + else: + setattr(sub_layer_parent, sub_layer_name, new_sub_layer) + + hit_layer_pattern_list.append(pattern) + return hit_layer_pattern_list + + def stop_after(self, stop_layer_name: str) -> bool: + """stop forward and backward after 'stop_layer_name'. + + Args: + stop_layer_name (str): The name of layer that stop forward and backward after this layer. + + Returns: + bool: 'True' if successful, 'False' otherwise. + """ + + layer_list = parse_pattern_str(stop_layer_name, self) + if not layer_list: + return False + + parent_layer = self + for layer_dict in layer_list: + name, index_list = layer_dict["name"], layer_dict["index_list"] + if not set_identity(parent_layer, name, index_list): + msg = f"Failed to set the layers that after stop_layer_name('{stop_layer_name}') to IdentityLayer. The error layer's name is '{name}'." + return False + parent_layer = layer_dict["layer"] + + return True + + def freeze_befor(self, layer_name: str) -> bool: + """freeze the layer named layer_name and its previous layer. + + Args: + layer_name (str): The name of layer that would be freezed. + + Returns: + bool: 'True' if successful, 'False' otherwise. + """ + + def stop_grad(layer, pattern): + class StopGradLayer(nn.Module): + def __init__(self): + super().__init__() + self.layer = layer + + def forward(self, x): + x = self.layer(x) + x.stop_gradient = True + return x + + new_layer = StopGradLayer() + return new_layer + + res = self.upgrade_sublayer(layer_name, stop_grad) + if len(res) == 0: + msg = "Failed to stop the gradient before the layer named '{layer_name}'" + return False + return True + + def update_res(self, return_patterns: Union[str, List[str]]) -> Dict[str, nn.Module]: + """update the result(s) to be returned. + + Args: + return_patterns (Union[str, List[str]]): The name of layer to return output. + + Returns: + Dict[str, nn.Module]: The pattern(str) and corresponding layer(nn.Module) that have been set successfully. + """ + + # clear res_dict that could have been set + self.res_dict = {} + + class Handler(object): + def __init__(self, res_dict): + # res_dict is a reference + self.res_dict = res_dict + + def __call__(self, layer, pattern): + layer.res_dict = self.res_dict + layer.res_name = pattern + if hasattr(layer, "hook_remove_helper"): + layer.hook_remove_helper.remove() + layer.hook_remove_helper = layer.register_forward_post_hook( + save_sub_res_hook + ) + return layer + + handle_func = Handler(self.res_dict) + + hit_layer_pattern_list = self.upgrade_sublayer( + return_patterns, handle_func=handle_func + ) + + if hasattr(self, "hook_remove_helper"): + self.hook_remove_helper.remove() + self.hook_remove_helper = self.register_forward_post_hook( + self._return_dict_hook + ) + + return hit_layer_pattern_list + + +def save_sub_res_hook(layer, input, output): + layer.res_dict[layer.res_name] = output + + +def set_identity( + parent_layer: nn.Module, layer_name: str, layer_index_list: str = None +) -> bool: + """set the layer specified by layer_name and layer_index_list to Identity. + + Args: + parent_layer (nn.Module): The parent layer of target layer specified by layer_name and layer_index_list. + layer_name (str): The name of target layer to be set to Identity. + layer_index_list (str, optional): The index of target layer to be set to Identity in parent_layer. Defaults to None. + + Returns: + bool: True if successfully, False otherwise. + """ + + stop_after = False + for sub_layer_name in parent_layer._sub_layers: + if stop_after: + parent_layer._sub_layers[sub_layer_name] = Identity() + continue + if sub_layer_name == layer_name: + stop_after = True + + if layer_index_list and stop_after: + layer_container = parent_layer._sub_layers[layer_name] + for num, layer_index in enumerate(layer_index_list): + stop_after = False + for i in range(num): + layer_container = layer_container[layer_index_list[i]] + for sub_layer_index in layer_container._sub_layers: + if stop_after: + parent_layer._sub_layers[layer_name][sub_layer_index] = Identity() + continue + if layer_index == sub_layer_index: + stop_after = True + + return stop_after + + +def parse_pattern_str( + pattern: str, parent_layer: nn.Module +) -> Union[None, List[Dict[str, Union[nn.Module, str, None]]]]: + """parse the string type pattern. + + Args: + pattern (str): The pattern to describe layer. + parent_layer (nn.Module): The root layer relative to the pattern. + + Returns: + Union[None, List[Dict[str, Union[nn.Module, str, None]]]]: None if failed. If successfully, the members are layers parsed in order: + [ + {"layer": first layer, "name": first layer's name parsed, "index": first layer's index parsed if exist}, + {"layer": second layer, "name": second layer's name parsed, "index": second layer's index parsed if exist}, + ... + ] + """ + + pattern_list = pattern.split(".") + if not pattern_list: + msg = f"The pattern('{pattern}') is illegal. Please check and retry." + return None + + layer_list = [] + while len(pattern_list) > 0: + if "[" in pattern_list[0]: + target_layer_name = pattern_list[0].split("[")[0] + target_layer_index_list = list( + index.split("]")[0] for index in pattern_list[0].split("[")[1:] + ) + else: + target_layer_name = pattern_list[0] + target_layer_index_list = None + + target_layer = getattr(parent_layer, target_layer_name, None) + + if target_layer is None: + msg = f"Not found layer named('{target_layer_name}') specified in pattern('{pattern}')." + return None + + if target_layer_index_list: + for target_layer_index in target_layer_index_list: + if int(target_layer_index) < 0 or int(target_layer_index) >= len( + target_layer + ): + msg = f"Not found layer by index('{target_layer_index}') specified in pattern('{pattern}'). The index should < {len(target_layer)} and > 0." + return None + target_layer = target_layer[target_layer_index] + + layer_list.append( + { + "layer": target_layer, + "name": target_layer_name, + "index_list": target_layer_index_list, + } + ) + + pattern_list = pattern_list[1:] + parent_layer = target_layer + + return layer_list + + +class LearnableAffineBlock(TheseusLayer): + """ + Create a learnable affine block module. This module can significantly improve accuracy on smaller models. + + Args: + scale_value (float): The initial value of the scale parameter, default is 1.0. + bias_value (float): The initial value of the bias parameter, default is 0.0. + lr_mult (float): The learning rate multiplier, default is 1.0. + lab_lr (float): The learning rate, default is 0.01. + """ + + def __init__(self, scale_value=1.0, bias_value=0.0, lr_mult=1.0, lab_lr=0.01): + super().__init__() + # self.scale = self.create_parameter( + # shape=[ + # 1, + # ], + # default_initializer=nn.init.Constant(value=scale_value), + # # attr=ParamAttr(learning_rate=lr_mult * lab_lr), + # ) + # self.add_parameter("scale", self.scale) + self.scale = torch.Parameter( + nn.init.constant_( + torch.ones(1).to(torch.float32), val=scale_value + ) + ) + self.register_parameter("scale", self.scale) + + # self.bias = self.create_parameter( + # shape=[ + # 1, + # ], + # default_initializer=nn.init.Constant(value=bias_value), + # # attr=ParamAttr(learning_rate=lr_mult * lab_lr), + # ) + # self.add_parameter("bias", self.bias) + self.bias = torch.Parameter( + nn.init.constant_( + torch.ones(1).to(torch.float32), val=bias_value + ) + ) + self.register_parameter("bias", self.bias) + + def forward(self, x): + return self.scale * x + self.bias + + +class ConvBNAct(TheseusLayer): + """ + ConvBNAct is a combination of convolution and batchnorm layers. + + Args: + in_channels (int): Number of input channels. + out_channels (int): Number of output channels. + kernel_size (int): Size of the convolution kernel. Defaults to 3. + stride (int): Stride of the convolution. Defaults to 1. + padding (int/str): Padding or padding type for the convolution. Defaults to 1. + groups (int): Number of groups for the convolution. Defaults to 1. + use_act: (bool): Whether to use activation function. Defaults to True. + use_lab (bool): Whether to use the LAB operation. Defaults to False. + lr_mult (float): Learning rate multiplier for the layer. Defaults to 1.0. + """ + + def __init__( + self, + in_channels, + out_channels, + kernel_size=3, + stride=1, + padding=1, + groups=1, + use_act=True, + use_lab=False, + lr_mult=1.0, + ): + super().__init__() + self.use_act = use_act + self.use_lab = use_lab + self.conv = nn.Conv2d( + in_channels, + out_channels, + kernel_size, + stride, + padding=padding if isinstance(padding, str) else (kernel_size - 1) // 2, + groups=groups, + bias=False, + ) + self.bn = nn.BatchNorm2d( + out_channels, + ) + if self.use_act: + self.act = nn.ReLU() + if self.use_lab: + self.lab = LearnableAffineBlock(lr_mult=lr_mult) + + def forward(self, x): + x = self.conv(x) + x = self.bn(x) + if self.use_act: + x = self.act(x) + if self.use_lab: + x = self.lab(x) + return x + + +class LightConvBNAct(TheseusLayer): + """ + LightConvBNAct is a combination of pw and dw layers. + + Args: + in_channels (int): Number of input channels. + out_channels (int): Number of output channels. + kernel_size (int): Size of the depth-wise convolution kernel. + use_lab (bool): Whether to use the LAB operation. Defaults to False. + lr_mult (float): Learning rate multiplier for the layer. Defaults to 1.0. + """ + + def __init__( + self, + in_channels, + out_channels, + kernel_size, + use_lab=False, + lr_mult=1.0, + **kwargs, + ): + super().__init__() + self.conv1 = ConvBNAct( + in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + use_act=False, + use_lab=use_lab, + lr_mult=lr_mult, + ) + self.conv2 = ConvBNAct( + in_channels=out_channels, + out_channels=out_channels, + kernel_size=kernel_size, + groups=out_channels, + use_act=True, + use_lab=use_lab, + lr_mult=lr_mult, + ) + + def forward(self, x): + x = self.conv1(x) + x = self.conv2(x) + return x + + +class PaddingSameAsPaddleMaxPool2d(torch.nn.Module): + def __init__(self, kernel_size, stride=1): + super().__init__() + self.kernel_size = kernel_size + self.stride = stride + self.pool = torch.nn.MaxPool2d(kernel_size, stride, padding=0, ceil_mode=True) + + def forward(self, x): + _, _, h, w = x.shape + pad_h_total = max(0, (math.ceil(h / self.stride) - 1) * self.stride + self.kernel_size - h) + pad_w_total = max(0, (math.ceil(w / self.stride) - 1) * self.stride + self.kernel_size - w) + pad_h = pad_h_total // 2 + pad_w = pad_w_total // 2 + x = torch.nn.functional.pad(x, [pad_w, pad_w_total - pad_w, pad_h, pad_h_total - pad_h]) + return self.pool(x) + + +class StemBlock(TheseusLayer): + """ + StemBlock for PP-HGNetV2. + + Args: + in_channels (int): Number of input channels. + mid_channels (int): Number of middle channels. + out_channels (int): Number of output channels. + use_lab (bool): Whether to use the LAB operation. Defaults to False. + lr_mult (float): Learning rate multiplier for the layer. Defaults to 1.0. + """ + + def __init__( + self, + in_channels, + mid_channels, + out_channels, + use_lab=False, + lr_mult=1.0, + text_rec=False, + ): + super().__init__() + self.stem1 = ConvBNAct( + in_channels=in_channels, + out_channels=mid_channels, + kernel_size=3, + stride=2, + use_lab=use_lab, + lr_mult=lr_mult, + ) + self.stem2a = ConvBNAct( + in_channels=mid_channels, + out_channels=mid_channels // 2, + kernel_size=2, + stride=1, + padding="same", + use_lab=use_lab, + lr_mult=lr_mult, + ) + self.stem2b = ConvBNAct( + in_channels=mid_channels // 2, + out_channels=mid_channels, + kernel_size=2, + stride=1, + padding="same", + use_lab=use_lab, + lr_mult=lr_mult, + ) + self.stem3 = ConvBNAct( + in_channels=mid_channels * 2, + out_channels=mid_channels, + kernel_size=3, + stride=1 if text_rec else 2, + use_lab=use_lab, + lr_mult=lr_mult, + ) + self.stem4 = ConvBNAct( + in_channels=mid_channels, + out_channels=out_channels, + kernel_size=1, + stride=1, + use_lab=use_lab, + lr_mult=lr_mult, + ) + self.pool = PaddingSameAsPaddleMaxPool2d( + kernel_size=2, stride=1, + ) + + def forward(self, x): + x = self.stem1(x) + x2 = self.stem2a(x) + x2 = self.stem2b(x2) + x1 = self.pool(x) + x = torch.cat([x1, x2], 1) + x = self.stem3(x) + x = self.stem4(x) + + return x + + +class HGV2_Block(TheseusLayer): + """ + HGV2_Block, the basic unit that constitutes the HGV2_Stage. + + Args: + in_channels (int): Number of input channels. + mid_channels (int): Number of middle channels. + out_channels (int): Number of output channels. + kernel_size (int): Size of the convolution kernel. Defaults to 3. + layer_num (int): Number of layers in the HGV2 block. Defaults to 6. + stride (int): Stride of the convolution. Defaults to 1. + padding (int/str): Padding or padding type for the convolution. Defaults to 1. + groups (int): Number of groups for the convolution. Defaults to 1. + use_act (bool): Whether to use activation function. Defaults to True. + use_lab (bool): Whether to use the LAB operation. Defaults to False. + lr_mult (float): Learning rate multiplier for the layer. Defaults to 1.0. + """ + + def __init__( + self, + in_channels, + mid_channels, + out_channels, + kernel_size=3, + layer_num=6, + identity=False, + light_block=True, + use_lab=False, + lr_mult=1.0, + ): + super().__init__() + self.identity = identity + + self.layers = nn.ModuleList() + block_type = "LightConvBNAct" if light_block else "ConvBNAct" + for i in range(layer_num): + self.layers.append( + eval(block_type)( + in_channels=in_channels if i == 0 else mid_channels, + out_channels=mid_channels, + stride=1, + kernel_size=kernel_size, + use_lab=use_lab, + lr_mult=lr_mult, + ) + ) + # feature aggregation + total_channels = in_channels + layer_num * mid_channels + self.aggregation_squeeze_conv = ConvBNAct( + in_channels=total_channels, + out_channels=out_channels // 2, + kernel_size=1, + stride=1, + use_lab=use_lab, + lr_mult=lr_mult, + ) + self.aggregation_excitation_conv = ConvBNAct( + in_channels=out_channels // 2, + out_channels=out_channels, + kernel_size=1, + stride=1, + use_lab=use_lab, + lr_mult=lr_mult, + ) + + def forward(self, x): + identity = x + output = [] + output.append(x) + for layer in self.layers: + x = layer(x) + output.append(x) + x = torch.cat(output, dim=1) + x = self.aggregation_squeeze_conv(x) + x = self.aggregation_excitation_conv(x) + if self.identity: + x += identity + return x + + +class HGV2_Stage(TheseusLayer): + """ + HGV2_Stage, the basic unit that constitutes the PPHGNetV2. + + Args: + in_channels (int): Number of input channels. + mid_channels (int): Number of middle channels. + out_channels (int): Number of output channels. + block_num (int): Number of blocks in the HGV2 stage. + layer_num (int): Number of layers in the HGV2 block. Defaults to 6. + is_downsample (bool): Whether to use downsampling operation. Defaults to False. + light_block (bool): Whether to use light block. Defaults to True. + kernel_size (int): Size of the convolution kernel. Defaults to 3. + use_lab (bool, optional): Whether to use the LAB operation. Defaults to False. + lr_mult (float, optional): Learning rate multiplier for the layer. Defaults to 1.0. + """ + + def __init__( + self, + in_channels, + mid_channels, + out_channels, + block_num, + layer_num=6, + is_downsample=True, + light_block=True, + kernel_size=3, + use_lab=False, + stride=2, + lr_mult=1.0, + ): + + super().__init__() + self.is_downsample = is_downsample + if self.is_downsample: + self.downsample = ConvBNAct( + in_channels=in_channels, + out_channels=in_channels, + kernel_size=3, + stride=stride, + groups=in_channels, + use_act=False, + use_lab=use_lab, + lr_mult=lr_mult, + ) + + blocks_list = [] + for i in range(block_num): + blocks_list.append( + HGV2_Block( + in_channels=in_channels if i == 0 else out_channels, + mid_channels=mid_channels, + out_channels=out_channels, + kernel_size=kernel_size, + layer_num=layer_num, + identity=False if i == 0 else True, + light_block=light_block, + use_lab=use_lab, + lr_mult=lr_mult, + ) + ) + self.blocks = nn.Sequential(*blocks_list) + + def forward(self, x): + if self.is_downsample: + x = self.downsample(x) + x = self.blocks(x) + return x + + +class PPHGNetV2(TheseusLayer): + """ + PPHGNetV2 + + Args: + stage_config (dict): Config for PPHGNetV2 stages. such as the number of channels, stride, etc. + stem_channels: (list): Number of channels of the stem of the PPHGNetV2. + use_lab (bool): Whether to use the LAB operation. Defaults to False. + use_last_conv (bool): Whether to use the last conv layer as the output channel. Defaults to True. + class_expand (int): Number of channels for the last 1x1 convolutional layer. + drop_prob (float): Dropout probability for the last 1x1 convolutional layer. Defaults to 0.0. + class_num (int): The number of classes for the classification layer. Defaults to 1000. + lr_mult_list (list): Learning rate multiplier for the stages. Defaults to [1.0, 1.0, 1.0, 1.0, 1.0]. + Returns: + model: nn.Module. Specific PPHGNetV2 model depends on args. + """ + + def __init__( + self, + stage_config, + stem_channels=[3, 32, 64], + use_lab=False, + use_last_conv=True, + class_expand=2048, + dropout_prob=0.0, + class_num=1000, + lr_mult_list=[1.0, 1.0, 1.0, 1.0, 1.0], + det=False, + text_rec=False, + out_indices=None, + **kwargs, + ): + super().__init__() + self.det = det + self.text_rec = text_rec + self.use_lab = use_lab + self.use_last_conv = use_last_conv + self.class_expand = class_expand + self.class_num = class_num + self.out_indices = out_indices if out_indices is not None else [0, 1, 2, 3] + self.out_channels = [] + + # stem + self.stem = StemBlock( + in_channels=stem_channels[0], + mid_channels=stem_channels[1], + out_channels=stem_channels[2], + use_lab=use_lab, + lr_mult=lr_mult_list[0], + text_rec=text_rec, + ) + + # stages + self.stages = nn.ModuleList() + for i, k in enumerate(stage_config): + ( + in_channels, + mid_channels, + out_channels, + block_num, + is_downsample, + light_block, + kernel_size, + layer_num, + stride, + ) = stage_config[k] + self.stages.append( + HGV2_Stage( + in_channels, + mid_channels, + out_channels, + block_num, + layer_num, + is_downsample, + light_block, + kernel_size, + use_lab, + stride, + lr_mult=lr_mult_list[i + 1], + ) + ) + if i in self.out_indices: + self.out_channels.append(out_channels) + if not self.det: + self.out_channels = stage_config["stage4"][2] + + self.avg_pool = nn.AdaptiveAvgPool2d(1) + + if self.use_last_conv: + self.last_conv = nn.Conv2d( + in_channels=out_channels, + out_channels=self.class_expand, + kernel_size=1, + stride=1, + padding=0, + bias=False, + ) + self.act = nn.ReLU() + if self.use_lab: + self.lab = LearnableAffineBlock() + # self.dropout = nn.Dropout(p=dropout_prob, mode="downscale_in_infer") + self.dropout = nn.Dropout(p=dropout_prob) + + self.flatten = nn.Flatten(start_dim=1, end_dim=-1) + if not self.det: + self.fc = nn.Linear( + self.class_expand if self.use_last_conv else out_channels, + self.class_num, + ) + + self._init_weights() + + def _init_weights(self): + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight) + elif isinstance(m, (nn.BatchNorm2d)): + nn.init.ones_(m.weight) + nn.init.zeros_(m.bias) + elif isinstance(m, nn.Linear): + nn.init.zeros_(m.bias) + + def forward(self, x): + x = self.stem(x) + out = [] + for i, stage in enumerate(self.stages): + x = stage(x) + if self.det and i in self.out_indices: + out.append(x) + if self.det: + return out + + if self.text_rec: + if self.training: + x = F.adaptive_avg_pool2d(x, [1, 40]) + else: + x = F.avg_pool2d(x, [3, 2]) + return x + + +def PPHGNetV2_B0(pretrained=False, use_ssld=False, **kwargs): + """ + PPHGNetV2_B0 + Args: + pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. + If str, means the path of the pretrained model. + use_ssld (bool) Whether using ssld pretrained model when pretrained is True. + Returns: + model: nn.Module. Specific `PPHGNetV2_B0` model depends on args. + """ + stage_config = { + # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num + "stage1": [16, 16, 64, 1, False, False, 3, 3], + "stage2": [64, 32, 256, 1, True, False, 3, 3], + "stage3": [256, 64, 512, 2, True, True, 5, 3], + "stage4": [512, 128, 1024, 1, True, True, 5, 3], + } + + model = PPHGNetV2( + stem_channels=[3, 16, 16], stage_config=stage_config, use_lab=True, **kwargs + ) + return model + + +def PPHGNetV2_B1(pretrained=False, use_ssld=False, **kwargs): + """ + PPHGNetV2_B1 + Args: + pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. + If str, means the path of the pretrained model. + use_ssld (bool) Whether using ssld pretrained model when pretrained is True. + Returns: + model: nn.Module. Specific `PPHGNetV2_B1` model depends on args. + """ + stage_config = { + # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num + "stage1": [32, 32, 64, 1, False, False, 3, 3], + "stage2": [64, 48, 256, 1, True, False, 3, 3], + "stage3": [256, 96, 512, 2, True, True, 5, 3], + "stage4": [512, 192, 1024, 1, True, True, 5, 3], + } + + model = PPHGNetV2( + stem_channels=[3, 24, 32], stage_config=stage_config, use_lab=True, **kwargs + ) + return model + + +def PPHGNetV2_B2(pretrained=False, use_ssld=False, **kwargs): + """ + PPHGNetV2_B2 + Args: + pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. + If str, means the path of the pretrained model. + use_ssld (bool) Whether using ssld pretrained model when pretrained is True. + Returns: + model: nn.Module. Specific `PPHGNetV2_B2` model depends on args. + """ + stage_config = { + # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num + "stage1": [32, 32, 96, 1, False, False, 3, 4], + "stage2": [96, 64, 384, 1, True, False, 3, 4], + "stage3": [384, 128, 768, 3, True, True, 5, 4], + "stage4": [768, 256, 1536, 1, True, True, 5, 4], + } + + model = PPHGNetV2( + stem_channels=[3, 24, 32], stage_config=stage_config, use_lab=True, **kwargs + ) + return model + + +def PPHGNetV2_B3(pretrained=False, use_ssld=False, **kwargs): + """ + PPHGNetV2_B3 + Args: + pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. + If str, means the path of the pretrained model. + use_ssld (bool) Whether using ssld pretrained model when pretrained is True. + Returns: + model: nn.Module. Specific `PPHGNetV2_B3` model depends on args. + """ + stage_config = { + # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num + "stage1": [32, 32, 128, 1, False, False, 3, 5], + "stage2": [128, 64, 512, 1, True, False, 3, 5], + "stage3": [512, 128, 1024, 3, True, True, 5, 5], + "stage4": [1024, 256, 2048, 1, True, True, 5, 5], + } + + model = PPHGNetV2( + stem_channels=[3, 24, 32], stage_config=stage_config, use_lab=True, **kwargs + ) + return model + + +def PPHGNetV2_B4(pretrained=False, use_ssld=False, det=False, text_rec=False, **kwargs): + """ + PPHGNetV2_B4 + Args: + pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. + If str, means the path of the pretrained model. + use_ssld (bool) Whether using ssld pretrained model when pretrained is True. + Returns: + model: nn.Module. Specific `PPHGNetV2_B4` model depends on args. + """ + stage_config_rec = { + # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num, stride + "stage1": [48, 48, 128, 1, True, False, 3, 6, [2, 1]], + "stage2": [128, 96, 512, 1, True, False, 3, 6, [1, 2]], + "stage3": [512, 192, 1024, 3, True, True, 5, 6, [2, 1]], + "stage4": [1024, 384, 2048, 1, True, True, 5, 6, [2, 1]], + } + + stage_config_det = { + # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num + "stage1": [48, 48, 128, 1, False, False, 3, 6, 2], + "stage2": [128, 96, 512, 1, True, False, 3, 6, 2], + "stage3": [512, 192, 1024, 3, True, True, 5, 6, 2], + "stage4": [1024, 384, 2048, 1, True, True, 5, 6, 2], + } + model = PPHGNetV2( + stem_channels=[3, 32, 48], + stage_config=stage_config_det if det else stage_config_rec, + use_lab=False, + det=det, + text_rec=text_rec, + **kwargs, + ) + return model + + +def PPHGNetV2_B5(pretrained=False, use_ssld=False, **kwargs): + """ + PPHGNetV2_B5 + Args: + pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. + If str, means the path of the pretrained model. + use_ssld (bool) Whether using ssld pretrained model when pretrained is True. + Returns: + model: nn.Module. Specific `PPHGNetV2_B5` model depends on args. + """ + stage_config = { + # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num + "stage1": [64, 64, 128, 1, False, False, 3, 6], + "stage2": [128, 128, 512, 2, True, False, 3, 6], + "stage3": [512, 256, 1024, 5, True, True, 5, 6], + "stage4": [1024, 512, 2048, 2, True, True, 5, 6], + } + + model = PPHGNetV2( + stem_channels=[3, 32, 64], stage_config=stage_config, use_lab=False, **kwargs + ) + return model + + +def PPHGNetV2_B6(pretrained=False, use_ssld=False, **kwargs): + """ + PPHGNetV2_B6 + Args: + pretrained (bool/str): If `True` load pretrained parameters, `False` otherwise. + If str, means the path of the pretrained model. + use_ssld (bool) Whether using ssld pretrained model when pretrained is True. + Returns: + model: nn.Module. Specific `PPHGNetV2_B6` model depends on args. + """ + stage_config = { + # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num + "stage1": [96, 96, 192, 2, False, False, 3, 6], + "stage2": [192, 192, 512, 3, True, False, 3, 6], + "stage3": [512, 384, 1024, 6, True, True, 5, 6], + "stage4": [1024, 768, 2048, 3, True, True, 5, 6], + } + + model = PPHGNetV2( + stem_channels=[3, 48, 96], stage_config=stage_config, use_lab=False, **kwargs + ) + return model + + +class PPHGNetV2_B4_Formula(nn.Module): + """ + PPHGNetV2_B4_Formula + Args: + in_channels (int): Number of input channels. Default is 3 (for RGB images). + class_num (int): Number of classes for classification. Default is 1000. + Returns: + model: nn.Module. Specific `PPHGNetV2_B4` model with defined architecture. + """ + + def __init__(self, in_channels=3, class_num=1000): + super().__init__() + self.in_channels = in_channels + self.out_channels = 2048 + stage_config = { + # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num + "stage1": [48, 48, 128, 1, False, False, 3, 6, 2], + "stage2": [128, 96, 512, 1, True, False, 3, 6, 2], + "stage3": [512, 192, 1024, 3, True, True, 5, 6, 2], + "stage4": [1024, 384, 2048, 1, True, True, 5, 6, 2], + } + + self.pphgnet_b4 = PPHGNetV2( + stem_channels=[3, 32, 48], + stage_config=stage_config, + class_num=class_num, + use_lab=False, + ) + + def forward(self, input_data): + if self.training: + pixel_values, label, attention_mask = input_data + else: + if isinstance(input_data, list): + pixel_values = input_data[0] + else: + pixel_values = input_data + num_channels = pixel_values.shape[1] + if num_channels == 1: + pixel_values = torch.repeat_interleave(pixel_values, repeats=3, dim=1) + pphgnet_b4_output = self.pphgnet_b4(pixel_values) + b, c, h, w = pphgnet_b4_output.shape + pphgnet_b4_output = pphgnet_b4_output.reshape([b, c, h * w]).transpose( + [0, 2, 1] + ) + pphgnet_b4_output = DonutSwinModelOutput( + last_hidden_state=pphgnet_b4_output, + pooler_output=None, + hidden_states=None, + attentions=False, + reshaped_hidden_states=None, + ) + if self.training: + return pphgnet_b4_output, label, attention_mask + else: + return pphgnet_b4_output + + +class PPHGNetV2_B6_Formula(nn.Module): + """ + PPHGNetV2_B6_Formula + Args: + in_channels (int): Number of input channels. Default is 3 (for RGB images). + class_num (int): Number of classes for classification. Default is 1000. + Returns: + model: nn.Module. Specific `PPHGNetV2_B6` model with defined architecture. + """ + + def __init__(self, in_channels=3, class_num=1000): + super().__init__() + self.in_channels = in_channels + self.out_channels = 2048 + stage_config = { + # in_channels, mid_channels, out_channels, num_blocks, is_downsample, light_block, kernel_size, layer_num + "stage1": [96, 96, 192, 2, False, False, 3, 6, 2], + "stage2": [192, 192, 512, 3, True, False, 3, 6, 2], + "stage3": [512, 384, 1024, 6, True, True, 5, 6, 2], + "stage4": [1024, 768, 2048, 3, True, True, 5, 6, 2], + } + + self.pphgnet_b6 = PPHGNetV2( + stem_channels=[3, 48, 96], + class_num=class_num, + stage_config=stage_config, + use_lab=False, + ) + + def forward(self, input_data): + if self.training: + pixel_values, label, attention_mask = input_data + else: + if isinstance(input_data, list): + pixel_values = input_data[0] + else: + pixel_values = input_data + num_channels = pixel_values.shape[1] + if num_channels == 1: + pixel_values = torch.repeat_interleave(pixel_values, repeats=3, dim=1) + pphgnet_b6_output = self.pphgnet_b6(pixel_values) + b, c, h, w = pphgnet_b6_output.shape + pphgnet_b6_output = pphgnet_b6_output.reshape([b, c, h * w]).transpose( + [0, 2, 1] + ) + pphgnet_b6_output = DonutSwinModelOutput( + last_hidden_state=pphgnet_b6_output, + pooler_output=None, + hidden_states=None, + attentions=False, + reshaped_hidden_states=None, + ) + if self.training: + return pphgnet_b6_output, label, attention_mask + else: + return pphgnet_b6_output diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_svtrnet.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_svtrnet.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_svtrnet.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/backbones/rec_svtrnet.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/common.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/common.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/common.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/common.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/__init__.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/__init__.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/cls_head.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/cls_head.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/cls_head.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/cls_head.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/det_db_head.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/det_db_head.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/det_db_head.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/det_db_head.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/rec_ctc_head.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/rec_ctc_head.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/rec_ctc_head.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/rec_ctc_head.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/rec_multi_head.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/rec_multi_head.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/rec_multi_head.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/heads/rec_multi_head.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/__init__.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/__init__.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/db_fpn.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/db_fpn.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/db_fpn.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/db_fpn.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/intracl.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/intracl.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/intracl.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/intracl.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/rnn.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/rnn.py similarity index 92% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/rnn.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/rnn.py index 79c8af3028a02abbfbc31fec95d5088e3f59c506..f59e9ddd27ec500347cf753cba22e5934f776bf5 100644 --- a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/rnn.py +++ b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/modeling/necks/rnn.py @@ -9,28 +9,28 @@ class Im2Seq(nn.Module): super().__init__() self.out_channels = in_channels - # def forward(self, x): - # B, C, H, W = x.shape - # # assert H == 1 - # x = x.squeeze(dim=2) - # # x = x.transpose([0, 2, 1]) # paddle (NTC)(batch, width, channels) - # x = x.permute(0, 2, 1) - # return x - def forward(self, x): B, C, H, W = x.shape - # 处理四维张量,将空间维度展平为序列 - if H == 1: - # 原来的处理逻辑,适用于H=1的情况 - x = x.squeeze(dim=2) - x = x.permute(0, 2, 1) # (B, W, C) - else: - # 处理H不为1的情况 - x = x.permute(0, 2, 3, 1) # (B, H, W, C) - x = x.reshape(B, H * W, C) # (B, H*W, C) - + # assert H == 1 + x = x.squeeze(dim=2) + # x = x.transpose([0, 2, 1]) # paddle (NTC)(batch, width, channels) + x = x.permute(0, 2, 1) return x + # def forward(self, x): + # B, C, H, W = x.shape + # # 处理四维张量,将空间维度展平为序列 + # if H == 1: + # # 原来的处理逻辑,适用于H=1的情况 + # x = x.squeeze(dim=2) + # x = x.permute(0, 2, 1) # (B, W, C) + # else: + # # 处理H不为1的情况 + # x = x.permute(0, 2, 3, 1) # (B, H, W, C) + # x = x.reshape(B, H * W, C) # (B, H*W, C) + # + # return x + class EncoderWithRNN_(nn.Module): def __init__(self, in_channels, hidden_size): super(EncoderWithRNN_, self).__init__() diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/postprocess/__init__.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/postprocess/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/postprocess/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/postprocess/__init__.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/postprocess/cls_postprocess.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/postprocess/cls_postprocess.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/postprocess/cls_postprocess.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/postprocess/cls_postprocess.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/postprocess/db_postprocess.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/postprocess/db_postprocess.py similarity index 92% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/postprocess/db_postprocess.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/postprocess/db_postprocess.py index 309f7f3fe4bbaf3e9b7a472fba3c4dc0b91d202c..7d1a56502ab4704a666403ffb21e4e696902ec93 100755 --- a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/postprocess/db_postprocess.py +++ b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/postprocess/db_postprocess.py @@ -124,10 +124,10 @@ class DBPostProcess(object): ''' h, w = bitmap.shape[:2] box = _box.copy() - xmin = np.clip(np.floor(box[:, 0].min()).astype(np.int64), 0, w - 1) - xmax = np.clip(np.ceil(box[:, 0].max()).astype(np.int64), 0, w - 1) - ymin = np.clip(np.floor(box[:, 1].min()).astype(np.int64), 0, h - 1) - ymax = np.clip(np.ceil(box[:, 1].max()).astype(np.int64), 0, h - 1) + xmin = np.clip(np.floor(box[:, 0].min()).astype(np.int if 'int' in np.__dict__ else np.int32), 0, w - 1) + xmax = np.clip(np.ceil(box[:, 0].max()).astype(np.int if 'int' in np.__dict__ else np.int32), 0, w - 1) + ymin = np.clip(np.floor(box[:, 1].min()).astype(np.int if 'int' in np.__dict__ else np.int32), 0, h - 1) + ymax = np.clip(np.ceil(box[:, 1].max()).astype(np.int if 'int' in np.__dict__ else np.int32), 0, h - 1) mask = np.zeros((ymax - ymin + 1, xmax - xmin + 1), dtype=np.uint8) box[:, 0] = box[:, 0] - xmin diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/postprocess/rec_postprocess.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/postprocess/rec_postprocess.py similarity index 87% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/postprocess/rec_postprocess.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/postprocess/rec_postprocess.py index c83fe5c33dbee9be142880aa088f054131dac042..467f51ece2d3b710a0e0d59280c00fff07850498 100755 --- a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/postprocess/rec_postprocess.py +++ b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/postprocess/rec_postprocess.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import re import numpy as np import torch @@ -24,8 +25,9 @@ class BaseRecLabelDecode(object): self.beg_str = "sos" self.end_str = "eos" - + self.reverse = False self.character_str = [] + if character_dict_path is None: self.character_str = "0123456789abcdefghijklmnopqrstuvwxyz" dict_character = list(self.character_str) @@ -38,6 +40,8 @@ class BaseRecLabelDecode(object): if use_space_char: self.character_str.append(" ") dict_character = list(self.character_str) + if "arabic" in character_dict_path: + self.reverse = True dict_character = self.add_special_char(dict_character) self.dict = {} @@ -45,10 +49,98 @@ class BaseRecLabelDecode(object): self.dict[char] = i self.character = dict_character + def pred_reverse(self, pred): + pred_re = [] + c_current = "" + for c in pred: + if not bool(re.search("[a-zA-Z0-9 :*./%+-]", c)): + if c_current != "": + pred_re.append(c_current) + pred_re.append(c) + c_current = "" + else: + c_current += c + if c_current != "": + pred_re.append(c_current) + + return "".join(pred_re[::-1]) + def add_special_char(self, dict_character): return dict_character - def decode(self, text_index, text_prob=None, is_remove_duplicate=False): + def get_word_info(self, text, selection): + """ + Group the decoded characters and record the corresponding decoded positions. + + Args: + text: the decoded text + selection: the bool array that identifies which columns of features are decoded as non-separated characters + Returns: + word_list: list of the grouped words + word_col_list: list of decoding positions corresponding to each character in the grouped word + state_list: list of marker to identify the type of grouping words, including two types of grouping words: + - 'cn': continuous chinese characters (e.g., 你好啊) + - 'en&num': continuous english characters (e.g., hello), number (e.g., 123, 1.123), or mixed of them connected by '-' (e.g., VGG-16) + The remaining characters in text are treated as separators between groups (e.g., space, '(', ')', etc.). + """ + state = None + word_content = [] + word_col_content = [] + word_list = [] + word_col_list = [] + state_list = [] + valid_col = np.where(selection == True)[0] + + for c_i, char in enumerate(text): + if "\u4e00" <= char <= "\u9fff": + c_state = "cn" + elif bool(re.search("[a-zA-Z0-9]", char)): + c_state = "en&num" + else: + c_state = "splitter" + + if ( + char == "." + and state == "en&num" + and c_i + 1 < len(text) + and bool(re.search("[0-9]", text[c_i + 1])) + ): # grouping floating number + c_state = "en&num" + if ( + char == "-" and state == "en&num" + ): # grouping word with '-', such as 'state-of-the-art' + c_state = "en&num" + + if state == None: + state = c_state + + if state != c_state: + if len(word_content) != 0: + word_list.append(word_content) + word_col_list.append(word_col_content) + state_list.append(state) + word_content = [] + word_col_content = [] + state = c_state + + if state != "splitter": + word_content.append(char) + word_col_content.append(valid_col[c_i]) + + if len(word_content) != 0: + word_list.append(word_content) + word_col_list.append(word_col_content) + state_list.append(state) + + return word_list, word_col_list, state_list + + def decode( + self, + text_index, + text_prob=None, + is_remove_duplicate=False, + return_word_box=False, + ): """ convert text-index into text-label. """ result_list = [] ignored_tokens = self.get_ignored_tokens() @@ -88,12 +180,22 @@ class CTCLabelDecode(BaseRecLabelDecode): super(CTCLabelDecode, self).__init__(character_dict_path, use_space_char) - def __call__(self, preds, label=None, *args, **kwargs): + def __call__(self, preds, label=None, return_word_box=False, *args, **kwargs): if isinstance(preds, torch.Tensor): preds = preds.numpy() preds_idx = preds.argmax(axis=2) preds_prob = preds.max(axis=2) - text = self.decode(preds_idx, preds_prob, is_remove_duplicate=True) + text = self.decode( + preds_idx, + preds_prob, + is_remove_duplicate=True, + return_word_box=return_word_box, + ) + if return_word_box: + for rec_idx, rec in enumerate(text): + wh_ratio = kwargs["wh_ratio_list"][rec_idx] + max_wh_ratio = kwargs["max_wh_ratio"] + rec[2][0] = rec[2][0] * (wh_ratio / max_wh_ratio) if label is None: return text diff --git a/magic_pdf/dict2md/__init__.py b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/__init__.py old mode 100644 new mode 100755 similarity index 100% rename from magic_pdf/dict2md/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/__init__.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/arch_config.yaml b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/arch_config.yaml similarity index 96% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/arch_config.yaml rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/arch_config.yaml index 2dd3b633a8c13d5c450ebc93f84c8f59ae5c8d93..5d4d0369fad55e1685152f774da909991fa8487a 100644 --- a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/arch_config.yaml +++ b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/arch_config.yaml @@ -120,6 +120,22 @@ ch_PP-OCRv5_det_infer: name: DBHead k: 50 +ch_PP-OCRv5_det_server_infer: + model_type: det + algorithm: DB + Transform: null + Backbone: + name: PPHGNetV2_B4 + det: True + Neck: + name: LKPAN + out_channels: 256 + intracl: True + Head: + name: PFHeadLocal + k: 50 + mode: "large" + ch_PP-OCRv4_det_server_infer: model_type: det algorithm: DB diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/arabic_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/arabic_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/arabic_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/arabic_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/chinese_cht_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/chinese_cht_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/chinese_cht_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/chinese_cht_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/cyrillic_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/cyrillic_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/cyrillic_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/cyrillic_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/devanagari_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/devanagari_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/devanagari_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/devanagari_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/en_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/en_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/en_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/en_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/japan_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/japan_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/japan_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/japan_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ka_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ka_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ka_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ka_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/korean_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/korean_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/korean_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/korean_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/latin_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/latin_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/latin_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/latin_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocr_keys_v1.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocr_keys_v1.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocr_keys_v1.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocr_keys_v1.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocrv4_doc_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocrv4_doc_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocrv4_doc_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocrv4_doc_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocrv5_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocrv5_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocrv5_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ppocrv5_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ta_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ta_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ta_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/ta_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/te_dict.txt b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/te_dict.txt similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/te_dict.txt rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/dict/te_dict.txt diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/models_config.yml b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/models_config.yml similarity index 79% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/models_config.yml rename to mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/models_config.yml index 876f3ee993f73e7d0e9af57336242c7403415f92..1cf69092cae3b85034da874f6531a80bd13deaa4 100644 --- a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/pytorchocr/utils/resources/models_config.yml +++ b/mineru/model/ocr/paddleocr2pytorch/pytorchocr/utils/resources/models_config.yml @@ -1,22 +1,22 @@ lang: ch_lite: - det: ch_PP-OCRv3_det_infer.pth + det: ch_PP-OCRv5_det_infer.pth rec: ch_PP-OCRv5_rec_infer.pth dict: ppocrv5_dict.txt ch_lite_v4: - det: ch_PP-OCRv3_det_infer.pth + det: ch_PP-OCRv5_det_infer.pth rec: ch_PP-OCRv4_rec_infer.pth dict: ppocr_keys_v1.txt ch_server: - det: ch_PP-OCRv3_det_infer.pth + det: ch_PP-OCRv5_det_infer.pth rec: ch_PP-OCRv5_rec_server_infer.pth dict: ppocrv5_dict.txt ch_server_v4: - det: ch_PP-OCRv3_det_infer.pth + det: ch_PP-OCRv5_det_infer.pth rec: ch_PP-OCRv4_rec_server_infer.pth dict: ppocr_keys_v1.txt ch: - det: ch_PP-OCRv3_det_infer.pth + det: ch_PP-OCRv5_det_infer.pth rec: ch_PP-OCRv4_rec_server_doc_infer.pth dict: ppocrv4_doc_dict.txt en: @@ -28,12 +28,12 @@ lang: rec: korean_PP-OCRv3_rec_infer.pth dict: korean_dict.txt japan: - det: Multilingual_PP-OCRv3_det_infer.pth - rec: japan_PP-OCRv3_rec_infer.pth + det: ch_PP-OCRv5_det_infer.pth + rec: ch_PP-OCRv5_rec_server_infer.pth dict: japan_dict.txt chinese_cht: - det: Multilingual_PP-OCRv3_det_infer.pth - rec: chinese_cht_PP-OCRv3_rec_infer.pth + det: ch_PP-OCRv5_det_infer.pth + rec: ch_PP-OCRv5_rec_server_infer.pth dict: chinese_cht_dict.txt ta: det: Multilingual_PP-OCRv3_det_infer.pth diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/__init__.py b/mineru/model/ocr/paddleocr2pytorch/tools/__init__.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/__init__.py rename to mineru/model/ocr/paddleocr2pytorch/tools/__init__.py diff --git a/mineru/model/ocr/paddleocr2pytorch/tools/infer/__init__.py b/mineru/model/ocr/paddleocr2pytorch/tools/infer/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/model/ocr/paddleocr2pytorch/tools/infer/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/predict_cls.py b/mineru/model/ocr/paddleocr2pytorch/tools/infer/predict_cls.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/predict_cls.py rename to mineru/model/ocr/paddleocr2pytorch/tools/infer/predict_cls.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/predict_det.py b/mineru/model/ocr/paddleocr2pytorch/tools/infer/predict_det.py similarity index 67% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/predict_det.py rename to mineru/model/ocr/paddleocr2pytorch/tools/infer/predict_det.py index c6f1f9c7b95e61b8ee3789246238f999b3378bd5..3de483acf1cd8c09b5d11bbfd738632b88594382 100755 --- a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/predict_det.py +++ b/mineru/model/ocr/paddleocr2pytorch/tools/infer/predict_det.py @@ -117,6 +117,128 @@ class TextDetector(BaseOCRV20): self.net.eval() self.net.to(self.device) + def _batch_process_same_size(self, img_list): + """ + 对相同尺寸的图像进行批处理 + + Args: + img_list: 相同尺寸的图像列表 + + Returns: + batch_results: 批处理结果列表 + total_elapse: 总耗时 + """ + starttime = time.time() + + # 预处理所有图像 + batch_data = [] + batch_shapes = [] + ori_imgs = [] + + for img in img_list: + ori_im = img.copy() + ori_imgs.append(ori_im) + + data = {'image': img} + data = transform(data, self.preprocess_op) + if data is None: + # 如果预处理失败,返回空结果 + return [(None, 0) for _ in img_list], 0 + + img_processed, shape_list = data + batch_data.append(img_processed) + batch_shapes.append(shape_list) + + # 堆叠成批处理张量 + try: + batch_tensor = np.stack(batch_data, axis=0) + batch_shapes = np.stack(batch_shapes, axis=0) + except Exception as e: + # 如果堆叠失败,回退到逐个处理 + batch_results = [] + for img in img_list: + dt_boxes, elapse = self.__call__(img) + batch_results.append((dt_boxes, elapse)) + return batch_results, time.time() - starttime + + # 批处理推理 + with torch.no_grad(): + inp = torch.from_numpy(batch_tensor) + inp = inp.to(self.device) + outputs = self.net(inp) + + # 处理输出 + preds = {} + if self.det_algorithm == "EAST": + preds['f_geo'] = outputs['f_geo'].cpu().numpy() + preds['f_score'] = outputs['f_score'].cpu().numpy() + elif self.det_algorithm == 'SAST': + preds['f_border'] = outputs['f_border'].cpu().numpy() + preds['f_score'] = outputs['f_score'].cpu().numpy() + preds['f_tco'] = outputs['f_tco'].cpu().numpy() + preds['f_tvo'] = outputs['f_tvo'].cpu().numpy() + elif self.det_algorithm in ['DB', 'PSE', 'DB++']: + preds['maps'] = outputs['maps'].cpu().numpy() + elif self.det_algorithm == 'FCE': + for i, (k, output) in enumerate(outputs.items()): + preds['level_{}'.format(i)] = output.cpu().numpy() + else: + raise NotImplementedError + + # 后处理每个图像的结果 + batch_results = [] + total_elapse = time.time() - starttime + + for i in range(len(img_list)): + # 提取单个图像的预测结果 + single_preds = {} + for key, value in preds.items(): + if isinstance(value, np.ndarray): + single_preds[key] = value[i:i + 1] # 保持批次维度 + else: + single_preds[key] = value + + # 后处理 + post_result = self.postprocess_op(single_preds, batch_shapes[i:i + 1]) + dt_boxes = post_result[0]['points'] + + # 过滤和裁剪检测框 + if (self.det_algorithm == "SAST" and + self.det_sast_polygon) or (self.det_algorithm in ["PSE", "FCE"] and + self.postprocess_op.box_type == 'poly'): + dt_boxes = self.filter_tag_det_res_only_clip(dt_boxes, ori_imgs[i].shape) + else: + dt_boxes = self.filter_tag_det_res(dt_boxes, ori_imgs[i].shape) + + batch_results.append((dt_boxes, total_elapse / len(img_list))) + + return batch_results, total_elapse + + def batch_predict(self, img_list, max_batch_size=8): + """ + 批处理预测方法,支持多张图像同时检测 + + Args: + img_list: 图像列表 + max_batch_size: 最大批处理大小 + + Returns: + batch_results: 批处理结果列表,每个元素为(dt_boxes, elapse) + """ + if not img_list: + return [] + + batch_results = [] + + # 分批处理 + for i in range(0, len(img_list), max_batch_size): + batch_imgs = img_list[i:i + max_batch_size] + # assert尺寸一致 + batch_dt_boxes, batch_elapse = self._batch_process_same_size(batch_imgs) + batch_results.extend(batch_dt_boxes) + + return batch_results + def order_points_clockwise(self, pts): """ reference from: https://github.com/jrosebr1/imutils/blob/master/imutils/perspective.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/predict_rec.py b/mineru/model/ocr/paddleocr2pytorch/tools/infer/predict_rec.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/predict_rec.py rename to mineru/model/ocr/paddleocr2pytorch/tools/infer/predict_rec.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/predict_system.py b/mineru/model/ocr/paddleocr2pytorch/tools/infer/predict_system.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/predict_system.py rename to mineru/model/ocr/paddleocr2pytorch/tools/infer/predict_system.py diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/pytorchocr_utility.py b/mineru/model/ocr/paddleocr2pytorch/tools/infer/pytorchocr_utility.py similarity index 100% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/tools/infer/pytorchocr_utility.py rename to mineru/model/ocr/paddleocr2pytorch/tools/infer/pytorchocr_utility.py diff --git a/mineru/model/reading_order/__init__.py b/mineru/model/reading_order/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/model/reading_order/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/magic_pdf/model/sub_modules/reading_oreder/layoutreader/helpers.py b/mineru/model/reading_order/layout_reader.py similarity index 100% rename from magic_pdf/model/sub_modules/reading_oreder/layoutreader/helpers.py rename to mineru/model/reading_order/layout_reader.py diff --git a/magic_pdf/model/sub_modules/reading_oreder/layoutreader/xycut.py b/mineru/model/reading_order/xycut.py similarity index 100% rename from magic_pdf/model/sub_modules/reading_oreder/layoutreader/xycut.py rename to mineru/model/reading_order/xycut.py diff --git a/mineru/model/table/__init__.py b/mineru/model/table/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/model/table/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/magic_pdf/model/sub_modules/table/rapidtable/rapid_table.py b/mineru/model/table/rapid_table.py similarity index 66% rename from magic_pdf/model/sub_modules/table/rapidtable/rapid_table.py rename to mineru/model/table/rapid_table.py index b698b3efb3c7ce57f2b526f6c88a1b0d04a0fd35..2252af8d78a1f534fb3439745220df0d969ad3d5 100644 --- a/magic_pdf/model/sub_modules/table/rapidtable/rapid_table.py +++ b/mineru/model/table/rapid_table.py @@ -1,41 +1,18 @@ import os -from pathlib import Path import cv2 import numpy as np -import torch from loguru import logger from rapid_table import RapidTable, RapidTableInput -from rapid_table.main import ModelType -from magic_pdf.libs.config_reader import get_device +from mineru.utils.enum_class import ModelPath +from mineru.utils.models_download_utils import auto_download_and_get_model_root_path class RapidTableModel(object): - def __init__(self, ocr_engine, table_sub_model_name='slanet_plus'): - sub_model_list = [model.value for model in ModelType] - if table_sub_model_name is None: - input_args = RapidTableInput() - elif table_sub_model_name in sub_model_list: - if torch.cuda.is_available() and table_sub_model_name == "unitable": - input_args = RapidTableInput(model_type=table_sub_model_name, use_cuda=True, device=get_device()) - else: - root_dir = Path(__file__).absolute().parent.parent.parent.parent.parent - slanet_plus_model_path = os.path.join(root_dir, 'resources', 'slanet_plus', 'slanet-plus.onnx') - input_args = RapidTableInput(model_type=table_sub_model_name, model_path=slanet_plus_model_path) - else: - raise ValueError(f"Invalid table_sub_model_name: {table_sub_model_name}. It must be one of {sub_model_list}") - + def __init__(self, ocr_engine): + slanet_plus_model_path = os.path.join(auto_download_and_get_model_root_path(ModelPath.slanet_plus), ModelPath.slanet_plus) + input_args = RapidTableInput(model_type='slanet_plus', model_path=slanet_plus_model_path) self.table_model = RapidTable(input_args) - - # self.ocr_model_name = "RapidOCR" - # if torch.cuda.is_available(): - # from rapidocr_paddle import RapidOCR - # self.ocr_engine = RapidOCR(det_use_cuda=True, cls_use_cuda=True, rec_use_cuda=True) - # else: - # from rapidocr_onnxruntime import RapidOCR - # self.ocr_engine = RapidOCR() - - # self.ocr_model_name = "PaddleOCR" self.ocr_engine = ocr_engine diff --git a/mineru/model/vlm_hf_model/__init__.py b/mineru/model/vlm_hf_model/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..d463f72f1f21d24ea180224146678112f80156b0 --- /dev/null +++ b/mineru/model/vlm_hf_model/__init__.py @@ -0,0 +1,9 @@ +from transformers import AutoConfig, AutoImageProcessor, AutoModelForCausalLM + +from .configuration_mineru2 import Mineru2QwenConfig +from .image_processing_mineru2 import Mineru2ImageProcessor +from .modeling_mineru2 import Mineru2QwenForCausalLM + +AutoConfig.register(Mineru2QwenConfig.model_type, Mineru2QwenConfig) +AutoModelForCausalLM.register(Mineru2QwenConfig, Mineru2QwenForCausalLM) +AutoImageProcessor.register(Mineru2QwenConfig, slow_image_processor_class=Mineru2ImageProcessor) diff --git a/mineru/model/vlm_hf_model/configuration_mineru2.py b/mineru/model/vlm_hf_model/configuration_mineru2.py new file mode 100644 index 0000000000000000000000000000000000000000..1ac8f6ae5e12df9b79c822727124d095bec12433 --- /dev/null +++ b/mineru/model/vlm_hf_model/configuration_mineru2.py @@ -0,0 +1,38 @@ +from transformers import Qwen2Config + + +class Mineru2QwenConfig(Qwen2Config): + model_type = "mineru2_qwen" + + def __init__( + self, + ignore_index=-100, + image_aspect_ratio="square_anyres_max_9", + image_grid_pinpoints="(1x1),...,(4x4)", + image_token_index=151646, + mm_hidden_size=1152, + mm_patch_merge_type="spatial_unpad", + mm_projector_type="mlp2x_gelu", + mm_vision_select_feature="full", + mm_vision_select_layer=-2, + mm_vision_tower="google/siglip-so400m-patch14-384", + tie_word_embeddings=False, + tokenizer_model_max_length=16384, + tokenizer_padding_side="right", + unfreeze_mm_vision_tower=True, + **kwargs, + ): + self.ignore_index = ignore_index + self.image_aspect_ratio = image_aspect_ratio + self.image_grid_pinpoints = image_grid_pinpoints + self.image_token_index = image_token_index + self.mm_hidden_size = mm_hidden_size + self.mm_patch_merge_type = mm_patch_merge_type + self.mm_projector_type = mm_projector_type + self.mm_vision_select_feature = mm_vision_select_feature + self.mm_vision_select_layer = mm_vision_select_layer + self.mm_vision_tower = mm_vision_tower + self.tokenizer_model_max_length = tokenizer_model_max_length + self.tokenizer_padding_side = tokenizer_padding_side + self.unfreeze_mm_vision_tower = unfreeze_mm_vision_tower + super().__init__(tie_word_embeddings=tie_word_embeddings, **kwargs) diff --git a/mineru/model/vlm_hf_model/image_processing_mineru2.py b/mineru/model/vlm_hf_model/image_processing_mineru2.py new file mode 100644 index 0000000000000000000000000000000000000000..276c615416f9031dd0a46d1ba73b947f5afffb2b --- /dev/null +++ b/mineru/model/vlm_hf_model/image_processing_mineru2.py @@ -0,0 +1,269 @@ +import ast +import math +import re +from functools import partial, reduce +from typing import Dict, Optional, Union + +import numpy as np +import torch +from PIL import Image +from transformers.image_processing_utils import ( + BaseImageProcessor, + BatchFeature, + get_size_dict, +) +from transformers.image_transforms import ( + convert_to_rgb, + normalize, + rescale, + resize, + to_channel_dimension_format, +) +from transformers.image_utils import ( + ChannelDimension, + PILImageResampling, + to_numpy_array, +) +from transformers.utils import TensorType + + +def select_best_resolution(original_size: tuple, possible_resolutions: list) -> tuple: + original_width, original_height = original_size + best_fit = (0, 0) + max_effective_resolution = 0 + min_wasted_resolution = float("inf") + + for width, height in possible_resolutions: + scale = min(width / original_width, height / original_height) + downscaled_width, downscaled_height = int(original_width * scale), int(original_height * scale) + effective_resolution = min(downscaled_width * downscaled_height, original_width * original_height) + wasted_resolution = (width * height) - effective_resolution + + if effective_resolution > max_effective_resolution or ( + effective_resolution == max_effective_resolution and wasted_resolution < min_wasted_resolution + ): + max_effective_resolution = effective_resolution + min_wasted_resolution = wasted_resolution + best_fit = (width, height) + + return best_fit + + +def divide_to_patches(image, patch_size): + patches = [] + width, height = image.size + for i in range(0, height, patch_size): + for j in range(0, width, patch_size): + box = (j, i, j + patch_size, i + patch_size) + patch = image.crop(box) + patches.append(patch) + return patches + + +def expand2square(pil_img, background_color): + width, height = pil_img.size + if width == height: + return pil_img + if pil_img.mode == "L": + pil_img = pil_img.convert("RGB") + if width > height: + result = Image.new(pil_img.mode, (width, width), background_color) + result.paste(pil_img, (0, (width - height) // 2)) + return result + else: + result = Image.new(pil_img.mode, (height, height), background_color) + result.paste(pil_img, ((height - width) // 2, 0)) + return result + + +def get_anyres_image_grid_shape(image_size, grid_pinpoints, patch_size): + if isinstance(grid_pinpoints, str) and "x" in grid_pinpoints: + assert patch_size in [224, 336, 384, 448, 512], "patch_size should be in [224, 336, 384, 448, 512]" + matches = re.findall(r"\((\d+)x(\d+)\)", grid_pinpoints) + range_start = tuple(map(int, matches[0])) + range_end = tuple(map(int, matches[-1])) + grid_pinpoints = [ + (i, j) for i in range(range_start[0], range_end[0] + 1) for j in range(range_start[1], range_end[1] + 1) + ] + grid_pinpoints = [[dim * patch_size for dim in pair] for pair in grid_pinpoints] + if type(grid_pinpoints) is list: + possible_resolutions = grid_pinpoints + else: + possible_resolutions = ast.literal_eval(grid_pinpoints) # type: ignore + width, height = select_best_resolution(image_size, possible_resolutions) + return width // patch_size, height // patch_size + + +# This functions is not used. +def resize_and_pad_image(image, target_resolution): + original_width, original_height = image.size + target_width, target_height = target_resolution + + scale_w = target_width / original_width + scale_h = target_height / original_height + + if scale_w < scale_h: + new_width = target_width + new_height = min(math.ceil(original_height * scale_w), target_height) + else: + new_height = target_height + new_width = min(math.ceil(original_width * scale_h), target_width) + + # Resize the image + resized_image = image.resize((new_width, new_height)) + + new_image = Image.new("RGB", (target_width, target_height), (0, 0, 0)) + paste_x = (target_width - new_width) // 2 + paste_y = (target_height - new_height) // 2 + new_image.paste(resized_image, (paste_x, paste_y)) + + return new_image + + +# DIFFERENT from sglang.srt.mm_utils.process_anyres_image +def process_anyres_image(image, processor, grid_pinpoints): + if isinstance(grid_pinpoints, str) and "x" in grid_pinpoints: + patch_size = processor.crop_size["height"] + assert patch_size in [224, 336, 384, 448, 512], "patch_size should be in [224, 336, 384, 448, 512]" + matches = re.findall(r"\((\d+)x(\d+)\)", grid_pinpoints) + range_start = tuple(map(int, matches[0])) + range_end = tuple(map(int, matches[-1])) + grid_pinpoints = [ + (i, j) for i in range(range_start[0], range_end[0] + 1) for j in range(range_start[1], range_end[1] + 1) + ] + grid_pinpoints = [[dim * patch_size for dim in pair] for pair in grid_pinpoints] + + if type(grid_pinpoints) is list: + possible_resolutions = grid_pinpoints + else: + possible_resolutions = ast.literal_eval(grid_pinpoints) # type: ignore + best_resolution = select_best_resolution(image.size, possible_resolutions) + + # image_padded = resize_and_pad_image(image, best_resolution) + image_padded = image.resize(best_resolution) + + patches = divide_to_patches(image_padded, processor.crop_size["height"]) + + image_original_resize = image.resize((processor.crop_size["height"], processor.crop_size["height"])) + + image_patches = [image_original_resize] + patches + image_patches = [processor.preprocess(image_patch, return_tensors="pt")["pixel_values"][0] for image_patch in image_patches] + return torch.stack(image_patches, dim=0) + + +def process_images(images, image_processor, model_cfg): + image_aspect_ratio = getattr(model_cfg, "image_aspect_ratio", "") + new_images = [] + if image_aspect_ratio == "pad": + for image in images: + image = expand2square(image, tuple(int(x * 255) for x in image_processor.image_mean)) + image = image_processor.preprocess(image, return_tensors="pt")["pixel_values"][0] + new_images.append(image) + elif image_aspect_ratio == "anyres" or "anyres_max" in image_aspect_ratio: + for image in images: + image = process_anyres_image(image, image_processor, model_cfg.image_grid_pinpoints) + new_images.append(image) + else: + return image_processor(images, return_tensors="pt")["pixel_values"] + if all(x.shape == new_images[0].shape for x in new_images): + new_images = torch.stack(new_images, dim=0) + return new_images + + +class Mineru2ImageProcessor(BaseImageProcessor): + model_input_names = ["pixel_values"] + + def __init__( + self, + image_mean=(0.5, 0.5, 0.5), + image_std=(0.5, 0.5, 0.5), + size=(384, 384), + crop_size: Optional[Dict[str, int]] = None, + resample=PILImageResampling.BICUBIC, + rescale_factor=1 / 255, + data_format=ChannelDimension.FIRST, + image_aspect_ratio: Optional[str] = None, + image_grid_pinpoints: Optional[list] = None, + **kwargs, + ) -> None: + super().__init__(**kwargs) + + crop_size = crop_size if crop_size is not None else {"height": 384, "width": 384} + crop_size = get_size_dict(crop_size, default_to_square=True, param_name="crop_size") + + self.image_mean = image_mean + self.image_std = image_std + self.size = size + self.resample = resample + self.rescale_factor = rescale_factor + self.data_format = data_format + self.crop_size = crop_size + self.image_aspect_ratio = image_aspect_ratio + self.image_grid_pinpoints = image_grid_pinpoints + self.in_e2e_processing = False + + def _preprocess(self, images): + if isinstance(images, Image.Image): + images = [images] + else: + # to adapt video data + images = [to_numpy_array(image) for image in images] + assert isinstance(images, list) + + transforms = [ + convert_to_rgb, + to_numpy_array, + partial(resize, size=self.size, resample=self.resample, data_format=self.data_format), + partial(rescale, scale=self.rescale_factor, data_format=self.data_format), + partial(normalize, mean=self.image_mean, std=self.image_std, data_format=self.data_format), + partial(to_channel_dimension_format, channel_dim=self.data_format, input_channel_dim=self.data_format), + ] + + images = reduce(lambda x, f: [*map(f, x)], transforms, images) + return {"pixel_values": images} + + def _preprocess_end_to_end(self, images): + image_aspect_ratio = self.image_aspect_ratio + image_grid_pinpoints = self.image_grid_pinpoints + assert image_aspect_ratio is not None + assert image_grid_pinpoints is not None + + pixel_values = [] + if image_aspect_ratio == "pad": + for image in images: + image = expand2square(image, tuple(int(x * 255) for x in self.image_mean)) + image = self._preprocess(image)["pixel_values"][0] + pixel_values.append(image) + elif image_aspect_ratio == "anyres" or "anyres_max" in image_aspect_ratio: + for image in images: + image = process_anyres_image(image, self, self.image_grid_pinpoints) + pixel_values.append(image.numpy()) + else: + pixel_values = self._preprocess(images)["pixel_values"] + + if isinstance(pixel_values, list) and all(x.shape == pixel_values[0].shape for x in pixel_values): + pixel_values = np.stack(pixel_values, axis=0) + + # CAUTION: here used (height, width). + image_sizes = [(image.height, image.width) for image in images] + assert len(pixel_values) == len(image_sizes) + + return {"pixel_values": pixel_values, "image_sizes": image_sizes} + + def preprocess( + self, + images, + return_tensors: Optional[Union[str, TensorType]] = None, + **kwargs, + ): + if self.image_aspect_ratio is None or self.in_e2e_processing: + data = self._preprocess(images) + else: + assert self.image_grid_pinpoints is not None + self.in_e2e_processing = True + try: + data = self._preprocess_end_to_end(images) + finally: + self.in_e2e_processing = False + + return BatchFeature(data=data, tensor_type=return_tensors) diff --git a/mineru/model/vlm_hf_model/modeling_mineru2.py b/mineru/model/vlm_hf_model/modeling_mineru2.py new file mode 100644 index 0000000000000000000000000000000000000000..a52d7c4485f213e483f3a0883a1b8a33e5737f71 --- /dev/null +++ b/mineru/model/vlm_hf_model/modeling_mineru2.py @@ -0,0 +1,449 @@ +import math +import re +from typing import List, Optional, Tuple, Union + +import torch +import torch.nn as nn +from transformers import ( + Qwen2ForCausalLM, + Qwen2Model, + SiglipVisionConfig, + SiglipVisionModel, +) +from transformers.generation.utils import GenerateOutput +from transformers.modeling_outputs import CausalLMOutputWithPast + +from .configuration_mineru2 import Mineru2QwenConfig +from .image_processing_mineru2 import Mineru2ImageProcessor, get_anyres_image_grid_shape + + +class SiglipVisionTower(nn.Module): + def __init__(self, vision_tower): + super().__init__() + + self.config = SiglipVisionConfig.from_pretrained(vision_tower) + assert isinstance(self.config, SiglipVisionConfig) + self.config.num_hidden_layers -= 1 # drop the last hidden layer + self.config.vision_use_head = False + + self.vision_tower = SiglipVisionModel(self.config) + self.vision_tower.requires_grad_(False) + + self.image_processor = Mineru2ImageProcessor() + + def forward(self, images): + if type(images) is list: + image_features = [] + for image in images: + image_forward_out = self.vision_tower( + image.to(device=self.device, dtype=self.dtype).unsqueeze(0), output_hidden_states=True + ) + image_feature = image_forward_out.hidden_states[-1].to(image.dtype) + image_features.append(image_feature) + else: + image_forward_outs = self.vision_tower(images.to(device=self.device, dtype=self.dtype), output_hidden_states=True) + image_features = image_forward_outs.hidden_states[-1].to(images.dtype) + + return image_features + + @property + def dummy_feature(self): + return torch.zeros(1, self.hidden_size, device=self.device, dtype=self.dtype) + + @property + def dtype(self): + for p in self.vision_tower.parameters(): + return p.dtype + + @property + def device(self): + for p in self.vision_tower.parameters(): + return p.device + + @property + def hidden_size(self): + return self.config.hidden_size + + @property + def num_patches(self): + return (self.config.image_size // self.config.patch_size) ** 2 + + @property + def num_patches_per_side(self): + return self.config.image_size // self.config.patch_size + + @property + def image_size(self): + return self.config.image_size + + +def build_vision_tower(config: Mineru2QwenConfig): + vision_tower = getattr(config, "mm_vision_tower", getattr(config, "vision_tower", "")) + model_path = getattr(config, "_name_or_path", "") + if "siglip" in vision_tower.lower(): + if model_path: + return SiglipVisionTower(f"{model_path}/{vision_tower}") + else: + return SiglipVisionTower(vision_tower) + raise ValueError(f"Unknown vision tower: {vision_tower}") + + +def build_vision_projector(config: Mineru2QwenConfig): + projector_type = getattr(config, "mm_projector_type", "linear") + + if projector_type == "linear": + return nn.Linear(config.mm_hidden_size, config.hidden_size) + + mlp_gelu_match = re.match(r"^mlp(\d+)x_gelu$", projector_type) + if mlp_gelu_match: + mlp_depth = int(mlp_gelu_match.group(1)) + modules = [nn.Linear(config.mm_hidden_size, config.hidden_size)] + for _ in range(1, mlp_depth): + modules.append(nn.GELU()) # type: ignore + modules.append(nn.Linear(config.hidden_size, config.hidden_size)) + return nn.Sequential(*modules) + + if projector_type == "identity": + return nn.Identity() + + raise ValueError(f"Unknown projector type: {projector_type}") + + +class Mineru2QwenModel(Qwen2Model): + config_class = Mineru2QwenConfig + + def __init__(self, config: Mineru2QwenConfig): + super(Mineru2QwenModel, self).__init__(config) + + self.vision_tower = build_vision_tower(config) + self.mm_projector = build_vision_projector(config) + + if "unpad" in getattr(config, "mm_patch_merge_type", ""): + self.image_newline = nn.Parameter(torch.empty(config.hidden_size, dtype=self.dtype)) + + +class Mineru2QwenForCausalLM(Qwen2ForCausalLM): + config_class = Mineru2QwenConfig + + def __init__(self, config: Mineru2QwenConfig): + super(Qwen2ForCausalLM, self).__init__(config) + config.rope_scaling = None + self.model = Mineru2QwenModel(config) + self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False) + + self.ignore_index = config.ignore_index + self.image_token_index = config.image_token_index + + # Initialize weights and apply final processing + self.post_init() + + def get_model(self): + return self.model + + def encode_images(self, images: torch.Tensor): + image_features = self.get_model().vision_tower(images) + image_features = self.get_model().mm_projector(image_features) + return image_features + + def prepare_inputs_labels_for_multimodal( + self, input_ids, position_ids, attention_mask, past_key_values, labels, images, image_sizes=None + ): + vision_tower = self.get_model().vision_tower + if vision_tower is None or images is None or input_ids.shape[1] == 1: + return input_ids, position_ids, attention_mask, past_key_values, None, labels + + if type(images) is list or images.ndim == 5: + if type(images) is list: + images = [x.unsqueeze(0) if x.ndim == 3 else x for x in images] + concat_images = torch.cat([image for image in images], dim=0) + image_features = self.encode_images(concat_images) + split_sizes = [image.shape[0] for image in images] + image_features = torch.split(image_features, split_sizes, dim=0) + mm_patch_merge_type = getattr(self.config, "mm_patch_merge_type", "flat") + image_aspect_ratio = getattr(self.config, "image_aspect_ratio", "square") + if mm_patch_merge_type == "flat": + image_features = [x.flatten(0, 1) for x in image_features] + elif mm_patch_merge_type.startswith("spatial"): + new_image_features = [] + for image_idx, image_feature in enumerate(image_features): + if image_feature.shape[0] > 1: + base_image_feature = image_feature[0] + image_feature = image_feature[1:] + height = width = self.get_model().vision_tower.num_patches_per_side + assert height * width == base_image_feature.shape[0] + + if "anyres_max" in image_aspect_ratio: + matched_anyres_max_num_patches = re.match(r"square_anyres_max_(\d+)", image_aspect_ratio) + if matched_anyres_max_num_patches: + max_num_patches = int(matched_anyres_max_num_patches.group(1)) + + if image_aspect_ratio == "anyres" or "anyres_max" in image_aspect_ratio: + num_patch_width, num_patch_height = get_anyres_image_grid_shape( + image_sizes[image_idx], + self.config.image_grid_pinpoints, + self.get_model().vision_tower.config.image_size, + ) + image_feature = image_feature.view(num_patch_height, num_patch_width, height, width, -1) + else: + raise NotImplementedError + if ( + "unpad" in mm_patch_merge_type + and "anyres_max" in image_aspect_ratio + and matched_anyres_max_num_patches + ): + unit = image_feature.shape[2] + image_feature = image_feature.permute(4, 0, 2, 1, 3).contiguous() + image_feature = image_feature.flatten(1, 2).flatten(2, 3) + c, h, w = image_feature.shape + times = math.sqrt(h * w / (max_num_patches * unit**2)) + if times > 1.1: + image_feature = image_feature[None] + image_feature = nn.functional.interpolate( + image_feature, [int(h // times), int(w // times)], mode="bilinear" + )[0] + image_feature = torch.cat( + ( + image_feature, + self.model.image_newline[:, None, None] + .expand(*image_feature.shape[:-1], 1) + .to(image_feature.device), + ), + dim=-1, + ) + image_feature = image_feature.flatten(1, 2).transpose(0, 1) + elif "unpad" in mm_patch_merge_type: + image_feature = image_feature.permute(4, 0, 2, 1, 3).contiguous() + image_feature = image_feature.flatten(1, 2).flatten(2, 3) + image_feature = torch.cat( + ( + image_feature, + self.model.image_newline[:, None, None] + .expand(*image_feature.shape[:-1], 1) + .to(image_feature.device), + ), + dim=-1, + ) + image_feature = image_feature.flatten(1, 2).transpose(0, 1) + else: + image_feature = image_feature.permute(0, 2, 1, 3, 4).contiguous() + image_feature = image_feature.flatten(0, 3) + image_feature = torch.cat((base_image_feature, image_feature), dim=0) + else: + image_feature = image_feature[0] + if "unpad" in mm_patch_merge_type: + image_feature = torch.cat( + (image_feature, self.model.image_newline[None].to(image_feature.device)), dim=0 + ) + new_image_features.append(image_feature) + image_features = new_image_features + else: + raise ValueError(f"Unexpected mm_patch_merge_type: {self.config.mm_patch_merge_type}") + else: + image_features = self.encode_images(images) + + _labels = labels + _position_ids = position_ids + _attention_mask = attention_mask + if attention_mask is None: + attention_mask = torch.ones_like(input_ids, dtype=torch.bool) + else: + attention_mask = attention_mask.bool() + if position_ids is None: + position_ids = torch.arange(0, input_ids.shape[1], dtype=torch.long, device=input_ids.device) + if labels is None: + labels = torch.full_like(input_ids, self.ignore_index) + + # remove the padding using attention_mask -- FIXME + _input_ids = input_ids + input_ids = [cur_input_ids[cur_attention_mask] for cur_input_ids, cur_attention_mask in zip(input_ids, attention_mask)] + labels = [cur_labels[cur_attention_mask] for cur_labels, cur_attention_mask in zip(labels, attention_mask)] + + new_input_embeds = [] + new_labels = [] + cur_image_idx = 0 + for batch_idx, cur_input_ids in enumerate(input_ids): + num_images = (cur_input_ids == self.image_token_index).sum() + if num_images == 0: + cur_image_features = image_features[cur_image_idx] + cur_input_embeds_1 = self.get_model().embed_tokens(cur_input_ids) + cur_input_embeds = torch.cat([cur_input_embeds_1, cur_image_features[0:0]], dim=0) + new_input_embeds.append(cur_input_embeds) + new_labels.append(labels[batch_idx]) + cur_image_idx += 1 + continue + + image_token_indices = ( + [-1] + torch.where(cur_input_ids == self.image_token_index)[0].tolist() + [cur_input_ids.shape[0]] + ) + cur_input_ids_noim = [] + cur_labels = labels[batch_idx] + cur_labels_noim = [] + for i in range(len(image_token_indices) - 1): + cur_input_ids_noim.append(cur_input_ids[image_token_indices[i] + 1 : image_token_indices[i + 1]]) + cur_labels_noim.append(cur_labels[image_token_indices[i] + 1 : image_token_indices[i + 1]]) + split_sizes = [x.shape[0] for x in cur_labels_noim] + cur_input_embeds = self.get_model().embed_tokens(torch.cat(cur_input_ids_noim)) + cur_input_embeds_no_im = torch.split(cur_input_embeds, split_sizes, dim=0) + cur_new_input_embeds = [] + cur_new_labels = [] + + for i in range(num_images + 1): + cur_new_input_embeds.append(cur_input_embeds_no_im[i]) + cur_new_labels.append(cur_labels_noim[i]) + if i < num_images: + cur_image_features = image_features[cur_image_idx] + cur_image_idx += 1 + cur_new_input_embeds.append(cur_image_features) + cur_new_labels.append( + torch.full( + (cur_image_features.shape[0],), self.ignore_index, device=cur_labels.device, dtype=cur_labels.dtype + ) + ) + + cur_new_input_embeds = [x.to(self.device) for x in cur_new_input_embeds] + + cur_new_input_embeds = torch.cat(cur_new_input_embeds) + cur_new_labels = torch.cat(cur_new_labels) + + new_input_embeds.append(cur_new_input_embeds) + new_labels.append(cur_new_labels) + + # Truncate sequences to max length as image embeddings can make the sequence longer + tokenizer_model_max_length = getattr(self.config, "tokenizer_model_max_length", None) + if tokenizer_model_max_length is not None: + new_input_embeds = [x[:tokenizer_model_max_length] for x in new_input_embeds] + new_labels = [x[:tokenizer_model_max_length] for x in new_labels] + + # Combine them + max_len = max(x.shape[0] for x in new_input_embeds) + batch_size = len(new_input_embeds) + + new_input_embeds_padded = [] + new_labels_padded = torch.full( + (batch_size, max_len), self.ignore_index, dtype=new_labels[0].dtype, device=new_labels[0].device + ) + attention_mask = torch.zeros((batch_size, max_len), dtype=attention_mask.dtype, device=attention_mask.device) + position_ids = torch.zeros((batch_size, max_len), dtype=position_ids.dtype, device=position_ids.device) + + for i, (cur_new_embed, cur_new_labels) in enumerate(zip(new_input_embeds, new_labels)): + cur_len = cur_new_embed.shape[0] + if getattr(self.config, "tokenizer_padding_side", "right") == "left": + new_input_embeds_padded.append( + torch.cat( + ( + torch.zeros( + (max_len - cur_len, cur_new_embed.shape[1]), + dtype=cur_new_embed.dtype, + device=cur_new_embed.device, + ), + cur_new_embed, + ), + dim=0, + ) + ) + if cur_len > 0: + new_labels_padded[i, -cur_len:] = cur_new_labels + attention_mask[i, -cur_len:] = True + position_ids[i, -cur_len:] = torch.arange(0, cur_len, dtype=position_ids.dtype, device=position_ids.device) + else: + new_input_embeds_padded.append( + torch.cat( + ( + cur_new_embed, + torch.zeros( + (max_len - cur_len, cur_new_embed.shape[1]), + dtype=cur_new_embed.dtype, + device=cur_new_embed.device, + ), + ), + dim=0, + ) + ) + if cur_len > 0: + new_labels_padded[i, :cur_len] = cur_new_labels + attention_mask[i, :cur_len] = True + position_ids[i, :cur_len] = torch.arange(0, cur_len, dtype=position_ids.dtype, device=position_ids.device) + + new_input_embeds = torch.stack(new_input_embeds_padded, dim=0) + + if _labels is None: + new_labels = None + else: + new_labels = new_labels_padded + + if _attention_mask is None: + attention_mask = None + else: + attention_mask = attention_mask.to(dtype=_attention_mask.dtype) + + if _position_ids is None: + position_ids = None + + return None, position_ids, attention_mask, past_key_values, new_input_embeds, new_labels + + def forward( + self, + input_ids: torch.LongTensor = None, + attention_mask: Optional[torch.Tensor] = None, + position_ids: Optional[torch.LongTensor] = None, + past_key_values: Optional[List[torch.FloatTensor]] = None, + inputs_embeds: Optional[torch.FloatTensor] = None, + labels: Optional[torch.LongTensor] = None, + use_cache: Optional[bool] = None, + output_attentions: Optional[bool] = None, + output_hidden_states: Optional[bool] = None, + images: Optional[torch.FloatTensor] = None, + image_sizes: Optional[List[List[int]]] = None, + return_dict: Optional[bool] = None, + cache_position: Optional[torch.LongTensor] = None, + ) -> Union[Tuple, CausalLMOutputWithPast]: + + if inputs_embeds is None: + (input_ids, position_ids, attention_mask, past_key_values, inputs_embeds, labels) = ( + self.prepare_inputs_labels_for_multimodal( + input_ids, position_ids, attention_mask, past_key_values, labels, images, image_sizes + ) + ) + return super().forward( + input_ids=input_ids, + attention_mask=attention_mask, + position_ids=position_ids, + past_key_values=past_key_values, + inputs_embeds=inputs_embeds, + labels=labels, + use_cache=use_cache, + output_attentions=output_attentions, + output_hidden_states=output_hidden_states, + return_dict=return_dict, + ) + + @torch.no_grad() + def generate( + self, + inputs: Optional[torch.Tensor] = None, + images: Optional[torch.Tensor] = None, + image_sizes: Optional[List[List[int]]] = None, + **kwargs, + ) -> Union[GenerateOutput, torch.LongTensor]: + position_ids = kwargs.pop("position_ids", None) + attention_mask = kwargs.pop("attention_mask", None) + if "inputs_embeds" in kwargs: + raise NotImplementedError("`inputs_embeds` is not supported") + + inputs, position_ids, attention_mask, _, inputs_embeds, _ = self.prepare_inputs_labels_for_multimodal( + inputs, position_ids, attention_mask, None, None, images, image_sizes=image_sizes + ) + + return super().generate(position_ids=position_ids, attention_mask=attention_mask, inputs_embeds=inputs_embeds, **kwargs) + + def prepare_inputs_for_generation(self, input_ids, past_key_values=None, inputs_embeds=None, **kwargs): + images = kwargs.pop("images", None) + image_sizes = kwargs.pop("image_sizes", None) + inputs = super().prepare_inputs_for_generation( + input_ids, past_key_values=past_key_values, inputs_embeds=inputs_embeds, **kwargs + ) + if images is not None: + inputs["images"] = images + if image_sizes is not None: + inputs["image_sizes"] = image_sizes + return inputs diff --git a/mineru/model/vlm_sglang_model/__init__.py b/mineru/model/vlm_sglang_model/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..914822cb26364ceddd6fc9d3988c2615a63e05b1 --- /dev/null +++ b/mineru/model/vlm_sglang_model/__init__.py @@ -0,0 +1,21 @@ +from sglang.srt.configs.model_config import multimodal_model_archs +from sglang.srt.models.registry import ModelRegistry + +try: + # sglang==0.4.5.post3 + from sglang.srt.managers.multimodal_processor import ( + PROCESSOR_MAPPING as PROCESSOR_MAPPING, + ) +except ImportError: + # sglang==0.4.4.post1 + from sglang.srt.managers.image_processor import ( + IMAGE_PROCESSOR_MAPPING as PROCESSOR_MAPPING, + ) + +from .. import vlm_hf_model as _ +from .image_processor import Mineru2ImageProcessor +from .model import Mineru2QwenForCausalLM + +ModelRegistry.models[Mineru2QwenForCausalLM.__name__] = Mineru2QwenForCausalLM +PROCESSOR_MAPPING[Mineru2QwenForCausalLM] = Mineru2ImageProcessor +multimodal_model_archs.append(Mineru2QwenForCausalLM.__name__) diff --git a/mineru/model/vlm_sglang_model/engine.py b/mineru/model/vlm_sglang_model/engine.py new file mode 100644 index 0000000000000000000000000000000000000000..0674a0edfa85f19c855ca3ce9559b3452491d9ca --- /dev/null +++ b/mineru/model/vlm_sglang_model/engine.py @@ -0,0 +1,264 @@ +import asyncio +import time +from types import MethodType +from typing import AsyncIterator, Dict, Iterator, List, Optional, Union + +import fastapi +from sglang.srt.entrypoints.engine import Engine as _Engine +from sglang.srt.managers.io_struct import EmbeddingReqInput, GenerateReqInput +from sglang.srt.managers.tokenizer_manager import ( + TokenizerManager, + dataclass_to_string_truncated, + logger, +) +from sglang.srt.sampling.sampling_params import SamplingParams +from sglang.srt.server_args import ServerArgs + +from ...utils.run_async import run_async +from .logit_processor import Mineru2LogitProcessor + + +class BatchEngine(_Engine): + """ + The engine is patched to support batch multi-modal generate, and early image preprocessing. + """ + + def __init__(self, server_args: ServerArgs, **kwargs): + server_args.enable_custom_logit_processor = True + super().__init__(server_args=server_args, **kwargs) + _patch_tokenizer_manager(self.tokenizer_manager) + + def generate( + self, + # The input prompt. It can be a single prompt or a batch of prompts. + prompt: Optional[Union[List[str], str]] = None, + sampling_params: Optional[Union[List[Dict], Dict]] = None, + # The token ids for text; one can either specify text or input_ids. + input_ids: Optional[Union[List[List[int]], List[int]]] = None, + # The image input. It can be a file name, a url, or base64 encoded string. + # See also python/sglang/srt/utils.py:load_image. + image_data: Optional[Union[List[str], str]] = None, + return_logprob: Optional[Union[List[bool], bool]] = False, + logprob_start_len: Optional[Union[List[int], int]] = None, + top_logprobs_num: Optional[Union[List[int], int]] = None, + token_ids_logprob: Optional[Union[List[List[int]], List[int]]] = None, + lora_path: Optional[List[Optional[str]]] = None, + custom_logit_processor: Optional[Union[List[Optional[str]], str]] = None, + return_hidden_states: bool = False, + stream: bool = False, + ) -> Union[Dict, Iterator[Dict]]: + """ + The arguments of this function is the same as `sglang/srt/managers/io_struct.py::GenerateReqInput`. + Please refer to `GenerateReqInput` for the documentation. + """ + modalities_list = [] + + # EDIT + if isinstance(image_data, list): + for _ in range(len(image_data)): + modalities_list.append(["image"]) + elif image_data is not None: + modalities_list.append("image") + + # ADD + if custom_logit_processor is None: + custom_logit_processor = Mineru2LogitProcessor().to_str() + + obj = GenerateReqInput( + text=prompt, + input_ids=input_ids, + sampling_params=sampling_params, + image_data=image_data, + return_logprob=return_logprob, + logprob_start_len=logprob_start_len, + top_logprobs_num=top_logprobs_num, + token_ids_logprob=token_ids_logprob, + lora_path=lora_path, + modalities=modalities_list, + custom_logit_processor=custom_logit_processor, + return_hidden_states=return_hidden_states, + stream=stream, + ) + generator = _generate_request(self.tokenizer_manager, obj, None) + + if stream: + + def generator_wrapper(): + while True: + try: + chunk = run_async(generator.__anext__()) + yield chunk + except StopAsyncIteration: + break + + return generator_wrapper() + else: + ret = run_async(generator.__anext__()) + return ret + + async def async_generate( + self, + # The input prompt. It can be a single prompt or a batch of prompts. + prompt: Optional[Union[List[str], str]] = None, + sampling_params: Optional[Union[List[Dict], Dict]] = None, + # The token ids for text; one can either specify text or input_ids. + input_ids: Optional[Union[List[List[int]], List[int]]] = None, + # The image input. It can be a file name, a url, or base64 encoded string. + # See also python/sglang/srt/utils.py:load_image. + image_data: Optional[Union[List[str], str]] = None, + return_logprob: Optional[Union[List[bool], bool]] = False, + logprob_start_len: Optional[Union[List[int], int]] = None, + top_logprobs_num: Optional[Union[List[int], int]] = None, + token_ids_logprob: Optional[Union[List[List[int]], List[int]]] = None, + lora_path: Optional[List[Optional[str]]] = None, + custom_logit_processor: Optional[Union[List[Optional[str]], str]] = None, + return_hidden_states: bool = False, + stream: bool = False, + ) -> Union[Dict, AsyncIterator[Dict], Iterator[Dict]]: + """ + The arguments of this function is the same as `sglang/srt/managers/io_struct.py::GenerateReqInput`. + Please refer to `GenerateReqInput` for the documentation. + """ + modalities_list = [] + + # EDIT + if isinstance(image_data, list): + for _ in range(len(image_data)): + modalities_list.append(["image"]) + elif image_data is not None: + modalities_list.append("image") + + # ADD + if custom_logit_processor is None: + custom_logit_processor = Mineru2LogitProcessor().to_str() + + obj = GenerateReqInput( + text=prompt, + input_ids=input_ids, + sampling_params=sampling_params, + image_data=image_data, + return_logprob=return_logprob, + logprob_start_len=logprob_start_len, + top_logprobs_num=top_logprobs_num, + token_ids_logprob=token_ids_logprob, + lora_path=lora_path, + modalities=modalities_list, + custom_logit_processor=custom_logit_processor, + return_hidden_states=return_hidden_states, + stream=stream, + ) + generator = _generate_request(self.tokenizer_manager, obj, None) + + if stream is True: + return generator + else: + return await generator.__anext__() + + +def _auto_create_handle_loop(self: TokenizerManager): + """ + patch the original `auto_create_handle_loop()` method to reset `no_create_loop` + when the event loop changes. + """ + try: + curr_handle_loop = asyncio.get_running_loop() + except RuntimeError: + curr_handle_loop = None + + last_handle_loop = getattr(self, "_last_handle_loop", None) + if last_handle_loop != curr_handle_loop: + self.no_create_loop = False + setattr(self, "_last_handle_loop", curr_handle_loop) + return TokenizerManager.auto_create_handle_loop(self) + + +def _patch_tokenizer_manager(self: TokenizerManager): + self.auto_create_handle_loop = MethodType(_auto_create_handle_loop, self) + + +async def _one_request( + self: TokenizerManager, + obj: Union[GenerateReqInput, EmbeddingReqInput], + request: Optional[fastapi.Request], + created_time: Optional[float], +): + tokenized_obj = await self._tokenize_one_request(obj) + self._send_one_request(obj, tokenized_obj, created_time) + async for out in self._wait_one_response(obj, request): + yield out + + +async def _handle_batch_request( + self: TokenizerManager, + obj: Union[GenerateReqInput, EmbeddingReqInput], + request: Optional[fastapi.Request] = None, + created_time: Optional[float] = None, +): + batch_size = obj.batch_size + + generators = [] + rids = [] + + if getattr(obj, "parallel_sample_num", 1) != 1: + raise Exception("parallel_sample_num != 1 is not supported in this patched code.") + + # Send all requests + for i in range(batch_size): + tmp_obj = obj[i] + generators.append(_one_request(self, tmp_obj, request, created_time)) + rids.append(tmp_obj.rid) + + # Wait for all requests + is_stream = hasattr(obj, "stream") and obj.stream + if not is_stream: + outputs = await asyncio.gather(*(gen.__anext__() for gen in generators)) + yield outputs + else: + rid_to_index = {rid: i for i, rid in enumerate(rids)} + task_map = {asyncio.create_task(gen.__anext__()): gen for gen in generators} + while task_map: + done, _ = await asyncio.wait(task_map.keys(), return_when=asyncio.FIRST_COMPLETED) + + for task in done: + gen = task_map.pop(task) + try: + result = task.result() + result["index"] = rid_to_index[result["meta_info"]["id"]] + yield result + new_task = asyncio.create_task(gen.__anext__()) + task_map[new_task] = gen + except StopAsyncIteration: + pass + + +async def _generate_request( + self: TokenizerManager, + obj: Union[GenerateReqInput, EmbeddingReqInput], + request: Optional[fastapi.Request] = None, +): + created_time = time.time() + + self.auto_create_handle_loop() + + if isinstance(obj, EmbeddingReqInput) and self.is_generation: + raise ValueError( + "This model does not appear to be an embedding model by default. " + "Please add `--is-embedding` when launching the server or try another model." + ) + + obj.normalize_batch_and_arguments() + + if self.log_requests: + max_length, skip_names, _ = self.log_request_metadata + logger.info(f"Receive: obj={dataclass_to_string_truncated(obj, max_length, skip_names=skip_names)}") + + async with self.model_update_lock.reader_lock: + is_single = obj.is_single + if is_single: + tokenized_obj = await self._tokenize_one_request(obj) + self._send_one_request(obj, tokenized_obj, created_time) + async for response in self._wait_one_response(obj, request): + yield response + else: + async for response in _handle_batch_request(self, obj, request, created_time): + yield response diff --git a/mineru/model/vlm_sglang_model/image_processor.py b/mineru/model/vlm_sglang_model/image_processor.py new file mode 100644 index 0000000000000000000000000000000000000000..400154f003a707dcdbc5ff3953b532d701809ab7 --- /dev/null +++ b/mineru/model/vlm_sglang_model/image_processor.py @@ -0,0 +1,217 @@ +import ast +import asyncio +import re +from typing import List, Optional, Union + +import numpy as np + +try: + # sglang==0.4.5.post3 + from sglang.srt.managers.multimodal_processors.base_processor import ( + BaseMultimodalProcessor as BaseProcessor, + ) + + get_global_processor = None +except ImportError: + # sglang==0.4.4.post1 + from sglang.srt.managers.image_processors.base_image_processor import ( + BaseImageProcessor as BaseProcessor, + get_global_processor, + ) + +from sglang.srt.mm_utils import divide_to_patches, expand2square, select_best_resolution +from sglang.srt.utils import load_image, logger +from sglang.utils import get_exception_traceback + +from .model import Mineru2QwenForCausalLM + + +# image_best_res is only resized (not padded). +def process_anyres_image(image, processor, grid_pinpoints): + if isinstance(grid_pinpoints, str) and "x" in grid_pinpoints: + patch_size = processor.crop_size["height"] + assert patch_size in [224, 336, 384, 448, 512], "patch_size should be in [224, 336, 384, 448, 512]" + matches = re.findall(r"\((\d+)x(\d+)\)", grid_pinpoints) + range_start = tuple(map(int, matches[0])) + range_end = tuple(map(int, matches[-1])) + grid_pinpoints = [ + (i, j) for i in range(range_start[0], range_end[0] + 1) for j in range(range_start[1], range_end[1] + 1) + ] + grid_pinpoints = [[dim * patch_size for dim in pair] for pair in grid_pinpoints] + + if type(grid_pinpoints) is list: + possible_resolutions = grid_pinpoints + else: + possible_resolutions = ast.literal_eval(grid_pinpoints) + best_resolution = select_best_resolution(image.size, possible_resolutions) + + image_best_res = image.resize(best_resolution) # <<<<<<< Here changed + patches = divide_to_patches(image_best_res, processor.crop_size["height"]) + image_original_resize = image.resize((processor.crop_size["height"], processor.crop_size["height"])) + + image_patches = [image_original_resize] + patches + image_patches = [processor.preprocess(image_patch)["pixel_values"][0] for image_patch in image_patches] + return np.stack(image_patches, axis=0) + + +class Mineru2ImageProcessor(BaseProcessor): + def __init__(self, hf_config, server_args, _processor): + super().__init__(hf_config, server_args, _processor) + + @staticmethod + def _process_single_image_task( + image_data: Union[str, bytes], + image_aspect_ratio: Optional[str] = None, + image_grid_pinpoints: Optional[str] = None, + image_processor=None, + ): + if image_processor is None: + assert get_global_processor is not None + image_processor = get_global_processor().image_processor + + try: + image, image_size = load_image(image_data) + if image_size is not None: + # It is a video with multiple images + image_hash = hash(image_data) + pixel_values = image_processor(image)["pixel_values"] + pixel_values = np.stack(pixel_values, axis=0) + return pixel_values, image_hash, image_size + else: + # It is an image + image_hash = hash(image_data) + if image_aspect_ratio == "pad": + image = expand2square( + image, + tuple(int(x * 255) for x in image_processor.image_mean), + ) + pixel_values = image_processor(image.convert("RGB"))["pixel_values"][0] + elif image_aspect_ratio == "anyres" or (image_aspect_ratio is not None and "anyres_max" in image_aspect_ratio): + pixel_values = process_anyres_image(image, image_processor, image_grid_pinpoints) + else: + pixel_values = image_processor(image)["pixel_values"][0] + return pixel_values, image_hash, image.size + except Exception: + logger.error("Exception in TokenizerManager:\n" + get_exception_traceback()) + + async def _process_single_image(self, image_data: Union[bytes, str], aspect_ratio: str, grid_pinpoints: str): + if hasattr(self, "cpu_executor"): + executor = self.cpu_executor + else: + executor = self.executor + + if get_global_processor is not None: + image_processor = None # save ipc cost + else: + image_processor = self._processor.image_processor + + if executor is not None: + loop = asyncio.get_running_loop() + return await loop.run_in_executor( + executor, + Mineru2ImageProcessor._process_single_image_task, + image_data, + aspect_ratio, + grid_pinpoints, + image_processor, + ) + else: + return self._process_single_image_task( + image_data, + aspect_ratio, + grid_pinpoints, + image_processor, + ) + + # sglang==0.4.4.post1 + async def process_images_async( + self, + image_data: List[Union[str, bytes]], + input_text, + request_obj, + *args, + **kwargs, + ): + if not image_data: + return None + + modalities = request_obj.modalities or ["image"] + aspect_ratio = getattr(self.hf_config, "image_aspect_ratio", "") + + grid_pinpoints = ( + self.hf_config.image_grid_pinpoints + if hasattr(self.hf_config, "image_grid_pinpoints") and "anyres" in aspect_ratio + else None + ) + + if isinstance(image_data, str): + image_data = [image_data] + + if isinstance(image_data, list) and len(image_data) > 0: + if "multi-images" in modalities or "video" in modalities: + # Multiple images + aspect_ratio = "pad" # LLaVA OneVision Handling: more than one image --> interleaved image mode or video mode. We do not use anyres + pixel_values, image_hashes, image_sizes = [], [], [] + res = [] + for img_data in image_data: + res.append(self._process_single_image(img_data, aspect_ratio, grid_pinpoints)) + res = await asyncio.gather(*res) + for pixel_v, image_h, image_s in res: + pixel_values.append(pixel_v) + image_hashes.append(image_h) + image_sizes.append(image_s) + + if isinstance(pixel_values[0], np.ndarray): + pixel_values = np.stack(pixel_values, axis=0) + else: + # A single image + pixel_values, image_hash, image_size = await self._process_single_image( + image_data[0], aspect_ratio, grid_pinpoints + ) + image_hashes = [image_hash] + image_sizes = [image_size] + else: + raise ValueError(f"Invalid image data: {image_data}") + + return { + "pixel_values": pixel_values, + "image_hashes": image_hashes, + "image_sizes": image_sizes, + "modalities": request_obj.modalities or ["image"], + } + + # sglang==0.4.5.post3 + async def process_mm_data_async( + self, + image_data: List[Union[str, bytes]], + input_text, + request_obj, + *args, + **kwargs, + ): + from sglang.srt.managers.schedule_batch import Modality, MultimodalDataItem + + result = await self.process_images_async(image_data, input_text, request_obj, *args, **kwargs) + + if result is None: + return None + + modality = Modality.IMAGE + if isinstance(request_obj.modalities, list): + if request_obj.modalities[0] == "multi-images": + modality = Modality.MULTI_IMAGES + elif request_obj.modalities[0] == "video": + modality = Modality.VIDEO + + return { + "mm_items": [ + MultimodalDataItem( + pixel_values=result["pixel_values"], + image_sizes=result["image_sizes"], + modality=modality, + ) + ], + } + + +ImageProcessorMapping = {Mineru2QwenForCausalLM: Mineru2ImageProcessor} diff --git a/mineru/model/vlm_sglang_model/logit_processor.py b/mineru/model/vlm_sglang_model/logit_processor.py new file mode 100644 index 0000000000000000000000000000000000000000..af29f341ca8a2632eee5bb883f21773d0bdb2ab9 --- /dev/null +++ b/mineru/model/vlm_sglang_model/logit_processor.py @@ -0,0 +1,90 @@ +from typing import List + +from sglang.srt.sampling.custom_logit_processor import CustomLogitProcessor + + +class Mineru2LogitProcessor(CustomLogitProcessor): + """ + Stateless logit processor for Mineru2. + + (base-class: sglang.srt.sampling.custom_logit_processor.CustomLogitProcessor) + + This processor applies token-level constraints to prevent repetition during generation. + It supports two main constraints: + + - no_repeat_ngram_size (int): + Prevents repeating the same n-gram of specified size in the output. + Inspired by Hugging Face's NoRepeatNGramLogitsProcessor. + This implementation is slower due to its lack of specialized optimization. + + - no_repeat_token_count (int): + (Placeholder for future logic) + Intended to prevent repeating the same token multiple times. + Not yet implemented in this version. + """ + + def __init__(self) -> None: + super().__init__() + self._generated_ngrams = {} # Cache of generated n-grams by request ID + self._time = {} # Timestamp of the last update for each request + self._gen_step = 0 # Global generation step counter + + def __call__(self, logits, batch_info: List[dict]): + """ + Applies repetition constraints to the logits before sampling tokens. + + Args: + logits (FloatTensor): A tensor of shape (batch_size, vocab_size) containing raw token logits. + batch_info (List[dict]): A list of metadata dicts for each sample in the batch. Each dict must include: + - "__req__": Request object containing request ID and output_ids. + - "no_repeat_ngram_size": Size of n-gram to avoid repeating. + + Returns: + FloatTensor: The modified logits tensor with banned token logits set to -inf. + """ + from sglang.srt.managers.schedule_batch import Req + + self._gen_step += 1 # Update global generation step + + for idx, info in enumerate(batch_info): + if not isinstance(info, dict) or "__req__" not in info: + continue + + req: Req = info["__req__"] + rid = req.rid + output_ids = req.output_ids + ngram_size = info.get("no_repeat_ngram_size", 0) + + # Skip if there are not enough tokens to form an n-gram + if ngram_size <= 0 or len(output_ids) < ngram_size: + continue + + # Record the current step for cache cleanup tracking + self._time[rid] = self._gen_step + + # Initialize n-gram cache for this request if it doesn't exist + if rid not in self._generated_ngrams: + self._generated_ngrams[rid] = {} + + # Get the n-gram prefix (all but the last token) + prev_ngram = tuple(output_ids[-ngram_size:-1]) + last_token = output_ids[-1] + + # Store this n-gram occurrence + self._generated_ngrams[rid][prev_ngram] = self._generated_ngrams[rid].get(prev_ngram, []) + [last_token] + + # Get the next-token candidates to ban based on current prefix + current_prefix = tuple(output_ids[-ngram_size + 1 :]) + banned_tokens = self._generated_ngrams[rid].get(current_prefix, []) + + # Set the logits of banned tokens to negative infinity + for token in banned_tokens: + logits[idx][token] = -float("inf") + + # Clean up cache for expired requests + expired_rids = [rid for rid, last_used in self._time.items() if last_used < self._gen_step] + for rid in expired_rids: + self._generated_ngrams.pop(rid, None) + self._time.pop(rid, None) + + return logits diff --git a/mineru/model/vlm_sglang_model/model.py b/mineru/model/vlm_sglang_model/model.py new file mode 100644 index 0000000000000000000000000000000000000000..69f0df92375450ee8381312542885789e72b4b84 --- /dev/null +++ b/mineru/model/vlm_sglang_model/model.py @@ -0,0 +1,452 @@ +import math +import re +from typing import Iterable, List, Optional, Tuple + +import numpy as np +import torch +from sglang.srt.layers.quantization.base_config import QuantizationConfig +from sglang.srt.mm_utils import ( + get_anyres_image_grid_shape, # unpad_image, unpad_image_shape +) +from sglang.srt.model_executor.forward_batch_info import ForwardBatch +from sglang.srt.model_loader.weight_utils import default_weight_loader +from sglang.srt.models.qwen2 import Qwen2ForCausalLM +from sglang.srt.utils import add_prefix +from torch import nn +from transformers import ( + CLIPVisionConfig, + CLIPVisionModel, + SiglipVisionConfig, + SiglipVisionModel, +) + +from ..vlm_hf_model.configuration_mineru2 import Mineru2QwenConfig +from ..vlm_hf_model.modeling_mineru2 import build_vision_projector +from ...utils.models_download_utils import auto_download_and_get_model_root_path + + +def flatten_nested_list(nested_list): + if isinstance(nested_list, list): + return [item for sublist in nested_list for item in flatten_nested_list(sublist)] + else: + return [nested_list] + + +def downgrade_modality(modality): + modality_str = str(modality) + if "MULTI_IMAGES" in modality_str: + return "multi-images" + if "IMAGE" in modality_str: + return "image" + if "VIDEO" in modality_str: + return "video" + if "AUDIO" in modality_str: + return "audio" + raise ValueError(f"Unexpected modality: {modality_str}") + + +class Mineru2QwenForCausalLM(nn.Module): + def __init__( + self, + config: Mineru2QwenConfig, + quant_config: Optional[QuantizationConfig] = None, + prefix: str = "", + ) -> None: + super().__init__() + self.config = config + + if getattr(self.config, "projector_hidden_act", None) is None: + self.config.projector_hidden_act = "gelu" + if getattr(self.config, "image_token_index", None) is None: + self.config.image_token_index = 151646 + + # load vision tower + mm_vision_tower = self.config.mm_vision_tower + model_root_path = auto_download_and_get_model_root_path("/", "vlm") + mm_vision_tower = f"{model_root_path}/{mm_vision_tower}" + + if "clip" in mm_vision_tower: + vision_config = CLIPVisionConfig.from_pretrained(mm_vision_tower) + self.vision_tower = CLIPVisionModel(vision_config) # type: ignore + elif "siglip" in mm_vision_tower: + vision_config = SiglipVisionConfig.from_pretrained(mm_vision_tower) + self.vision_tower = SiglipVisionModel(vision_config) # type: ignore + # Siglip needs all feature tokens + self.config.mm_vision_select_feature = "full" + else: + raise ValueError(f"Unexpected mm_vision_tower: {mm_vision_tower}") + + ### EDIT: change projector + # the name `projector` contains `proj` which is often used in attention layers, which can cause bugs in quantization. + self.multi_modal_mlp = build_vision_projector(config) + + self.language_model = Qwen2ForCausalLM( + config, + quant_config=quant_config, + prefix=add_prefix("language_model", prefix), + ) + + if "unpad" in getattr(config, "mm_patch_merge_type", ""): + self.language_model.model.image_newline = nn.Parameter(torch.empty(config.hidden_size)) + + language_model_device = next(self.language_model.parameters()).device + self.vision_tower = self.vision_tower.to(language_model_device) + self.vision_tower.eval() + + self.vision_feature_layer = self.config.mm_vision_select_layer + self.vision_feature_select_strategy = self.config.mm_vision_select_feature + self.image_size = self.vision_tower.config.image_size + self.patch_size = self.vision_tower.config.patch_size + + self.mm_patch_merge_type = getattr(self.config, "mm_patch_merge_type", "flat") + self.image_aspect_ratio = getattr(self.config, "image_aspect_ratio", "square") + self.image_grid_pinpoints = getattr(self.config, "image_grid_pinpoints", None) + + self.image_feature_len = int((self.image_size // self.patch_size) ** 2) + if self.vision_feature_select_strategy in ("patch", "full"): + pass + elif self.vision_feature_select_strategy == "cls_patch": + self.image_feature_len += 1 + else: + raise ValueError(f"Unexpected select feature: {self.select_feature}") + + def pad_input_ids(self, input_ids: List[int], image_inputs): + if hasattr(image_inputs, "mm_items"): # MultimodalInputs + # sglang==0.4.5.post3 + image_sizes = flatten_nested_list([item.image_sizes for item in image_inputs.mm_items]) + pad_values = [item.pad_value for item in image_inputs.mm_items] + else: # ImageInputs + # sglang==0.4.4.post1 + image_sizes = image_inputs.image_sizes + pad_values = image_inputs.pad_values + + # hardcode for spatial_unpad + anyres + # if image_inputs.modalities is not None and ( + # "multi-images" in image_inputs.modalities or "video" in image_inputs.modalities + # ): + # image_aspect_ratio = "pad" + # else: + # image_aspect_ratio = "anyres" + + offset_list = [] + image_inputs.image_pad_len = [] + for image_idx, image_s in enumerate(image_sizes): + if len(image_sizes) > 16: + # 2x2 pooling with stride 2 + new_image_feature_len = math.ceil(self.image_size / self.patch_size / 2) ** 2 + else: + new_image_feature_len = self.image_feature_len # multiimage + + height = width = self.num_patches_per_side + if "anyres" in self.config.image_aspect_ratio: + num_patch_width, num_patch_height = get_anyres_image_grid_shape( + image_s, + self.image_grid_pinpoints, + self.vision_tower.config.image_size, + ) + h = num_patch_height * height + w = num_patch_width * width + + ### EDIT: remove `unpad_image_shape` + # new_h, new_w = unpad_image_shape(h, w, image_s) + new_h, new_w = h, w + + if "anyres_max" in self.config.image_aspect_ratio: + matched_anyres_max_num_patches = re.match(r".*anyres_max_(\d+)", self.config.image_aspect_ratio) + if matched_anyres_max_num_patches: + max_num_patches = int(matched_anyres_max_num_patches.group(1)) + times = math.sqrt(new_h * new_w / (max_num_patches * self.image_feature_len)) + if times > 1.1: + new_h = int(new_h // times) + new_w = int(new_w // times) + new_image_feature_len += new_h * (new_w + 1) + + try: + offset = input_ids.index(self.config.image_token_index) + except ValueError: + offset = 0 + # old_len + pad_len - 1, because we need to remove image_token_id + input_ids = input_ids[:offset] + [pad_values[image_idx]] * new_image_feature_len + input_ids[offset + 1 :] + offset_list.append(offset) + image_inputs.image_pad_len.append(new_image_feature_len) + + image_inputs.image_offsets = offset_list + return input_ids + + def encode_images(self, pixel_values: torch.Tensor) -> torch.Tensor: + pixel_values = pixel_values.to(device=self.vision_tower.device, dtype=self.vision_tower.dtype) + image_outputs = self.vision_tower(pixel_values, output_hidden_states=True) + # NOTE: This is not memory efficient. (output_hidden_states=True) will save all the hidden stated. + + selected_image_feature = image_outputs.hidden_states[self.vision_feature_layer] + if self.vision_feature_select_strategy in ["default", "patch"]: + selected_image_feature = selected_image_feature[:, 1:] + elif self.vision_feature_select_strategy == "full": + selected_image_feature = selected_image_feature + else: + raise ValueError(f"Unexpected select feature strategy: {self.vision_feature_select_strategy}") + + image_features = self.multi_modal_mlp(selected_image_feature) + return image_features + + @torch.no_grad() + def forward( + self, + input_ids: torch.LongTensor, + positions: torch.Tensor, + forward_batch: ForwardBatch, + ) -> torch.Tensor: + if hasattr(forward_batch, "mm_inputs"): + # sglang==0.4.5.post3 + image_inputs = forward_batch.mm_inputs + is_sglang_mm_inputs = True + else: + # sglang==0.4.4.post1 + image_inputs = forward_batch.image_inputs + is_sglang_mm_inputs = False + + if image_inputs is None: + image_inputs = [] + + if forward_batch.forward_mode.is_extend(): + # Clamp input ids. This is because the input_ids for the image tokens are + # filled with the hash values of the image for the prefix matching in the radix attention. + # There values are useless because their embeddings will be replaced by vision embeddings anyway. + input_ids.clamp_(min=0, max=self.config.vocab_size - 1) + + # Embed text inputs + input_embeds = self.language_model.model.embed_tokens(input_ids) + + # Got List[List[str]] extend it to List[str] + # The length of the List should be equal to batch size + modalities_list = [] + max_image_offset = [] + for im in image_inputs: + if im: + if hasattr(im, "mm_items"): + # sglang==0.4.5.post3 + modalities_list.extend([downgrade_modality(item.modality) for item in im.mm_items]) + elif im.modalities is not None: + # sglang==0.4.4.post1 + modalities_list.extend(im.modalities) + if im and im.image_offsets: + max_image_offset.append(np.max(np.array(im.image_offsets) + np.array(im.image_pad_len))) + else: + max_image_offset.append(-1) + + start_positions = positions[forward_batch.extend_start_loc].cpu().numpy() + need_vision = start_positions <= np.array(max_image_offset) + + if need_vision.any(): + bs = forward_batch.batch_size + + if is_sglang_mm_inputs: + # sglang==0.4.5.post3 + pixel_values = flatten_nested_list( + [[item.pixel_values for item in image_inputs[i].mm_items] for i in range(bs) if need_vision[i]] + ) # image_inputs[batch_idx].mm_items[item_idx].pixel_values is Tensor + image_sizes = [ + flatten_nested_list([item.image_sizes for item in image_inputs[i].mm_items]) + for i in range(bs) + if need_vision[i] + ] # image_inputs[batch_idx].mm_items[item_idx].image_sizes should be tuple, but is list of tuple for now. + else: + # sglang==0.4.4.post1 + pixel_values = [image_inputs[i].pixel_values for i in range(bs) if need_vision[i]] + image_sizes = [image_inputs[i].image_sizes for i in range(bs) if need_vision[i]] + + ########## Encode Image ######## + + if pixel_values[0].ndim == 4: + # llava-hd: BS, num_patch, C=3, H=336, W=336, num_patch obtained from process_images + np.concatenate(pixel_values, axis=0) + # ndim=4 + concat_images = torch.tensor( + np.concatenate(pixel_values, axis=0), + device=self.vision_tower.device, + ) + image_features = self.encode_images(concat_images) + split_sizes = [image.shape[0] for image in pixel_values] + image_features = torch.split(image_features, split_sizes, dim=0) + # hd image_features: BS, num_patch, 576, 4096 + else: + # normal pixel: BS, C=3, H=336, W=336 + pixel_values = torch.tensor(np.array(pixel_values), device=self.vision_tower.device) + image_features = self.encode_images(pixel_values) + # image_features: BS, 576, 4096 + + if self.mm_patch_merge_type.startswith("spatial"): + new_image_features = [] + height = width = self.num_patches_per_side + for image_idx, image_feature in enumerate(image_features): + if modalities_list[image_idx] == "image": + image_aspect_ratio = self.config.image_aspect_ratio # single image + elif modalities_list[image_idx] == "multi-images" or modalities_list[image_idx] == "video": + image_aspect_ratio = "pad" # multi image + # image_aspect_ratio = ( + # "anyres" if len(image_sizes[image_idx]) == 1 else "pad" + # ) + if ( + image_feature.shape[0] > 1 + and "anyres" in image_aspect_ratio + and modalities_list[image_idx] == "image" + ): + base_image_feature = image_feature[0] + image_feature = image_feature[1:] + assert height * width == base_image_feature.shape[0] + + if "anyres_max" in image_aspect_ratio: + matched_anyres_max_num_patches = re.match(r".*anyres_max_(\d+)", image_aspect_ratio) + if matched_anyres_max_num_patches: + max_num_patches = int(matched_anyres_max_num_patches.group(1)) + + if image_aspect_ratio == "anyres" or "anyres_max" in image_aspect_ratio: + vision_tower_image_size = self.image_size + try: + num_patch_width, num_patch_height = get_anyres_image_grid_shape( + image_sizes[image_idx][0], + self.config.image_grid_pinpoints, + vision_tower_image_size, + ) + except Exception as e: + print(f"Error: {e}") + num_patch_width, num_patch_height = 2, 2 + image_feature = image_feature.view(num_patch_height, num_patch_width, height, width, -1) + else: + image_feature = image_feature.view(2, 2, height, width, -1) + + if "unpad" in self.mm_patch_merge_type: + unit = image_feature.shape[2] + image_feature = image_feature.permute(4, 0, 2, 1, 3).contiguous() + image_feature = image_feature.flatten(1, 2).flatten(2, 3) + + ### EDIT: remove `unpad_image` + # image_feature = unpad_image(image_feature, image_sizes[image_idx][0]) + + if "anyres_max" in image_aspect_ratio and matched_anyres_max_num_patches: + c, h, w = image_feature.shape + times = math.sqrt(h * w / (max_num_patches * unit**2)) + if times > 1.1: + image_feature = image_feature[None] + image_feature = nn.functional.interpolate( + image_feature, + [int(h // times), int(w // times)], + mode="bilinear", + )[0] + image_feature = torch.cat( + ( + image_feature, + self.language_model.model.image_newline[:, None, None].expand( + *image_feature.shape[:-1], 1 + ), + ), + dim=-1, + ) + image_feature = image_feature.flatten(1, 2).transpose(0, 1) + else: + image_feature = image_feature.permute(0, 2, 1, 3, 4).contiguous() + image_feature = image_feature.flatten(0, 3) + image_feature = torch.cat((base_image_feature, image_feature), dim=0) + image_feature = image_feature.unsqueeze(0) + else: + if modalities_list[image_idx] == "video": # video + # 2x2 pooling + num_of_frames = image_feature.shape[0] + image_feature = image_feature.view(num_of_frames, height, width, -1) + image_feature = image_feature.permute(0, 3, 1, 2).contiguous() # N, C, H, W + height, weight = image_feature.shape[2:] + scaled_shape = [ + math.ceil(height / 2), + math.ceil(weight / 2), + ] + image_feature = nn.functional.interpolate(image_feature, size=scaled_shape, mode="bilinear") + image_feature = image_feature.flatten(2).transpose(1, 2).contiguous() # N, C, H*W + if "unpad" in self.mm_patch_merge_type: + image_feature = torch.cat( + ( + image_feature, + # Expand to (bs, 1, hidden_dim) and concat at the end of the image tokens + self.language_model.model.image_newline[None, None].expand( + image_feature.shape[0], + 1, + image_feature.shape[-1], + ), + ), + dim=1, + ) + + new_image_features.append(image_feature) + image_features = new_image_features + + # Fill in the placeholder for the image + extend_start_loc_cpu = forward_batch.extend_start_loc.cpu().numpy() + extend_seq_lens = forward_batch.extend_seq_lens.cpu().numpy() + prefix_lens_cpu = forward_batch.extend_prefix_lens_cpu + pt = 0 + for i in range(bs): + if not need_vision[i]: + continue + + start_idx = extend_start_loc_cpu[i] + seq_len = extend_seq_lens[i] + prefix_len = prefix_lens_cpu[i] + + # Multiple images + for image_idx, image_offset in enumerate(image_inputs[i].image_offsets): + if image_offset + image_inputs[i].image_pad_len[image_idx] <= prefix_len: + continue + if image_offset >= prefix_len + seq_len: + break + + tmp_image_feature = image_features[pt][image_idx] + pad_len = tmp_image_feature.shape[0] + + input_offset = image_offset - prefix_len + left_idx = start_idx + input_offset + right_idx = left_idx + pad_len + assert right_idx > start_idx + if input_offset < 0: + left_idx = start_idx + tmp_image_feature = tmp_image_feature[-input_offset:] + if right_idx > start_idx + seq_len: + tmp_image_feature = tmp_image_feature[: start_idx + seq_len - right_idx] + right_idx = start_idx + seq_len + try: + input_embeds[left_idx:right_idx] = tmp_image_feature + except RuntimeError as e: + print(f"RuntimeError in image encoding: {e}") + print(f"{input_embeds.shape=}, {tmp_image_feature.shape=}") + print(f"{start_idx=}, {image_offset=}, {prefix_len=}, {pad_len=}") + pt += 1 + + return self.language_model(input_ids, positions, forward_batch, input_embeds=input_embeds) + elif forward_batch.forward_mode.is_decode(): + return self.language_model(input_ids, positions, forward_batch) + else: + raise ValueError(f"Unexpected forward mode: {forward_batch.forward_mode}") + + def load_weights(self, weights: Iterable[Tuple[str, torch.Tensor]]): + projector_weights = { + "model.mm_projector": "multi_modal_mlp", + "model.vision_tower.vision_tower": "vision_tower", + # Update the vision tower weights if we find them in the checkpoint (it may be finetuned). + "model.image_newline": "language_model.model.image_newline", + } + params_dict = dict(self.named_parameters()) + for name, loaded_weight in weights: + if "projector" in name or "vision_tower" in name or "image_newline" in name: + for weight_name, param_name in projector_weights.items(): + if weight_name in name: + name = name.replace(weight_name, param_name) + param = params_dict[name] + weight_loader = getattr(param, "weight_loader", default_weight_loader) + weight_loader(param, loaded_weight) + else: + self.language_model.load_weights([(name, loaded_weight)]) + + @property + def num_patches_per_side(self): + return self.image_size // self.patch_size + + +EntryClass = [Mineru2QwenForCausalLM] diff --git a/mineru/model/vlm_sglang_model/server.py b/mineru/model/vlm_sglang_model/server.py new file mode 100644 index 0000000000000000000000000000000000000000..7bbd897051d454dc7b9a27d1ffb6a8a9ac9f8d03 --- /dev/null +++ b/mineru/model/vlm_sglang_model/server.py @@ -0,0 +1,58 @@ +import os +import sys + +from fastapi import Request +from sglang.srt.entrypoints.http_server import app, generate_request, launch_server +from sglang.srt.managers.io_struct import GenerateReqInput +from sglang.srt.server_args import prepare_server_args +from sglang.srt.utils import kill_process_tree + +from mineru.utils.models_download_utils import auto_download_and_get_model_root_path +from .logit_processor import Mineru2LogitProcessor + +_custom_logit_processor_str = Mineru2LogitProcessor().to_str() + +# remote the existing /generate route +for route in app.routes[:]: + if hasattr(route, "path") and getattr(route, "path") == "/generate": + app.routes.remove(route) + + +# add the custom /generate route +@app.api_route("/generate", methods=["POST", "PUT"]) +async def custom_generate_request(obj: GenerateReqInput, request: Request): + if obj.custom_logit_processor is None: + obj.custom_logit_processor = _custom_logit_processor_str + return await generate_request(obj, request) + + +def main(): + # 检查命令行参数中是否包含--model-path + args = sys.argv[1:] + has_model_path_arg = False + + for i, arg in enumerate(args): + if arg == "--model-path" or arg.startswith("--model-path="): + has_model_path_arg = True + break + + # 如果没有--model-path参数,在参数列表中添加它 + if not has_model_path_arg: + default_path = auto_download_and_get_model_root_path("/", "vlm") + args.extend(["--model-path", default_path]) + + server_args = prepare_server_args(args) + + if server_args.chat_template is None: + server_args.chat_template = "chatml" + + server_args.enable_custom_logit_processor = True + + try: + launch_server(server_args) + finally: + kill_process_tree(os.getpid(), include_parent=False) + + +if __name__ == "__main__": + main() diff --git a/magic_pdf/resources/fasttext-langdetect/lid.176.ftz b/mineru/resources/fasttext-langdetect/lid.176.ftz similarity index 100% rename from magic_pdf/resources/fasttext-langdetect/lid.176.ftz rename to mineru/resources/fasttext-langdetect/lid.176.ftz diff --git a/mineru/utils/__init__.py b/mineru/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1e17167ceda21a510d4486bf1711c9a72bf414db --- /dev/null +++ b/mineru/utils/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Opendatalab. All rights reserved. diff --git a/magic_pdf/pre_proc/ocr_detect_all_bboxes.py b/mineru/utils/block_pre_proc.py similarity index 73% rename from magic_pdf/pre_proc/ocr_detect_all_bboxes.py rename to mineru/utils/block_pre_proc.py index b9fd5b029f1647e59e3c5f603b936201a726ddc8..bbc8bca060d6177fdf9782d1d317519b87b632e7 100644 --- a/magic_pdf/pre_proc/ocr_detect_all_bboxes.py +++ b/mineru/utils/block_pre_proc.py @@ -1,63 +1,37 @@ -from magic_pdf.config.ocr_content_type import BlockType -from magic_pdf.libs.boxbase import ( +# Copyright (c) Opendatalab. All rights reserved. +from mineru.utils.boxbase import ( calculate_iou, calculate_overlap_area_in_bbox1_area_ratio, calculate_vertical_projection_overlap_ratio, get_minbox_if_overlap_by_ratio ) -from magic_pdf.pre_proc.remove_bbox_overlap import remove_overlap_between_bbox_for_block +from mineru.utils.enum_class import BlockType -def add_bboxes(blocks, block_type, bboxes): - for block in blocks: - x0, y0, x1, y1 = block['bbox'] - if block_type in [ - BlockType.ImageBody, - BlockType.ImageCaption, - BlockType.ImageFootnote, - BlockType.TableBody, - BlockType.TableCaption, - BlockType.TableFootnote, - ]: - bboxes.append( - [ - x0, - y0, - x1, - y1, - None, - None, - None, - block_type, - None, - None, - None, - None, - block['score'], - block['group_id'], - ] - ) +def process_groups(groups, body_key, caption_key, footnote_key): + body_blocks = [] + caption_blocks = [] + footnote_blocks = [] + maybe_text_image_blocks = [] + for i, group in enumerate(groups): + if body_key == 'image_body' and len(group[caption_key]) == 0 and len(group[footnote_key]) == 0: + # 如果没有caption和footnote,则不需要将group_id添加到image_body中 + group[body_key]['group_id'] = i + maybe_text_image_blocks.append(group[body_key]) + continue else: - bboxes.append( - [ - x0, - y0, - x1, - y1, - None, - None, - None, - block_type, - None, - None, - None, - None, - block['score'], - ] - ) - - -def ocr_prepare_bboxes_for_layout_split_v2( + group[body_key]['group_id'] = i + body_blocks.append(group[body_key]) + for caption_block in group[caption_key]: + caption_block['group_id'] = i + caption_blocks.append(caption_block) + for footnote_block in group[footnote_key]: + footnote_block['group_id'] = i + footnote_blocks.append(footnote_block) + return body_blocks, caption_blocks, footnote_blocks, maybe_text_image_blocks + + +def prepare_block_bboxes( img_body_blocks, img_caption_blocks, img_footnote_blocks, @@ -73,15 +47,15 @@ def ocr_prepare_bboxes_for_layout_split_v2( ): all_bboxes = [] - add_bboxes(img_body_blocks, BlockType.ImageBody, all_bboxes) - add_bboxes(img_caption_blocks, BlockType.ImageCaption, all_bboxes) - add_bboxes(img_footnote_blocks, BlockType.ImageFootnote, all_bboxes) - add_bboxes(table_body_blocks, BlockType.TableBody, all_bboxes) - add_bboxes(table_caption_blocks, BlockType.TableCaption, all_bboxes) - add_bboxes(table_footnote_blocks, BlockType.TableFootnote, all_bboxes) - add_bboxes(text_blocks, BlockType.Text, all_bboxes) - add_bboxes(title_blocks, BlockType.Title, all_bboxes) - add_bboxes(interline_equation_blocks, BlockType.InterlineEquation, all_bboxes) + add_bboxes(img_body_blocks, BlockType.IMAGE_BODY, all_bboxes) + add_bboxes(img_caption_blocks, BlockType.IMAGE_CAPTION, all_bboxes) + add_bboxes(img_footnote_blocks, BlockType.IMAGE_CAPTION, all_bboxes) + add_bboxes(table_body_blocks, BlockType.TABLE_BODY, all_bboxes) + add_bboxes(table_caption_blocks, BlockType.TABLE_CAPTION, all_bboxes) + add_bboxes(table_footnote_blocks, BlockType.TABLE_FOOTNOTE, all_bboxes) + add_bboxes(text_blocks, BlockType.TEXT, all_bboxes) + add_bboxes(title_blocks, BlockType.TITLE, all_bboxes) + add_bboxes(interline_equation_blocks, BlockType.INTERLINE_EQUATION, all_bboxes) """block嵌套问题解决""" """文本框与标题框重叠,优先信任文本框""" @@ -97,7 +71,7 @@ def ocr_prepare_bboxes_for_layout_split_v2( """discarded_blocks""" all_discarded_blocks = [] - add_bboxes(discarded_blocks, BlockType.Discarded, all_discarded_blocks) + add_bboxes(discarded_blocks, BlockType.DISCARDED, all_discarded_blocks) """footnote识别:宽度超过1/3页面宽度的,高度超过10的,处于页面下半30%区域的""" footnote_blocks = [] @@ -122,63 +96,31 @@ def ocr_prepare_bboxes_for_layout_split_v2( return all_bboxes, all_discarded_blocks, footnote_blocks -def find_blocks_under_footnote(all_bboxes, footnote_blocks): - need_remove_blocks = [] - for block in all_bboxes: - block_x0, block_y0, block_x1, block_y1 = block[:4] - for footnote_bbox in footnote_blocks: - footnote_x0, footnote_y0, footnote_x1, footnote_y1 = footnote_bbox - # 如果footnote的纵向投影覆盖了block的纵向投影的80%且block的y0大于等于footnote的y1 - if ( - block_y0 >= footnote_y1 - and calculate_vertical_projection_overlap_ratio( - (block_x0, block_y0, block_x1, block_y1), footnote_bbox - ) - >= 0.8 - ): - if block not in need_remove_blocks: - need_remove_blocks.append(block) - break - return need_remove_blocks - - -def fix_interline_equation_overlap_text_blocks_with_hi_iou(all_bboxes): - # 先提取所有text和interline block - text_blocks = [] - for block in all_bboxes: - if block[7] == BlockType.Text: - text_blocks.append(block) - interline_equation_blocks = [] - for block in all_bboxes: - if block[7] == BlockType.InterlineEquation: - interline_equation_blocks.append(block) - - need_remove = [] - - for interline_equation_block in interline_equation_blocks: - for text_block in text_blocks: - interline_equation_block_bbox = interline_equation_block[:4] - text_block_bbox = text_block[:4] - if calculate_iou(interline_equation_block_bbox, text_block_bbox) > 0.8: - if text_block not in need_remove: - need_remove.append(text_block) - - if len(need_remove) > 0: - for block in need_remove: - all_bboxes.remove(block) - - return all_bboxes +def add_bboxes(blocks, block_type, bboxes): + for block in blocks: + x0, y0, x1, y1 = block['bbox'] + if block_type in [ + BlockType.IMAGE_BODY, + BlockType.IMAGE_CAPTION, + BlockType.IMAGE_FOOTNOTE, + BlockType.TABLE_BODY, + BlockType.TABLE_CAPTION, + BlockType.TABLE_FOOTNOTE, + ]: + bboxes.append([x0, y0, x1, y1, None, None, None, block_type, None, None, None, None, block['score'], block['group_id']]) + else: + bboxes.append([x0, y0, x1, y1, None, None, None, block_type, None, None, None, None, block['score']]) def fix_text_overlap_title_blocks(all_bboxes): # 先提取所有text和title block text_blocks = [] for block in all_bboxes: - if block[7] == BlockType.Text: + if block[7] == BlockType.TEXT: text_blocks.append(block) title_blocks = [] for block in all_bboxes: - if block[7] == BlockType.Title: + if block[7] == BlockType.TITLE: title_blocks.append(block) need_remove = [] @@ -219,6 +161,54 @@ def remove_need_drop_blocks(all_bboxes, discarded_blocks): return all_bboxes +def fix_interline_equation_overlap_text_blocks_with_hi_iou(all_bboxes): + # 先提取所有text和interline block + text_blocks = [] + for block in all_bboxes: + if block[7] == BlockType.TEXT: + text_blocks.append(block) + interline_equation_blocks = [] + for block in all_bboxes: + if block[7] == BlockType.INTERLINE_EQUATION: + interline_equation_blocks.append(block) + + need_remove = [] + + for interline_equation_block in interline_equation_blocks: + for text_block in text_blocks: + interline_equation_block_bbox = interline_equation_block[:4] + text_block_bbox = text_block[:4] + if calculate_iou(interline_equation_block_bbox, text_block_bbox) > 0.8: + if text_block not in need_remove: + need_remove.append(text_block) + + if len(need_remove) > 0: + for block in need_remove: + all_bboxes.remove(block) + + return all_bboxes + + +def find_blocks_under_footnote(all_bboxes, footnote_blocks): + need_remove_blocks = [] + for block in all_bboxes: + block_x0, block_y0, block_x1, block_y1 = block[:4] + for footnote_bbox in footnote_blocks: + footnote_x0, footnote_y0, footnote_x1, footnote_y1 = footnote_bbox + # 如果footnote的纵向投影覆盖了block的纵向投影的80%且block的y0大于等于footnote的y1 + if ( + block_y0 >= footnote_y1 + and calculate_vertical_projection_overlap_ratio( + (block_x0, block_y0, block_x1, block_y1), footnote_bbox + ) + >= 0.8 + ): + if block not in need_remove_blocks: + need_remove_blocks.append(block) + break + return need_remove_blocks + + def remove_overlaps_min_blocks(all_bboxes): # 重叠block,小的不能直接删除,需要和大的那个合并成一个更大的。 # 删除重叠blocks中较小的那些 @@ -254,4 +244,4 @@ def remove_overlaps_min_blocks(all_bboxes): for block in need_remove: all_bboxes.remove(block) - return all_bboxes + return all_bboxes \ No newline at end of file diff --git a/mineru/utils/block_sort.py b/mineru/utils/block_sort.py new file mode 100644 index 0000000000000000000000000000000000000000..aef05edea696013af454fd5f1bde1a66ab686252 --- /dev/null +++ b/mineru/utils/block_sort.py @@ -0,0 +1,339 @@ +# Copyright (c) Opendatalab. All rights reserved. +import copy +import os +import statistics +import warnings +from typing import List +import torch +from loguru import logger + +from mineru.utils.config_reader import get_device +from mineru.utils.enum_class import BlockType, ModelPath +from mineru.utils.models_download_utils import auto_download_and_get_model_root_path + + +def sort_blocks_by_bbox(blocks, page_w, page_h, footnote_blocks): + + """获取所有line并计算正文line的高度""" + line_height = get_line_height(blocks) + + """获取所有line并对line排序""" + sorted_bboxes = sort_lines_by_model(blocks, page_w, page_h, line_height, footnote_blocks) + + """根据line的中位数算block的序列关系""" + blocks = cal_block_index(blocks, sorted_bboxes) + + """将image和table的block还原回group形式参与后续流程""" + blocks = revert_group_blocks(blocks) + + """重排block""" + sorted_blocks = sorted(blocks, key=lambda b: b['index']) + + """block内重排(img和table的block内多个caption或footnote的排序)""" + for block in sorted_blocks: + if block['type'] in [BlockType.IMAGE, BlockType.TABLE]: + block['blocks'] = sorted(block['blocks'], key=lambda b: b['index']) + + return sorted_blocks + + +def get_line_height(blocks): + page_line_height_list = [] + for block in blocks: + if block['type'] in [ + BlockType.TEXT, BlockType.TITLE, + BlockType.IMAGE_CAPTION, BlockType.IMAGE_FOOTNOTE, + BlockType.TABLE_CAPTION, BlockType.TABLE_FOOTNOTE + ]: + for line in block['lines']: + bbox = line['bbox'] + page_line_height_list.append(int(bbox[3] - bbox[1])) + if len(page_line_height_list) > 0: + return statistics.median(page_line_height_list) + else: + return 10 + + +def sort_lines_by_model(fix_blocks, page_w, page_h, line_height, footnote_blocks): + page_line_list = [] + + def add_lines_to_block(b): + line_bboxes = insert_lines_into_block(b['bbox'], line_height, page_w, page_h) + b['lines'] = [] + for line_bbox in line_bboxes: + b['lines'].append({'bbox': line_bbox, 'spans': []}) + page_line_list.extend(line_bboxes) + + for block in fix_blocks: + if block['type'] in [ + BlockType.TEXT, BlockType.TITLE, + BlockType.IMAGE_CAPTION, BlockType.IMAGE_FOOTNOTE, + BlockType.TABLE_CAPTION, BlockType.TABLE_FOOTNOTE + ]: + if len(block['lines']) == 0: + add_lines_to_block(block) + elif block['type'] in [BlockType.TITLE] and len(block['lines']) == 1 and (block['bbox'][3] - block['bbox'][1]) > line_height * 2: + block['real_lines'] = copy.deepcopy(block['lines']) + add_lines_to_block(block) + else: + for line in block['lines']: + bbox = line['bbox'] + page_line_list.append(bbox) + elif block['type'] in [BlockType.IMAGE_BODY, BlockType.TABLE_BODY, BlockType.INTERLINE_EQUATION]: + block['real_lines'] = copy.deepcopy(block['lines']) + add_lines_to_block(block) + + for block in footnote_blocks: + footnote_block = {'bbox': block[:4]} + add_lines_to_block(footnote_block) + + if len(page_line_list) > 200: # layoutreader最高支持512line + return None + + # 使用layoutreader排序 + x_scale = 1000.0 / page_w + y_scale = 1000.0 / page_h + boxes = [] + # logger.info(f"Scale: {x_scale}, {y_scale}, Boxes len: {len(page_line_list)}") + for left, top, right, bottom in page_line_list: + if left < 0: + logger.warning( + f'left < 0, left: {left}, right: {right}, top: {top}, bottom: {bottom}, page_w: {page_w}, page_h: {page_h}' + ) # noqa: E501 + left = 0 + if right > page_w: + logger.warning( + f'right > page_w, left: {left}, right: {right}, top: {top}, bottom: {bottom}, page_w: {page_w}, page_h: {page_h}' + ) # noqa: E501 + right = page_w + if top < 0: + logger.warning( + f'top < 0, left: {left}, right: {right}, top: {top}, bottom: {bottom}, page_w: {page_w}, page_h: {page_h}' + ) # noqa: E501 + top = 0 + if bottom > page_h: + logger.warning( + f'bottom > page_h, left: {left}, right: {right}, top: {top}, bottom: {bottom}, page_w: {page_w}, page_h: {page_h}' + ) # noqa: E501 + bottom = page_h + + left = round(left * x_scale) + top = round(top * y_scale) + right = round(right * x_scale) + bottom = round(bottom * y_scale) + assert ( + 1000 >= right >= left >= 0 and 1000 >= bottom >= top >= 0 + ), f'Invalid box. right: {right}, left: {left}, bottom: {bottom}, top: {top}' # noqa: E126, E121 + boxes.append([left, top, right, bottom]) + model_manager = ModelSingleton() + model = model_manager.get_model('layoutreader') + with torch.no_grad(): + orders = do_predict(boxes, model) + sorted_bboxes = [page_line_list[i] for i in orders] + + return sorted_bboxes + + +def insert_lines_into_block(block_bbox, line_height, page_w, page_h): + # block_bbox是一个元组(x0, y0, x1, y1),其中(x0, y0)是左下角坐标,(x1, y1)是右上角坐标 + x0, y0, x1, y1 = block_bbox + + block_height = y1 - y0 + block_weight = x1 - x0 + + # 如果block高度小于n行正文,则直接返回block的bbox + if line_height * 2 < block_height: + if ( + block_height > page_h * 0.25 and page_w * 0.5 > block_weight > page_w * 0.25 + ): # 可能是双列结构,可以切细点 + lines = int(block_height / line_height) + else: + # 如果block的宽度超过0.4页面宽度,则将block分成3行(是一种复杂布局,图不能切的太细) + if block_weight > page_w * 0.4: + lines = 3 + elif block_weight > page_w * 0.25: # (可能是三列结构,也切细点) + lines = int(block_height / line_height) + else: # 判断长宽比 + if block_height / block_weight > 1.2: # 细长的不分 + return [[x0, y0, x1, y1]] + else: # 不细长的还是分成两行 + lines = 2 + + line_height = (y1 - y0) / lines + + # 确定从哪个y位置开始绘制线条 + current_y = y0 + + # 用于存储线条的位置信息[(x0, y), ...] + lines_positions = [] + + for i in range(lines): + lines_positions.append([x0, current_y, x1, current_y + line_height]) + current_y += line_height + return lines_positions + + else: + return [[x0, y0, x1, y1]] + + +def model_init(model_name: str): + from transformers import LayoutLMv3ForTokenClassification + device_name = get_device() + bf_16_support = False + if device_name.startswith("cuda"): + bf_16_support = torch.cuda.is_bf16_supported() + elif device_name.startswith("mps"): + bf_16_support = True + + device = torch.device(device_name) + if model_name == 'layoutreader': + # 检测modelscope的缓存目录是否存在 + layoutreader_model_dir = os.path.join(auto_download_and_get_model_root_path(ModelPath.layout_reader), ModelPath.layout_reader) + if os.path.exists(layoutreader_model_dir): + model = LayoutLMv3ForTokenClassification.from_pretrained( + layoutreader_model_dir + ) + else: + logger.warning( + 'local layoutreader model not exists, use online model from huggingface' + ) + model = LayoutLMv3ForTokenClassification.from_pretrained( + 'hantian/layoutreader' + ) + if bf_16_support: + model.to(device).eval().bfloat16() + else: + model.to(device).eval() + else: + logger.error('model name not allow') + exit(1) + return model + + +class ModelSingleton: + _instance = None + _models = {} + + def __new__(cls, *args, **kwargs): + if cls._instance is None: + cls._instance = super().__new__(cls) + return cls._instance + + def get_model(self, model_name: str): + if model_name not in self._models: + self._models[model_name] = model_init(model_name=model_name) + return self._models[model_name] + + +def do_predict(boxes: List[List[int]], model) -> List[int]: + from mineru.model.reading_order.layout_reader import ( + boxes2inputs, parse_logits, prepare_inputs) + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=FutureWarning, module="transformers") + + inputs = boxes2inputs(boxes) + inputs = prepare_inputs(inputs, model) + logits = model(**inputs).logits.cpu().squeeze(0) + return parse_logits(logits, len(boxes)) + + +def cal_block_index(fix_blocks, sorted_bboxes): + + if sorted_bboxes is not None: + # 使用layoutreader排序 + for block in fix_blocks: + line_index_list = [] + if len(block['lines']) == 0: + block['index'] = sorted_bboxes.index(block['bbox']) + else: + for line in block['lines']: + line['index'] = sorted_bboxes.index(line['bbox']) + line_index_list.append(line['index']) + median_value = statistics.median(line_index_list) + block['index'] = median_value + + # 删除图表body block中的虚拟line信息, 并用real_lines信息回填 + if block['type'] in [BlockType.IMAGE_BODY, BlockType.TABLE_BODY, BlockType.TITLE, BlockType.INTERLINE_EQUATION]: + if 'real_lines' in block: + block['virtual_lines'] = copy.deepcopy(block['lines']) + block['lines'] = copy.deepcopy(block['real_lines']) + del block['real_lines'] + else: + # 使用xycut排序 + block_bboxes = [] + for block in fix_blocks: + # 如果block['bbox']任意值小于0,将其置为0 + block['bbox'] = [max(0, x) for x in block['bbox']] + block_bboxes.append(block['bbox']) + + # 删除图表body block中的虚拟line信息, 并用real_lines信息回填 + if block['type'] in [BlockType.IMAGE_BODY, BlockType.TABLE_BODY, BlockType.TITLE, BlockType.INTERLINE_EQUATION]: + if 'real_lines' in block: + block['virtual_lines'] = copy.deepcopy(block['lines']) + block['lines'] = copy.deepcopy(block['real_lines']) + del block['real_lines'] + + import numpy as np + from mineru.model.reading_order.xycut import recursive_xy_cut + + random_boxes = np.array(block_bboxes) + np.random.shuffle(random_boxes) + res = [] + recursive_xy_cut(np.asarray(random_boxes).astype(int), np.arange(len(block_bboxes)), res) + assert len(res) == len(block_bboxes) + sorted_boxes = random_boxes[np.array(res)].tolist() + + for i, block in enumerate(fix_blocks): + block['index'] = sorted_boxes.index(block['bbox']) + + # 生成line index + sorted_blocks = sorted(fix_blocks, key=lambda b: b['index']) + line_inedx = 1 + for block in sorted_blocks: + for line in block['lines']: + line['index'] = line_inedx + line_inedx += 1 + + return fix_blocks + + +def revert_group_blocks(blocks): + image_groups = {} + table_groups = {} + new_blocks = [] + for block in blocks: + if block['type'] in [BlockType.IMAGE_BODY, BlockType.IMAGE_CAPTION, BlockType.IMAGE_FOOTNOTE]: + group_id = block['group_id'] + if group_id not in image_groups: + image_groups[group_id] = [] + image_groups[group_id].append(block) + elif block['type'] in [BlockType.TABLE_BODY, BlockType.TABLE_CAPTION, BlockType.TABLE_FOOTNOTE]: + group_id = block['group_id'] + if group_id not in table_groups: + table_groups[group_id] = [] + table_groups[group_id].append(block) + else: + new_blocks.append(block) + + for group_id, blocks in image_groups.items(): + new_blocks.append(process_block_list(blocks, BlockType.IMAGE_BODY, BlockType.IMAGE)) + + for group_id, blocks in table_groups.items(): + new_blocks.append(process_block_list(blocks, BlockType.TABLE_BODY, BlockType.TABLE)) + + return new_blocks + + +def process_block_list(blocks, body_type, block_type): + indices = [block['index'] for block in blocks] + median_index = statistics.median(indices) + + body_bbox = next((block['bbox'] for block in blocks if block.get('type') == body_type), []) + + return { + 'type': block_type, + 'bbox': body_bbox, + 'blocks': blocks, + 'index': median_index, + } \ No newline at end of file diff --git a/mineru/utils/boxbase.py b/mineru/utils/boxbase.py new file mode 100644 index 0000000000000000000000000000000000000000..e249ecadd1d3c7b92c8bf13e946211e70abc921d --- /dev/null +++ b/mineru/utils/boxbase.py @@ -0,0 +1,203 @@ +import math + + +def is_in(box1, box2) -> bool: + """box1是否完全在box2里面.""" + x0_1, y0_1, x1_1, y1_1 = box1 + x0_2, y0_2, x1_2, y1_2 = box2 + + return ( + x0_1 >= x0_2 # box1的左边界不在box2的左边外 + and y0_1 >= y0_2 # box1的上边界不在box2的上边外 + and x1_1 <= x1_2 # box1的右边界不在box2的右边外 + and y1_1 <= y1_2 + ) # box1的下边界不在box2的下边外 + + +def bbox_relative_pos(bbox1, bbox2): + """判断两个矩形框的相对位置关系. + + Args: + bbox1: 一个四元组,表示第一个矩形框的左上角和右下角的坐标,格式为(x1, y1, x1b, y1b) + bbox2: 一个四元组,表示第二个矩形框的左上角和右下角的坐标,格式为(x2, y2, x2b, y2b) + + Returns: + 一个四元组,表示矩形框1相对于矩形框2的位置关系,格式为(left, right, bottom, top) + 其中,left表示矩形框1是否在矩形框2的左侧,right表示矩形框1是否在矩形框2的右侧, + bottom表示矩形框1是否在矩形框2的下方,top表示矩形框1是否在矩形框2的上方 + """ + x1, y1, x1b, y1b = bbox1 + x2, y2, x2b, y2b = bbox2 + + left = x2b < x1 + right = x1b < x2 + bottom = y2b < y1 + top = y1b < y2 + return left, right, bottom, top + + +def bbox_distance(bbox1, bbox2): + """计算两个矩形框的距离。 + + Args: + bbox1 (tuple): 第一个矩形框的坐标,格式为 (x1, y1, x2, y2),其中 (x1, y1) 为左上角坐标,(x2, y2) 为右下角坐标。 + bbox2 (tuple): 第二个矩形框的坐标,格式为 (x1, y1, x2, y2),其中 (x1, y1) 为左上角坐标,(x2, y2) 为右下角坐标。 + + Returns: + float: 矩形框之间的距离。 + """ + + def dist(point1, point2): + return math.sqrt((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2) + + x1, y1, x1b, y1b = bbox1 + x2, y2, x2b, y2b = bbox2 + + left, right, bottom, top = bbox_relative_pos(bbox1, bbox2) + + if top and left: + return dist((x1, y1b), (x2b, y2)) + elif left and bottom: + return dist((x1, y1), (x2b, y2b)) + elif bottom and right: + return dist((x1b, y1), (x2, y2b)) + elif right and top: + return dist((x1b, y1b), (x2, y2)) + elif left: + return x1 - x2b + elif right: + return x2 - x1b + elif bottom: + return y1 - y2b + elif top: + return y2 - y1b + return 0.0 + + +def get_minbox_if_overlap_by_ratio(bbox1, bbox2, ratio): + """通过calculate_overlap_area_2_minbox_area_ratio计算两个bbox重叠的面积占最小面积的box的比例 + 如果比例大于ratio,则返回小的那个bbox, 否则返回None.""" + x1_min, y1_min, x1_max, y1_max = bbox1 + x2_min, y2_min, x2_max, y2_max = bbox2 + area1 = (x1_max - x1_min) * (y1_max - y1_min) + area2 = (x2_max - x2_min) * (y2_max - y2_min) + overlap_ratio = calculate_overlap_area_2_minbox_area_ratio(bbox1, bbox2) + if overlap_ratio > ratio: + if area1 <= area2: + return bbox1 + else: + return bbox2 + else: + return None + + +def calculate_overlap_area_2_minbox_area_ratio(bbox1, bbox2): + """计算box1和box2的重叠面积占最小面积的box的比例.""" + # Determine the coordinates of the intersection rectangle + x_left = max(bbox1[0], bbox2[0]) + y_top = max(bbox1[1], bbox2[1]) + x_right = min(bbox1[2], bbox2[2]) + y_bottom = min(bbox1[3], bbox2[3]) + + if x_right < x_left or y_bottom < y_top: + return 0.0 + + # The area of overlap area + intersection_area = (x_right - x_left) * (y_bottom - y_top) + min_box_area = min([(bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1]), + (bbox2[3] - bbox2[1]) * (bbox2[2] - bbox2[0])]) + if min_box_area == 0: + return 0 + else: + return intersection_area / min_box_area + + +def calculate_iou(bbox1, bbox2): + """计算两个边界框的交并比(IOU)。 + + Args: + bbox1 (list[float]): 第一个边界框的坐标,格式为 [x1, y1, x2, y2],其中 (x1, y1) 为左上角坐标,(x2, y2) 为右下角坐标。 + bbox2 (list[float]): 第二个边界框的坐标,格式与 `bbox1` 相同。 + + Returns: + float: 两个边界框的交并比(IOU),取值范围为 [0, 1]。 + """ + # Determine the coordinates of the intersection rectangle + x_left = max(bbox1[0], bbox2[0]) + y_top = max(bbox1[1], bbox2[1]) + x_right = min(bbox1[2], bbox2[2]) + y_bottom = min(bbox1[3], bbox2[3]) + + if x_right < x_left or y_bottom < y_top: + return 0.0 + + # The area of overlap area + intersection_area = (x_right - x_left) * (y_bottom - y_top) + + # The area of both rectangles + bbox1_area = (bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1]) + bbox2_area = (bbox2[2] - bbox2[0]) * (bbox2[3] - bbox2[1]) + + if any([bbox1_area == 0, bbox2_area == 0]): + return 0 + + # Compute the intersection over union by taking the intersection area + # and dividing it by the sum of both areas minus the intersection area + iou = intersection_area / float(bbox1_area + bbox2_area - intersection_area) + + return iou + + +def calculate_overlap_area_in_bbox1_area_ratio(bbox1, bbox2): + """计算box1和box2的重叠面积占bbox1的比例.""" + # Determine the coordinates of the intersection rectangle + x_left = max(bbox1[0], bbox2[0]) + y_top = max(bbox1[1], bbox2[1]) + x_right = min(bbox1[2], bbox2[2]) + y_bottom = min(bbox1[3], bbox2[3]) + + if x_right < x_left or y_bottom < y_top: + return 0.0 + + # The area of overlap area + intersection_area = (x_right - x_left) * (y_bottom - y_top) + bbox1_area = (bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1]) + if bbox1_area == 0: + return 0 + else: + return intersection_area / bbox1_area + + +def calculate_vertical_projection_overlap_ratio(block1, block2): + """ + Calculate the proportion of the x-axis covered by the vertical projection of two blocks. + + Args: + block1 (tuple): Coordinates of the first block (x0, y0, x1, y1). + block2 (tuple): Coordinates of the second block (x0, y0, x1, y1). + + Returns: + float: The proportion of the x-axis covered by the vertical projection of the two blocks. + """ + x0_1, _, x1_1, _ = block1 + x0_2, _, x1_2, _ = block2 + + # Calculate the intersection of the x-coordinates + x_left = max(x0_1, x0_2) + x_right = min(x1_1, x1_2) + + if x_right < x_left: + return 0.0 + + # Length of the intersection + intersection_length = x_right - x_left + + # Length of the x-axis projection of the first block + block1_length = x1_1 - x0_1 + + if block1_length == 0: + return 0.0 + + # Proportion of the x-axis covered by the intersection + # logger.info(f"intersection_length: {intersection_length}, block1_length: {block1_length}") + return intersection_length / block1_length \ No newline at end of file diff --git a/mineru/utils/config_reader.py b/mineru/utils/config_reader.py new file mode 100644 index 0000000000000000000000000000000000000000..54081202c738426c39852b40f05815161efe8fef --- /dev/null +++ b/mineru/utils/config_reader.py @@ -0,0 +1,138 @@ +# Copyright (c) Opendatalab. All rights reserved. +import json +import os + +import torch +from loguru import logger + +# 定义配置文件名常量 +CONFIG_FILE_NAME = os.getenv('MINERU_TOOLS_CONFIG_JSON', 'mineru.json') + + +def read_config(): + if os.path.isabs(CONFIG_FILE_NAME): + config_file = CONFIG_FILE_NAME + else: + home_dir = os.path.expanduser('~') + config_file = os.path.join(home_dir, CONFIG_FILE_NAME) + + if not os.path.exists(config_file): + # logger.warning(f'{config_file} not found, using default configuration') + return None + else: + with open(config_file, 'r', encoding='utf-8') as f: + config = json.load(f) + return config + + +def get_s3_config(bucket_name: str): + """~/magic-pdf.json 读出来.""" + config = read_config() + + bucket_info = config.get('bucket_info') + if bucket_name not in bucket_info: + access_key, secret_key, storage_endpoint = bucket_info['[default]'] + else: + access_key, secret_key, storage_endpoint = bucket_info[bucket_name] + + if access_key is None or secret_key is None or storage_endpoint is None: + raise Exception(f'ak, sk or endpoint not found in {CONFIG_FILE_NAME}') + + # logger.info(f"get_s3_config: ak={access_key}, sk={secret_key}, endpoint={storage_endpoint}") + + return access_key, secret_key, storage_endpoint + + +def get_s3_config_dict(path: str): + access_key, secret_key, storage_endpoint = get_s3_config(get_bucket_name(path)) + return {'ak': access_key, 'sk': secret_key, 'endpoint': storage_endpoint} + + +def get_bucket_name(path): + bucket, key = parse_bucket_key(path) + return bucket + + +def parse_bucket_key(s3_full_path: str): + """ + 输入 s3://bucket/path/to/my/file.txt + 输出 bucket, path/to/my/file.txt + """ + s3_full_path = s3_full_path.strip() + if s3_full_path.startswith("s3://"): + s3_full_path = s3_full_path[5:] + if s3_full_path.startswith("/"): + s3_full_path = s3_full_path[1:] + bucket, key = s3_full_path.split("/", 1) + return bucket, key + + +def get_device(): + device_mode = os.getenv('MINERU_DEVICE_MODE', None) + if device_mode is not None: + return device_mode + else: + if torch.cuda.is_available(): + return "cuda" + elif torch.backends.mps.is_available(): + return "mps" + else: + try: + import torch_npu + if torch_npu.npu.is_available(): + return "npu" + except Exception as e: + pass + return "cpu" + + +def get_table_recog_config(): + table_enable = os.getenv('MINERU_TABLE_ENABLE', None) + if table_enable is not None: + return json.loads(f'{{"enable": {table_enable}}}') + else: + # logger.warning(f"not found 'MINERU_TABLE_ENABLE' in environment variable, use 'true' as default.") + return json.loads(f'{{"enable": true}}') + + +def get_formula_config(): + formula_enable = os.getenv('MINERU_FORMULA_ENABLE', None) + if formula_enable is not None: + return json.loads(f'{{"enable": {formula_enable}}}') + else: + # logger.warning(f"not found 'MINERU_FORMULA_ENABLE' in environment variable, use 'true' as default.") + return json.loads(f'{{"enable": true}}') + + +def get_latex_delimiter_config(): + config = read_config() + if config is None: + return None + latex_delimiter_config = config.get('latex-delimiter-config', None) + if latex_delimiter_config is None: + # logger.warning(f"'latex-delimiter-config' not found in {CONFIG_FILE_NAME}, use 'None' as default") + return None + else: + return latex_delimiter_config + + +def get_llm_aided_config(): + config = read_config() + if config is None: + return None + llm_aided_config = config.get('llm-aided-config', None) + if llm_aided_config is None: + # logger.warning(f"'llm-aided-config' not found in {CONFIG_FILE_NAME}, use 'None' as default") + return None + else: + return llm_aided_config + + +def get_local_models_dir(): + config = read_config() + if config is None: + return None + models_dir = config.get('models-dir') + if models_dir is None: + logger.warning(f"'models-dir' not found in {CONFIG_FILE_NAME}, use None as default") + return models_dir \ No newline at end of file diff --git a/mineru/utils/cut_image.py b/mineru/utils/cut_image.py new file mode 100644 index 0000000000000000000000000000000000000000..20e02aeed1157bb2b5c44604d5c7497da54dad62 --- /dev/null +++ b/mineru/utils/cut_image.py @@ -0,0 +1,27 @@ +from loguru import logger + +from .pdf_image_tools import cut_image + + +def cut_image_and_table(span, page_pil_img, page_img_md5, page_id, image_writer, scale=2): + + def return_path(path_type): + return f"{path_type}/{page_img_md5}" + + span_type = span["type"] + + if not check_img_bbox(span["bbox"]) or not image_writer: + span["image_path"] = "" + else: + span["image_path"] = cut_image( + span["bbox"], page_id, page_pil_img, return_path=return_path(span_type), image_writer=image_writer, scale=scale + ) + + return span + + +def check_img_bbox(bbox) -> bool: + if any([bbox[0] >= bbox[2], bbox[1] >= bbox[3]]): + logger.warning(f"image_bboxes: 错误的box, {bbox}") + return False + return True diff --git a/mineru/utils/draw_bbox.py b/mineru/utils/draw_bbox.py new file mode 100644 index 0000000000000000000000000000000000000000..2109bea0f22f3eca53ef2b2afb44977f4d552c94 --- /dev/null +++ b/mineru/utils/draw_bbox.py @@ -0,0 +1,329 @@ +import json +from io import BytesIO + +from loguru import logger +from pypdf import PdfReader, PdfWriter +from reportlab.pdfgen import canvas + +from .enum_class import BlockType, ContentType + + +def draw_bbox_without_number(i, bbox_list, page, c, rgb_config, fill_config): + new_rgb = [float(color) / 255 for color in rgb_config] + page_data = bbox_list[i] + page_width, page_height = page.cropbox[2], page.cropbox[3] + + for bbox in page_data: + width = bbox[2] - bbox[0] + height = bbox[3] - bbox[1] + rect = [bbox[0], page_height - bbox[3], width, height] # Define the rectangle + + if fill_config: # filled rectangle + c.setFillColorRGB(new_rgb[0], new_rgb[1], new_rgb[2], 0.3) + c.rect(rect[0], rect[1], rect[2], rect[3], stroke=0, fill=1) + else: # bounding box + c.setStrokeColorRGB(new_rgb[0], new_rgb[1], new_rgb[2]) + c.rect(rect[0], rect[1], rect[2], rect[3], stroke=1, fill=0) + return c + + +def draw_bbox_with_number(i, bbox_list, page, c, rgb_config, fill_config, draw_bbox=True): + new_rgb = [float(color) / 255 for color in rgb_config] + page_data = bbox_list[i] + # 强制转换为 float + page_width, page_height = float(page.cropbox[2]), float(page.cropbox[3]) + + for j, bbox in enumerate(page_data): + # 确保bbox的每个元素都是float + x0, y0, x1, y1 = map(float, bbox) + width = x1 - x0 + height = y1 - y0 + rect = [x0, page_height - y1, width, height] + if draw_bbox: + if fill_config: + c.setFillColorRGB(*new_rgb, 0.3) + c.rect(rect[0], rect[1], rect[2], rect[3], stroke=0, fill=1) + else: + c.setStrokeColorRGB(*new_rgb) + c.rect(rect[0], rect[1], rect[2], rect[3], stroke=1, fill=0) + c.setFillColorRGB(*new_rgb, 1.0) + c.setFontSize(size=10) + # 这里也要用float + c.drawString(x1 + 2, page_height - y0 - 10, str(j + 1)) + + return c + + +def draw_layout_bbox(pdf_info, pdf_bytes, out_path, filename): + dropped_bbox_list = [] + tables_list, tables_body_list = [], [] + tables_caption_list, tables_footnote_list = [], [] + imgs_list, imgs_body_list, imgs_caption_list = [], [], [] + imgs_footnote_list = [] + titles_list = [] + texts_list = [] + interequations_list = [] + lists_list = [] + indexs_list = [] + for page in pdf_info: + page_dropped_list = [] + tables, tables_body, tables_caption, tables_footnote = [], [], [], [] + imgs, imgs_body, imgs_caption, imgs_footnote = [], [], [], [] + titles = [] + texts = [] + interequations = [] + lists = [] + indices = [] + + for dropped_bbox in page['discarded_blocks']: + page_dropped_list.append(dropped_bbox['bbox']) + dropped_bbox_list.append(page_dropped_list) + for block in page["para_blocks"]: + bbox = block["bbox"] + if block["type"] == BlockType.TABLE: + tables.append(bbox) + for nested_block in block["blocks"]: + bbox = nested_block["bbox"] + if nested_block["type"] == BlockType.TABLE_BODY: + tables_body.append(bbox) + elif nested_block["type"] == BlockType.TABLE_CAPTION: + tables_caption.append(bbox) + elif nested_block["type"] == BlockType.TABLE_FOOTNOTE: + tables_footnote.append(bbox) + elif block["type"] == BlockType.IMAGE: + imgs.append(bbox) + for nested_block in block["blocks"]: + bbox = nested_block["bbox"] + if nested_block["type"] == BlockType.IMAGE_BODY: + imgs_body.append(bbox) + elif nested_block["type"] == BlockType.IMAGE_CAPTION: + imgs_caption.append(bbox) + elif nested_block["type"] == BlockType.IMAGE_FOOTNOTE: + imgs_footnote.append(bbox) + elif block["type"] == BlockType.TITLE: + titles.append(bbox) + elif block["type"] == BlockType.TEXT: + texts.append(bbox) + elif block["type"] == BlockType.INTERLINE_EQUATION: + interequations.append(bbox) + elif block["type"] == BlockType.LIST: + lists.append(bbox) + elif block["type"] == BlockType.INDEX: + indices.append(bbox) + + tables_list.append(tables) + tables_body_list.append(tables_body) + tables_caption_list.append(tables_caption) + tables_footnote_list.append(tables_footnote) + imgs_list.append(imgs) + imgs_body_list.append(imgs_body) + imgs_caption_list.append(imgs_caption) + imgs_footnote_list.append(imgs_footnote) + titles_list.append(titles) + texts_list.append(texts) + interequations_list.append(interequations) + lists_list.append(lists) + indexs_list.append(indices) + + layout_bbox_list = [] + + table_type_order = {"table_caption": 1, "table_body": 2, "table_footnote": 3} + for page in pdf_info: + page_block_list = [] + for block in page["para_blocks"]: + if block["type"] in [ + BlockType.TEXT, + BlockType.TITLE, + BlockType.INTERLINE_EQUATION, + BlockType.LIST, + BlockType.INDEX, + ]: + bbox = block["bbox"] + page_block_list.append(bbox) + elif block["type"] in [BlockType.IMAGE]: + for sub_block in block["blocks"]: + bbox = sub_block["bbox"] + page_block_list.append(bbox) + elif block["type"] in [BlockType.TABLE]: + sorted_blocks = sorted(block["blocks"], key=lambda x: table_type_order[x["type"]]) + for sub_block in sorted_blocks: + bbox = sub_block["bbox"] + page_block_list.append(bbox) + + layout_bbox_list.append(page_block_list) + + pdf_bytes_io = BytesIO(pdf_bytes) + pdf_docs = PdfReader(pdf_bytes_io) + output_pdf = PdfWriter() + + for i, page in enumerate(pdf_docs.pages): + # 获取原始页面尺寸 + page_width, page_height = float(page.cropbox[2]), float(page.cropbox[3]) + custom_page_size = (page_width, page_height) + + packet = BytesIO() + # 使用原始PDF的尺寸创建canvas + c = canvas.Canvas(packet, pagesize=custom_page_size) + + c = draw_bbox_without_number(i, dropped_bbox_list, page, c, [158, 158, 158], True) + c = draw_bbox_without_number(i, tables_body_list, page, c, [204, 204, 0], True) + c = draw_bbox_without_number(i, tables_caption_list, page, c, [255, 255, 102], True) + c = draw_bbox_without_number(i, tables_footnote_list, page, c, [229, 255, 204], True) + c = draw_bbox_without_number(i, imgs_body_list, page, c, [153, 255, 51], True) + c = draw_bbox_without_number(i, imgs_caption_list, page, c, [102, 178, 255], True) + c = draw_bbox_without_number(i, imgs_footnote_list, page, c, [255, 178, 102], True) + c = draw_bbox_without_number(i, titles_list, page, c, [102, 102, 255], True) + c = draw_bbox_without_number(i, texts_list, page, c, [153, 0, 76], True) + c = draw_bbox_without_number(i, interequations_list, page, c, [0, 255, 0], True) + c = draw_bbox_without_number(i, lists_list, page, c, [40, 169, 92], True) + c = draw_bbox_without_number(i, indexs_list, page, c, [40, 169, 92], True) + c = draw_bbox_with_number(i, layout_bbox_list, page, c, [255, 0, 0], False, draw_bbox=False) + + c.save() + packet.seek(0) + overlay_pdf = PdfReader(packet) + + # 添加检查确保overlay_pdf.pages不为空 + if len(overlay_pdf.pages) > 0: + page.merge_page(overlay_pdf.pages[0]) + else: + # 记录日志并继续处理下一个页面 + # logger.warning(f"layout.pdf: 第{i + 1}页未能生成有效的overlay PDF") + pass + + output_pdf.add_page(page) + + # 保存结果 + with open(f"{out_path}/{filename}", "wb") as f: + output_pdf.write(f) + + +def draw_span_bbox(pdf_info, pdf_bytes, out_path, filename): + text_list = [] + inline_equation_list = [] + interline_equation_list = [] + image_list = [] + table_list = [] + dropped_list = [] + next_page_text_list = [] + next_page_inline_equation_list = [] + + def get_span_info(span): + if span['type'] == ContentType.TEXT: + if span.get('cross_page', False): + next_page_text_list.append(span['bbox']) + else: + page_text_list.append(span['bbox']) + elif span['type'] == ContentType.INLINE_EQUATION: + if span.get('cross_page', False): + next_page_inline_equation_list.append(span['bbox']) + else: + page_inline_equation_list.append(span['bbox']) + elif span['type'] == ContentType.INTERLINE_EQUATION: + page_interline_equation_list.append(span['bbox']) + elif span['type'] == ContentType.IMAGE: + page_image_list.append(span['bbox']) + elif span['type'] == ContentType.TABLE: + page_table_list.append(span['bbox']) + + for page in pdf_info: + page_text_list = [] + page_inline_equation_list = [] + page_interline_equation_list = [] + page_image_list = [] + page_table_list = [] + page_dropped_list = [] + + # 将跨页的span放到移动到下一页的列表中 + if len(next_page_text_list) > 0: + page_text_list.extend(next_page_text_list) + next_page_text_list.clear() + if len(next_page_inline_equation_list) > 0: + page_inline_equation_list.extend(next_page_inline_equation_list) + next_page_inline_equation_list.clear() + + # 构造dropped_list + for block in page['discarded_blocks']: + if block['type'] == BlockType.DISCARDED: + for line in block['lines']: + for span in line['spans']: + page_dropped_list.append(span['bbox']) + dropped_list.append(page_dropped_list) + # 构造其余useful_list + # for block in page['para_blocks']: # span直接用分段合并前的结果就可以 + for block in page['preproc_blocks']: + if block['type'] in [ + BlockType.TEXT, + BlockType.TITLE, + BlockType.INTERLINE_EQUATION, + BlockType.LIST, + BlockType.INDEX, + ]: + for line in block['lines']: + for span in line['spans']: + get_span_info(span) + elif block['type'] in [BlockType.IMAGE, BlockType.TABLE]: + for sub_block in block['blocks']: + for line in sub_block['lines']: + for span in line['spans']: + get_span_info(span) + text_list.append(page_text_list) + inline_equation_list.append(page_inline_equation_list) + interline_equation_list.append(page_interline_equation_list) + image_list.append(page_image_list) + table_list.append(page_table_list) + + pdf_bytes_io = BytesIO(pdf_bytes) + pdf_docs = PdfReader(pdf_bytes_io) + output_pdf = PdfWriter() + + for i, page in enumerate(pdf_docs.pages): + # 获取原始页面尺寸 + page_width, page_height = float(page.cropbox[2]), float(page.cropbox[3]) + custom_page_size = (page_width, page_height) + + packet = BytesIO() + # 使用原始PDF的尺寸创建canvas + c = canvas.Canvas(packet, pagesize=custom_page_size) + + # 获取当前页面的数据 + draw_bbox_without_number(i, text_list, page, c,[255, 0, 0], False) + draw_bbox_without_number(i, inline_equation_list, page, c, [0, 255, 0], False) + draw_bbox_without_number(i, interline_equation_list, page, c, [0, 0, 255], False) + draw_bbox_without_number(i, image_list, page, c, [255, 204, 0], False) + draw_bbox_without_number(i, table_list, page, c, [204, 0, 255], False) + draw_bbox_without_number(i, dropped_list, page, c, [158, 158, 158], False) + + c.save() + packet.seek(0) + overlay_pdf = PdfReader(packet) + + # 添加检查确保overlay_pdf.pages不为空 + if len(overlay_pdf.pages) > 0: + page.merge_page(overlay_pdf.pages[0]) + else: + # 记录日志并继续处理下一个页面 + # logger.warning(f"span.pdf: 第{i + 1}页未能生成有效的overlay PDF") + pass + + output_pdf.add_page(page) + + # Save the PDF + with open(f"{out_path}/{filename}", "wb") as f: + output_pdf.write(f) + + +if __name__ == "__main__": + # 读取PDF文件 + pdf_path = "examples/demo1.pdf" + with open(pdf_path, "rb") as f: + pdf_bytes = f.read() + + # 从json文件读取pdf_info + + json_path = "examples/demo1_1746005777.0863056_middle.json" + with open(json_path, "r", encoding="utf-8") as f: + pdf_ann = json.load(f) + pdf_info = pdf_ann["pdf_info"] + # 调用可视化函数,输出到examples目录 + draw_layout_bbox(pdf_info, pdf_bytes, "examples", "output_with_layout.pdf") diff --git a/mineru/utils/enum_class.py b/mineru/utils/enum_class.py new file mode 100644 index 0000000000000000000000000000000000000000..ac99fd47b64d7666309f295a782426a03a04acfb --- /dev/null +++ b/mineru/utils/enum_class.py @@ -0,0 +1,63 @@ +class BlockType: + IMAGE = 'image' + TABLE = 'table' + IMAGE_BODY = 'image_body' + TABLE_BODY = 'table_body' + IMAGE_CAPTION = 'image_caption' + TABLE_CAPTION = 'table_caption' + IMAGE_FOOTNOTE = 'image_footnote' + TABLE_FOOTNOTE = 'table_footnote' + TEXT = 'text' + TITLE = 'title' + INTERLINE_EQUATION = 'interline_equation' + LIST = 'list' + INDEX = 'index' + DISCARDED = 'discarded' + + +class ContentType: + IMAGE = 'image' + TABLE = 'table' + TEXT = 'text' + INTERLINE_EQUATION = 'interline_equation' + INLINE_EQUATION = 'inline_equation' + + +class CategoryId: + Title = 0 + Text = 1 + Abandon = 2 + ImageBody = 3 + ImageCaption = 4 + TableBody = 5 + TableCaption = 6 + TableFootnote = 7 + InterlineEquation_Layout = 8 + InlineEquation = 13 + InterlineEquation_YOLO = 14 + OcrText = 15 + ImageFootnote = 101 + + +class MakeMode: + MM_MD = 'mm_markdown' + NLP_MD = 'nlp_markdown' + CONTENT_LIST = 'content_list' + + +class ModelPath: + vlm_root_hf = "opendatalab/MinerU2.0-2505-0.9B" + vlm_root_modelscope = "OpenDataLab/MinerU2.0-2505-0.9B" + pipeline_root_modelscope = "OpenDataLab/PDF-Extract-Kit-1.0" + pipeline_root_hf = "opendatalab/PDF-Extract-Kit-1.0" + doclayout_yolo = "models/Layout/YOLO/doclayout_yolo_docstructbench_imgsz1280_2501.pt" + yolo_v8_mfd = "models/MFD/YOLO/yolo_v8_ft.pt" + unimernet_small = "models/MFR/unimernet_hf_small_2503" + pytorch_paddle = "models/OCR/paddleocr_torch" + layout_reader = "models/ReadingOrder/layout_reader" + slanet_plus = "models/TabRec/SlanetPlus/slanet-plus.onnx" + + +class SplitFlag: + CROSS_PAGE = 'cross_page' + LINES_DELETED = 'lines_deleted' \ No newline at end of file diff --git a/mineru/utils/format_utils.py b/mineru/utils/format_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..3cf6ec088988a0c9db3fee2a6ad1a0f8616c994d --- /dev/null +++ b/mineru/utils/format_utils.py @@ -0,0 +1,289 @@ + +import re +import itertools +import html +from typing import Any, Dict, List +from pydantic import ( + BaseModel, + computed_field, + model_validator, +) + +class TableCell(BaseModel): + """TableCell.""" + row_span: int = 1 + col_span: int = 1 + start_row_offset_idx: int + end_row_offset_idx: int + start_col_offset_idx: int + end_col_offset_idx: int + text: str + column_header: bool = False + row_header: bool = False + row_section: bool = False + + @model_validator(mode="before") + @classmethod + def from_dict_format(cls, data: Any) -> Any: + """from_dict_format.""" + if isinstance(data, Dict): + # Check if this is a native BoundingBox or a bbox from docling-ibm-models + if ( + # "bbox" not in data + # or data["bbox"] is None + # or isinstance(data["bbox"], BoundingBox) + "text" + in data + ): + return data + text = data["bbox"].get("token", "") + if not len(text): + text_cells = data.pop("text_cell_bboxes", None) + if text_cells: + for el in text_cells: + text += el["token"] + " " + + text = text.strip() + data["text"] = text + + return data + + +class TableData(BaseModel): # TBD + """BaseTableData.""" + + table_cells: List[TableCell] = [] + num_rows: int = 0 + num_cols: int = 0 + + @computed_field # type: ignore + @property + def grid( + self, + ) -> List[List[TableCell]]: + """grid.""" + # Initialise empty table data grid (only empty cells) + table_data = [ + [ + TableCell( + text="", + start_row_offset_idx=i, + end_row_offset_idx=i + 1, + start_col_offset_idx=j, + end_col_offset_idx=j + 1, + ) + for j in range(self.num_cols) + ] + for i in range(self.num_rows) + ] + + # Overwrite cells in table data for which there is actual cell content. + for cell in self.table_cells: + for i in range( + min(cell.start_row_offset_idx, self.num_rows), + min(cell.end_row_offset_idx, self.num_rows), + ): + for j in range( + min(cell.start_col_offset_idx, self.num_cols), + min(cell.end_col_offset_idx, self.num_cols), + ): + table_data[i][j] = cell + + return table_data + + +""" +OTSL +""" +OTSL_NL = "" +OTSL_FCEL = "" +OTSL_ECEL = "" +OTSL_LCEL = "" +OTSL_UCEL = "" +OTSL_XCEL = "" + + +def otsl_extract_tokens_and_text(s: str): + # Pattern to match anything enclosed by < > + # (including the angle brackets themselves) + # pattern = r"(<[^>]+>)" + pattern = r"(" + r"|".join([OTSL_NL, OTSL_FCEL, OTSL_ECEL, OTSL_LCEL, OTSL_UCEL, OTSL_XCEL]) + r")" + # Find all tokens (e.g. "", "", etc.) + tokens = re.findall(pattern, s) + # Remove any tokens that start with "= len(tokens[r_idx]): + return span + return span + + def count_down(tokens, c_idx, r_idx, which_tokens): + span = 0 + r_idx_iter = r_idx + while tokens[r_idx_iter][c_idx] in which_tokens: + r_idx_iter += 1 + span += 1 + if r_idx_iter >= len(tokens): + return span + return span + + for i, text in enumerate(texts): + cell_text = "" + if text in [ + OTSL_FCEL, + OTSL_ECEL, + ]: + row_span = 1 + col_span = 1 + right_offset = 1 + if text != OTSL_ECEL: + cell_text = texts[i + 1] + right_offset = 2 + + # Check next element(s) for lcel / ucel / xcel, + # set properly row_span, col_span + next_right_cell = "" + if i + right_offset < len(texts): + next_right_cell = texts[i + right_offset] + + next_bottom_cell = "" + if r_idx + 1 < len(split_row_tokens): + if c_idx < len(split_row_tokens[r_idx + 1]): + next_bottom_cell = split_row_tokens[r_idx + 1][c_idx] + + if next_right_cell in [ + OTSL_LCEL, + OTSL_XCEL, + ]: + # we have horisontal spanning cell or 2d spanning cell + col_span += count_right( + split_row_tokens, + c_idx + 1, + r_idx, + [OTSL_LCEL, OTSL_XCEL], + ) + if next_bottom_cell in [ + OTSL_UCEL, + OTSL_XCEL, + ]: + # we have a vertical spanning cell or 2d spanning cell + row_span += count_down( + split_row_tokens, + c_idx, + r_idx + 1, + [OTSL_UCEL, OTSL_XCEL], + ) + + table_cells.append( + TableCell( + text=cell_text.strip(), + row_span=row_span, + col_span=col_span, + start_row_offset_idx=r_idx, + end_row_offset_idx=r_idx + row_span, + start_col_offset_idx=c_idx, + end_col_offset_idx=c_idx + col_span, + ) + ) + if text in [ + OTSL_FCEL, + OTSL_ECEL, + OTSL_LCEL, + OTSL_UCEL, + OTSL_XCEL, + ]: + c_idx += 1 + if text == OTSL_NL: + r_idx += 1 + c_idx = 0 + return table_cells, split_row_tokens + + +def export_to_html(table_data: TableData): + nrows = table_data.num_rows + ncols = table_data.num_cols + + text = "" + + if len(table_data.table_cells) == 0: + return "" + + body = "" + + for i in range(nrows): + body += "" + for j in range(ncols): + cell: TableCell = table_data.grid[i][j] + + rowspan, rowstart = ( + cell.row_span, + cell.start_row_offset_idx, + ) + colspan, colstart = ( + cell.col_span, + cell.start_col_offset_idx, + ) + + if rowstart != i: + continue + if colstart != j: + continue + + content = html.escape(cell.text.strip()) + celltag = "td" + if cell.column_header: + celltag = "th" + + opening_tag = f"{celltag}" + if rowspan > 1: + opening_tag += f' rowspan="{rowspan}"' + if colspan > 1: + opening_tag += f' colspan="{colspan}"' + + body += f"<{opening_tag}>{content}" + body += "" + + # dir = get_text_direction(text) + body = f"{body}
    " + + return body + + +def convert_otsl_to_html(otsl_content: str): + tokens, mixed_texts = otsl_extract_tokens_and_text(otsl_content) + table_cells, split_row_tokens = otsl_parse_texts(mixed_texts, tokens) + + table_data = TableData( + num_rows=len(split_row_tokens), + num_cols=( + max(len(row) for row in split_row_tokens) if split_row_tokens else 0 + ), + table_cells=table_cells, + ) + + return export_to_html(table_data) diff --git a/mineru/utils/hash_utils.py b/mineru/utils/hash_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..2b82c78dd8d8839698edaa28bb78cdd25aa2ac67 --- /dev/null +++ b/mineru/utils/hash_utils.py @@ -0,0 +1,30 @@ +# Copyright (c) Opendatalab. All rights reserved. +import hashlib +import json + + +def bytes_md5(file_bytes): + hasher = hashlib.md5() + hasher.update(file_bytes) + return hasher.hexdigest().upper() + + +def str_md5(input_string): + hasher = hashlib.md5() + # 在Python3中,需要将字符串转化为字节对象才能被哈希函数处理 + input_bytes = input_string.encode('utf-8') + hasher.update(input_bytes) + return hasher.hexdigest() + + +def str_sha256(input_string): + hasher = hashlib.sha256() + # 在Python3中,需要将字符串转化为字节对象才能被哈希函数处理 + input_bytes = input_string.encode('utf-8') + hasher.update(input_bytes) + return hasher.hexdigest() + + +def dict_md5(d): + json_str = json.dumps(d, sort_keys=True, ensure_ascii=False) + return hashlib.md5(json_str.encode('utf-8')).hexdigest() \ No newline at end of file diff --git a/magic_pdf/libs/language.py b/mineru/utils/language.py similarity index 100% rename from magic_pdf/libs/language.py rename to mineru/utils/language.py diff --git a/magic_pdf/post_proc/llm_aided.py b/mineru/utils/llm_aided.py similarity index 56% rename from magic_pdf/post_proc/llm_aided.py rename to mineru/utils/llm_aided.py index c37481b3298a654b4596383e565f4514734d2dec..31ebd15286f3ace9d602161c427b8e244e72907a 100644 --- a/magic_pdf/post_proc/llm_aided.py +++ b/mineru/utils/llm_aided.py @@ -1,76 +1,12 @@ # Copyright (c) Opendatalab. All rights reserved. -import json from loguru import logger -from magic_pdf.dict2md.ocr_mkcontent import merge_para_with_text from openai import OpenAI import ast +from mineru.backend.pipeline.pipeline_middle_json_mkcontent import merge_para_with_text -#@todo: 有的公式以"\"结尾,这样会导致尾部拼接的"$"被转义,也需要修复 -formula_optimize_prompt = """请根据以下指南修正LaTeX公式的错误,确保公式能够渲染且符合原始内容: -1. 修正渲染或编译错误: - - Some syntax errors such as mismatched/missing/extra tokens. Your task is to fix these syntax errors and make sure corrected results conform to latex math syntax principles. - - 包含KaTeX不支持的关键词等原因导致的无法编译或渲染的错误 - -2. 保留原始信息: - - 保留原始公式中的所有重要信息 - - 不要添加任何原始公式中没有的新信息 - -IMPORTANT:请仅返回修正后的公式,不要包含任何介绍、解释或元数据。 - -LaTeX recognition result: -$FORMULA - -Your corrected result: -""" - -text_optimize_prompt = f"""请根据以下指南修正OCR引起的错误,确保文本连贯并符合原始内容: - -1. 修正OCR引起的拼写错误和错误: - - 修正常见的OCR错误(例如,'rn' 被误读为 'm') - - 使用上下文和常识进行修正 - - 只修正明显的错误,不要不必要的修改内容 - - 不要添加额外的句号或其他不必要的标点符号 - -2. 保持原始结构: - - 保留所有标题和子标题 - -3. 保留原始内容: - - 保留原始文本中的所有重要信息 - - 不要添加任何原始文本中没有的新信息 - - 保留段落之间的换行符 - -4. 保持连贯性: - - 确保内容与前文顺畅连接 - - 适当处理在句子中间开始或结束的文本 - -5. 修正行内公式: - - 去除行内公式前后多余的空格 - - 修正公式中的OCR错误 - - 确保公式能够通过KaTeX渲染 - -6. 修正全角字符 - - 修正全角标点符号为半角标点符号 - - 修正全角字母为半角字母 - - 修正全角数字为半角数字 - -IMPORTANT:请仅返回修正后的文本,保留所有原始格式,包括换行符。不要包含任何介绍、解释或元数据。 - -Previous context: - -Current chunk to process: - -Corrected text: -""" - -def llm_aided_formula(pdf_info_dict, formula_aided_config): - pass - -def llm_aided_text(pdf_info_dict, text_aided_config): - pass - -def llm_aided_title(pdf_info_dict, title_aided_config): +def llm_aided_title(page_info_list, title_aided_config): client = OpenAI( api_key=title_aided_config["api_key"], base_url=title_aided_config["base_url"], @@ -78,8 +14,8 @@ def llm_aided_title(pdf_info_dict, title_aided_config): title_dict = {} origin_title_list = [] i = 0 - for page_num, page in pdf_info_dict.items(): - blocks = page["para_blocks"] + for page_info in page_info_list: + blocks = page_info["para_blocks"] for block in blocks: if block["type"] == "title": origin_title_list.append(block) @@ -92,7 +28,7 @@ def llm_aided_title(pdf_info_dict, title_aided_config): line_avg_height = sum(page_line_height_list) / len(page_line_height_list) else: line_avg_height = int(block['bbox'][3] - block['bbox'][1]) - title_dict[f"{i}"] = [title_text, line_avg_height, int(page_num[5:])+1] + title_dict[f"{i}"] = [title_text, line_avg_height, int(page_info['page_idx']) + 1] i += 1 # logger.info(f"Title list: {title_dict}") @@ -115,16 +51,21 @@ def llm_aided_title(pdf_info_dict, title_aided_config): - 标题从前至后的层级必须是连续的,不能跳过层级 - 标题层级最多为4级,不要添加过多的层级 - 优化后的标题只保留代表该标题的层级的整数,不要保留其他信息 - + 5. 合理性检查与微调: - 在完成初步分级后,仔细检查分级结果的合理性 - 根据上下文关系和逻辑顺序,对不合理的分级进行微调 - 确保最终的分级结果符合文档的实际结构和逻辑 - 字典中可能包含被误当成标题的正文,你可以通过将其层级标记为 0 来排除它们 - + IMPORTANT: 请直接返回优化过的由标题层级组成的字典,格式为{{标题id:标题层级}},如下: -{{0:1,1:2,2:2,3:3}} +{{ + 0:1, + 1:2, + 2:2, + 3:3 +}} 不需要对字典格式化,不需要返回任何其他信息。 Input title list: @@ -145,16 +86,23 @@ Corrected title list: {'role': 'user', 'content': title_optimize_prompt}], temperature=0.7, ) - # logger.info(f"Title completion: {completion.choices[0].message.content}") - dict_completion = ast.literal_eval(completion.choices[0].message.content) - # logger.info(f"len(dict_completion): {len(dict_completion)}, len(title_dict): {len(title_dict)}") + content = completion.choices[0].message.content.strip() + # logger.info(f"Title completion: {content}") + if "" in content: + idx = content.index("") + len("") + content = content[idx:].strip() + import json_repair + dict_completion = json_repair.loads(content) + dict_completion = {int(k): int(v) for k, v in dict_completion.items()} + # logger.info(f"len(dict_completion): {len(dict_completion)}, len(title_dict): {len(title_dict)}") if len(dict_completion) == len(title_dict): for i, origin_title_block in enumerate(origin_title_list): origin_title_block["level"] = int(dict_completion[i]) break else: - logger.warning("The number of titles in the optimized result is not equal to the number of titles in the input.") + logger.warning( + "The number of titles in the optimized result is not equal to the number of titles in the input.") retry_count += 1 except Exception as e: logger.exception(e) diff --git a/magic_pdf/model/sub_modules/model_utils.py b/mineru/utils/model_utils.py similarity index 88% rename from magic_pdf/model/sub_modules/model_utils.py rename to mineru/utils/model_utils.py index 04d0fbbd028290e46cab1adc5911674fe0541ef0..ec724ffdcd2ae1aad41b94e50c6d19e3b0a44233 100644 --- a/magic_pdf/model/sub_modules/model_utils.py +++ b/mineru/utils/model_utils.py @@ -1,13 +1,14 @@ import time import torch +import gc +from PIL import Image from loguru import logger import numpy as np -from magic_pdf.libs.boxbase import get_minbox_if_overlap_by_ratio -from magic_pdf.libs.clean_memory import clean_memory +from mineru.utils.boxbase import get_minbox_if_overlap_by_ratio -def crop_img(input_res, input_np_img, crop_paste_x=0, crop_paste_y=0): +def crop_img(input_res, input_img, crop_paste_x=0, crop_paste_y=0): crop_xmin, crop_ymin = int(input_res['poly'][0]), int(input_res['poly'][1]) crop_xmax, crop_ymax = int(input_res['poly'][4]), int(input_res['poly'][5]) @@ -16,15 +17,24 @@ def crop_img(input_res, input_np_img, crop_paste_x=0, crop_paste_y=0): crop_new_width = crop_xmax - crop_xmin + crop_paste_x * 2 crop_new_height = crop_ymax - crop_ymin + crop_paste_y * 2 - # Create a white background array - return_image = np.ones((crop_new_height, crop_new_width, 3), dtype=np.uint8) * 255 + if isinstance(input_img, np.ndarray): - # Crop the original image using numpy slicing - cropped_img = input_np_img[crop_ymin:crop_ymax, crop_xmin:crop_xmax] + # Create a white background array + return_image = np.ones((crop_new_height, crop_new_width, 3), dtype=np.uint8) * 255 - # Paste the cropped image onto the white background - return_image[crop_paste_y:crop_paste_y + (crop_ymax - crop_ymin), - crop_paste_x:crop_paste_x + (crop_xmax - crop_xmin)] = cropped_img + # Crop the original image using numpy slicing + cropped_img = input_img[crop_ymin:crop_ymax, crop_xmin:crop_xmax] + + # Paste the cropped image onto the white background + return_image[crop_paste_y:crop_paste_y + (crop_ymax - crop_ymin), + crop_paste_x:crop_paste_x + (crop_xmax - crop_xmin)] = cropped_img + else: + # Create a white background array + return_image = Image.new('RGB', (crop_new_width, crop_new_height), 'white') + # Crop image + crop_box = (crop_xmin, crop_ymin, crop_xmax, crop_ymax) + cropped_img = input_img.crop(crop_box) + return_image.paste(cropped_img, (crop_paste_x, crop_paste_y)) return_list = [crop_paste_x, crop_paste_y, crop_xmin, crop_ymin, crop_xmax, crop_ymax, crop_new_width, crop_new_height] @@ -287,6 +297,20 @@ def get_res_list_from_layout_res(layout_res, iou_threshold=0.7, overlap_threshol return ocr_res_list, filtered_table_res_list, single_page_mfdetrec_res +def clean_memory(device='cuda'): + if device == 'cuda': + if torch.cuda.is_available(): + torch.cuda.empty_cache() + torch.cuda.ipc_collect() + elif str(device).startswith("npu"): + import torch_npu + if torch_npu.npu.is_available(): + torch_npu.npu.empty_cache() + elif str(device).startswith("mps"): + torch.mps.empty_cache() + gc.collect() + + def clean_vram(device, vram_threshold=8): total_memory = get_vram(device) if total_memory and total_memory <= vram_threshold: diff --git a/mineru/utils/models_download_utils.py b/mineru/utils/models_download_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..b2c17156cfb1f580fb94ebbb16a248dfc3830ed7 --- /dev/null +++ b/mineru/utils/models_download_utils.py @@ -0,0 +1,71 @@ +import os +from huggingface_hub import snapshot_download as hf_snapshot_download +from modelscope import snapshot_download as ms_snapshot_download + +from mineru.utils.config_reader import get_local_models_dir +from mineru.utils.enum_class import ModelPath + +def auto_download_and_get_model_root_path(relative_path: str, repo_mode='pipeline') -> str: + """ + 支持文件或目录的可靠下载。 + - 如果输入文件: 返回本地文件绝对路径 + - 如果输入目录: 返回本地缓存下与 relative_path 同结构的相对路径字符串 + :param repo_mode: 指定仓库模式,'pipeline' 或 'vlm' + :param relative_path: 文件或目录相对路径 + :return: 本地文件绝对路径或相对路径 + """ + model_source = os.getenv('MINERU_MODEL_SOURCE', "huggingface") + + if model_source == 'local': + local_models_config = get_local_models_dir() + root_path = local_models_config.get(repo_mode, None) + if not root_path: + raise ValueError(f"Local path for repo_mode '{repo_mode}' is not configured.") + return root_path + + # 建立仓库模式到路径的映射 + repo_mapping = { + 'pipeline': { + 'huggingface': ModelPath.pipeline_root_hf, + 'modelscope': ModelPath.pipeline_root_modelscope, + 'default': ModelPath.pipeline_root_hf + }, + 'vlm': { + 'huggingface': ModelPath.vlm_root_hf, + 'modelscope': ModelPath.vlm_root_modelscope, + 'default': ModelPath.vlm_root_hf + } + } + + if repo_mode not in repo_mapping: + raise ValueError(f"Unsupported repo_mode: {repo_mode}, must be 'pipeline' or 'vlm'") + + # 如果没有指定model_source或值不是'modelscope',则使用默认值 + repo = repo_mapping[repo_mode].get(model_source, repo_mapping[repo_mode]['default']) + + + if model_source == "huggingface": + snapshot_download = hf_snapshot_download + elif model_source == "modelscope": + snapshot_download = ms_snapshot_download + else: + raise ValueError(f"未知的仓库类型: {model_source}") + + cache_dir = None + + if repo_mode == 'pipeline': + relative_path = relative_path.strip('/') + cache_dir = snapshot_download(repo, allow_patterns=[relative_path, relative_path+"/*"]) + elif repo_mode == 'vlm': + # VLM 模式下,直接下载整个模型目录 + cache_dir = snapshot_download(repo) + + if not cache_dir: + raise FileNotFoundError(f"Failed to download model: {relative_path} from {repo}") + return cache_dir + + +if __name__ == '__main__': + path1 = "models/README.md" + root = auto_download_and_get_model_root_path(path1) + print("本地文件绝对路径:", os.path.join(root, path1)) \ No newline at end of file diff --git a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/ocr_utils.py b/mineru/utils/ocr_utils.py similarity index 87% rename from magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/ocr_utils.py rename to mineru/utils/ocr_utils.py index 70989fdf3958646b5778e4000d3750220a1d5c7a..cfeed33b4a539c607aed99dc39e9df8514b38441 100644 --- a/magic_pdf/model/sub_modules/ocr/paddleocr2pytorch/ocr_utils.py +++ b/mineru/utils/ocr_utils.py @@ -1,10 +1,51 @@ # Copyright (c) Opendatalab. All rights reserved. import copy - import cv2 import numpy as np -from magic_pdf.pre_proc.ocr_dict_merge import merge_spans_to_line -from magic_pdf.libs.boxbase import __is_overlaps_y_exceeds_threshold + + +class OcrConfidence: + min_confidence = 0.68 + min_width = 3 + + +def merge_spans_to_line(spans, threshold=0.6): + if len(spans) == 0: + return [] + else: + # 按照y0坐标排序 + spans.sort(key=lambda span: span['bbox'][1]) + + lines = [] + current_line = [spans[0]] + for span in spans[1:]: + # 如果当前的span与当前行的最后一个span在y轴上重叠,则添加到当前行 + if __is_overlaps_y_exceeds_threshold(span['bbox'], current_line[-1]['bbox'], threshold): + current_line.append(span) + else: + # 否则,开始新行 + lines.append(current_line) + current_line = [span] + + # 添加最后一行 + if current_line: + lines.append(current_line) + + return lines + +def __is_overlaps_y_exceeds_threshold(bbox1, + bbox2, + overlap_ratio_threshold=0.8): + """检查两个bbox在y轴上是否有重叠,并且该重叠区域的高度占两个bbox高度更低的那个超过80%""" + _, y0_1, _, y1_1 = bbox1 + _, y0_2, _, y1_2 = bbox2 + + overlap = max(0, min(y1_1, y1_2) - max(y0_1, y0_2)) + height1, height2 = y1_1 - y0_1, y1_2 - y0_2 + # max_height = max(height1, height2) + min_height = min(height1, height2) + + return (overlap / min_height) > overlap_ratio_threshold def img_decode(content: bytes): @@ -212,10 +253,7 @@ def merge_det_boxes(dt_boxes): angle_boxes_list.append(text_box) continue - text_box_dict = { - 'bbox': text_bbox, - 'type': 'text', - } + text_box_dict = {'bbox': text_bbox} dt_boxes_dict_list.append(text_box_dict) # Merge adjacent text regions into lines @@ -271,7 +309,7 @@ def get_ocr_result_list(ocr_res, useful_list, ocr_enable, new_image, lang): p1, p2, p3, p4 = box_ocr_res[0] text, score = box_ocr_res[1] # logger.info(f"text: {text}, score: {score}") - if score < 0.6: # 过滤低置信度的结果 + if score < OcrConfidence.min_confidence: # 过滤低置信度的结果 continue else: p1, p2, p3, p4 = box_ocr_res @@ -284,6 +322,11 @@ def get_ocr_result_list(ocr_res, useful_list, ocr_enable, new_image, lang): # average_angle_degrees = calculate_angle_degrees(box_ocr_res[0]) # if average_angle_degrees > 0.5: poly = [p1, p2, p3, p4] + + if (p3[0] - p1[0]) < OcrConfidence.min_width: + # logger.info(f"width too small: {p3[0] - p1[0]}, text: {text}") + continue + if calculate_is_angle(poly): # logger.info(f"average_angle_degrees: {average_angle_degrees}, text: {text}") # 与x轴的夹角超过0.5度,对边界做一下矫正 diff --git a/mineru/utils/pdf_classify.py b/mineru/utils/pdf_classify.py new file mode 100644 index 0000000000000000000000000000000000000000..1e98d2eea917ab8c483911089e487676b0c38561 --- /dev/null +++ b/mineru/utils/pdf_classify.py @@ -0,0 +1,260 @@ +# Copyright (c) Opendatalab. All rights reserved. +import re +from io import BytesIO +import numpy as np +import pypdfium2 as pdfium +from loguru import logger +from pdfminer.high_level import extract_text +from pdfminer.pdfparser import PDFParser +from pdfminer.pdfdocument import PDFDocument +from pdfminer.pdfpage import PDFPage +from pdfminer.pdfinterp import PDFResourceManager +from pdfminer.pdfinterp import PDFPageInterpreter +from pdfminer.layout import LAParams, LTImage, LTFigure +from pdfminer.converter import PDFPageAggregator + + +def classify(pdf_bytes): + """ + 判断PDF文件是可以直接提取文本还是需要OCR + + Args: + pdf_bytes: PDF文件的字节数据 + + Returns: + str: 'txt' 表示可以直接提取文本,'ocr' 表示需要OCR + """ + try: + # 从字节数据加载PDF + sample_pdf_bytes = extract_pages(pdf_bytes) + pdf = pdfium.PdfDocument(sample_pdf_bytes) + + # 获取PDF页数 + page_count = len(pdf) + + # 如果PDF页数为0,直接返回OCR + if page_count == 0: + return 'ocr' + + # 检查的页面数(最多检查10页) + pages_to_check = min(page_count, 10) + + # 设置阈值:如果每页平均少于50个有效字符,认为需要OCR + chars_threshold = 50 + + if (get_avg_cleaned_chars_per_page(pdf, pages_to_check) < chars_threshold) or detect_invalid_chars(sample_pdf_bytes): + return 'ocr' + else: + + if get_high_image_coverage_ratio(sample_pdf_bytes, pages_to_check) >= 0.8: + return 'ocr' + + return 'txt' + except Exception as e: + logger.error(f"判断PDF类型时出错: {e}") + # 出错时默认使用OCR + return 'ocr' + + +def get_avg_cleaned_chars_per_page(pdf_doc, pages_to_check): + # 总字符数 + total_chars = 0 + # 清理后的总字符数 + cleaned_total_chars = 0 + + # 检查前几页的文本 + for i in range(pages_to_check): + page = pdf_doc[i] + text_page = page.get_textpage() + text = text_page.get_text_bounded() + total_chars += len(text) + + # 清理提取的文本,移除空白字符 + cleaned_text = re.sub(r'\s+', '', text) + cleaned_total_chars += len(cleaned_text) + + # 计算平均每页字符数 + avg_cleaned_chars_per_page = cleaned_total_chars / pages_to_check + + # logger.debug(f"PDF分析: 平均每页清理后{avg_cleaned_chars_per_page:.1f}字符") + + pdf_doc.close() # 关闭PDF文档 + + return avg_cleaned_chars_per_page + + +def get_high_image_coverage_ratio(sample_pdf_bytes, pages_to_check): + # 创建内存文件对象 + pdf_stream = BytesIO(sample_pdf_bytes) + + # 创建PDF解析器 + parser = PDFParser(pdf_stream) + + # 创建PDF文档对象 + document = PDFDocument(parser) + + # 检查文档是否允许文本提取 + if not document.is_extractable: + # logger.warning("PDF不允许内容提取") + return 1.0 # 默认为高覆盖率,因为无法提取内容 + + # 创建资源管理器和参数对象 + rsrcmgr = PDFResourceManager() + laparams = LAParams( + line_overlap=0.5, + char_margin=2.0, + line_margin=0.5, + word_margin=0.1, + boxes_flow=None, + detect_vertical=False, + all_texts=False, + ) + + # 创建聚合器 + device = PDFPageAggregator(rsrcmgr, laparams=laparams) + + # 创建解释器 + interpreter = PDFPageInterpreter(rsrcmgr, device) + + # 记录高图像覆盖率的页面数量 + high_image_coverage_pages = 0 + page_count = 0 + + # 遍历页面 + for page in PDFPage.create_pages(document): + # 控制检查的页数 + if page_count >= pages_to_check: + break + + # 处理页面 + interpreter.process_page(page) + layout = device.get_result() + + # 页面尺寸 + page_width = layout.width + page_height = layout.height + page_area = page_width * page_height + + # 计算图像覆盖的总面积 + image_area = 0 + + # 遍历页面元素 + for element in layout: + # 检查是否为图像或图形元素 + if isinstance(element, (LTImage, LTFigure)): + # 计算图像边界框面积 + img_width = element.width + img_height = element.height + img_area = img_width * img_height + image_area += img_area + + # 计算覆盖率 + coverage_ratio = min(image_area / page_area, 1.0) if page_area > 0 else 0 + # logger.debug(f"PDF分析: 页面 {page_count + 1} 图像覆盖率: {coverage_ratio:.2f}") + + # 判断是否为高覆盖率 + if coverage_ratio >= 0.8: # 使用80%作为高覆盖率的阈值 + high_image_coverage_pages += 1 + + page_count += 1 + + # 如果没有处理任何页面,返回0 + if page_count == 0: + return 0.0 + + # 计算高图像覆盖率的页面比例 + high_coverage_ratio = high_image_coverage_pages / page_count + # logger.debug(f"PDF分析: 高图像覆盖页面比例: {high_coverage_ratio:.2f}") + + # 关闭资源 + pdf_stream.close() + + return high_coverage_ratio + + +def extract_pages(src_pdf_bytes: bytes) -> bytes: + """ + 从PDF字节数据中随机提取最多10页,返回新的PDF字节数据 + + Args: + src_pdf_bytes: PDF文件的字节数据 + + Returns: + bytes: 提取页面后的PDF字节数据 + """ + + # 从字节数据加载PDF + pdf = pdfium.PdfDocument(src_pdf_bytes) + + # 获取PDF页数 + total_page = len(pdf) + if total_page == 0: + # 如果PDF没有页面,直接返回空文档 + logger.warning("PDF is empty, return empty document") + return b'' + + # 选择最多10页 + select_page_cnt = min(10, total_page) + + # 从总页数中随机选择页面 + page_indices = np.random.choice(total_page, select_page_cnt, replace=False).tolist() + + # 创建一个新的PDF文档 + sample_docs = pdfium.PdfDocument.new() + + try: + # 将选择的页面导入新文档 + sample_docs.import_pages(pdf, page_indices) + + # 将新PDF保存到内存缓冲区 + output_buffer = BytesIO() + sample_docs.save(output_buffer) + + # 获取字节数据 + return output_buffer.getvalue() + except Exception as e: + logger.exception(e) + return b'' # 出错时返回空字节 + + +def detect_invalid_chars(sample_pdf_bytes: bytes) -> bool: + """" + 检测PDF中是否包含非法字符 + """ + '''pdfminer比较慢,需要先随机抽取10页左右的sample''' + # sample_pdf_bytes = extract_pages(src_pdf_bytes) + sample_pdf_file_like_object = BytesIO(sample_pdf_bytes) + laparams = LAParams( + line_overlap=0.5, + char_margin=2.0, + line_margin=0.5, + word_margin=0.1, + boxes_flow=None, + detect_vertical=False, + all_texts=False, + ) + text = extract_text(pdf_file=sample_pdf_file_like_object, laparams=laparams) + text = text.replace("\n", "") + # logger.info(text) + '''乱码文本用pdfminer提取出来的文本特征是(cid:xxx)''' + cid_pattern = re.compile(r'\(cid:\d+\)') + matches = cid_pattern.findall(text) + cid_count = len(matches) + cid_len = sum(len(match) for match in matches) + text_len = len(text) + if text_len == 0: + cid_chars_radio = 0 + else: + cid_chars_radio = cid_count/(cid_count + text_len - cid_len) + # logger.debug(f"cid_count: {cid_count}, text_len: {text_len}, cid_chars_radio: {cid_chars_radio}") + '''当一篇文章存在5%以上的文本是乱码时,认为该文档为乱码文档''' + if cid_chars_radio > 0.05: + return True # 乱码文档 + else: + return False # 正常文档 + + +if __name__ == '__main__': + with open('/Users/myhloli/pdf/luanma2x10.pdf', 'rb') as f: + p_bytes = f.read() + logger.info(f"PDF分类结果: {classify(p_bytes)}") \ No newline at end of file diff --git a/mineru/utils/pdf_image_tools.py b/mineru/utils/pdf_image_tools.py new file mode 100644 index 0000000000000000000000000000000000000000..36ed43ba7887482fbcbd0adf6bd85232da66e5fc --- /dev/null +++ b/mineru/utils/pdf_image_tools.py @@ -0,0 +1,103 @@ +# Copyright (c) Opendatalab. All rights reserved. +from io import BytesIO + +import pypdfium2 as pdfium +from loguru import logger +from PIL import Image + +from mineru.data.data_reader_writer import FileBasedDataWriter +from mineru.utils.pdf_reader import image_to_b64str, image_to_bytes, page_to_image +from .hash_utils import str_sha256 + + +def pdf_page_to_image(page: pdfium.PdfPage, dpi=200) -> dict: + """Convert pdfium.PdfDocument to image, Then convert the image to base64. + + Args: + page (_type_): pdfium.PdfPage + dpi (int, optional): reset the dpi of dpi. Defaults to 200. + + Returns: + dict: {'img_base64': str, 'img_pil': pil_img, 'scale': float } + """ + pil_img, scale = page_to_image(page, dpi=dpi) + img_base64 = image_to_b64str(pil_img) + + image_dict = { + "img_base64": img_base64, + "img_pil": pil_img, + "scale": scale, + } + return image_dict + + +def load_images_from_pdf( + pdf_bytes: bytes, + dpi=200, + start_page_id=0, + end_page_id=None, +): + images_list = [] + pdf_doc = pdfium.PdfDocument(pdf_bytes) + pdf_page_num = len(pdf_doc) + end_page_id = end_page_id if end_page_id is not None and end_page_id >= 0 else pdf_page_num - 1 + if end_page_id > pdf_page_num - 1: + logger.warning("end_page_id is out of range, use images length") + end_page_id = pdf_page_num - 1 + + for index in range(0, pdf_page_num): + if start_page_id <= index <= end_page_id: + page = pdf_doc[index] + image_dict = pdf_page_to_image(page, dpi=dpi) + images_list.append(image_dict) + + return images_list, pdf_doc + + +def cut_image(bbox: tuple, page_num: int, page_pil_img, return_path, image_writer: FileBasedDataWriter, scale=2): + """从第page_num页的page中,根据bbox进行裁剪出一张jpg图片,返回图片路径 save_path:需要同时支持s3和本地, + 图片存放在save_path下,文件名是: + {page_num}_{bbox[0]}_{bbox[1]}_{bbox[2]}_{bbox[3]}.jpg , bbox内数字取整。""" + + # 拼接文件名 + filename = f"{page_num}_{int(bbox[0])}_{int(bbox[1])}_{int(bbox[2])}_{int(bbox[3])}" + + # 老版本返回不带bucket的路径 + img_path = f"{return_path}_{filename}" if return_path is not None else None + + # 新版本生成平铺路径 + img_hash256_path = f"{str_sha256(img_path)}.jpg" + # img_hash256_path = f'{img_path}.jpg' + + crop_img = get_crop_img(bbox, page_pil_img, scale=scale) + + img_bytes = image_to_bytes(crop_img, image_format="JPEG") + + image_writer.write(img_hash256_path, img_bytes) + return img_hash256_path + + +def get_crop_img(bbox: tuple, pil_img, scale=2): + scale_bbox = ( + int(bbox[0] * scale), + int(bbox[1] * scale), + int(bbox[2] * scale), + int(bbox[3] * scale), + ) + return pil_img.crop(scale_bbox) + + +def images_bytes_to_pdf_bytes(image_bytes): + # 内存缓冲区 + pdf_buffer = BytesIO() + + # 载入并转换所有图像为 RGB 模式 + image = Image.open(BytesIO(image_bytes)).convert("RGB") + + # 第一张图保存为 PDF,其余追加 + image.save(pdf_buffer, format="PDF", save_all=True) + + # 获取 PDF bytes 并重置指针(可选) + pdf_bytes = pdf_buffer.getvalue() + pdf_buffer.close() + return pdf_bytes diff --git a/mineru/utils/pdf_reader.py b/mineru/utils/pdf_reader.py new file mode 100644 index 0000000000000000000000000000000000000000..5d887ddf5e3b23c3d6788ce68e3a04bcb00c333a --- /dev/null +++ b/mineru/utils/pdf_reader.py @@ -0,0 +1,98 @@ +# Copyright (c) Opendatalab. All rights reserved. +import base64 +from io import BytesIO + +from loguru import logger +from PIL import Image +from pypdfium2 import PdfBitmap, PdfDocument, PdfPage + + +def page_to_image( + page: PdfPage, + dpi: int = 144, # changed from 200 to 144 + max_width_or_height: int = 2560, # changed from 4500 to 2560 +) -> (Image.Image, float): + scale = dpi / 72 + + long_side_length = max(*page.get_size()) + if long_side_length > max_width_or_height: + scale = max_width_or_height / long_side_length + + bitmap: PdfBitmap = page.render(scale=scale) # type: ignore + try: + image = bitmap.to_pil() + finally: + try: + bitmap.close() + except Exception: + pass + return image, scale + + +def image_to_bytes( + image: Image.Image, + image_format: str = "PNG", # 也可以用 "JPEG" +) -> bytes: + with BytesIO() as image_buffer: + image.save(image_buffer, format=image_format) + return image_buffer.getvalue() + + +def image_to_b64str( + image: Image.Image, + image_format: str = "PNG", # 也可以用 "JPEG" +) -> str: + image_bytes = image_to_bytes(image, image_format) + return base64.b64encode(image_bytes).decode("utf-8") + + +def pdf_to_images( + pdf: str | bytes | PdfDocument, + dpi: int = 144, + max_width_or_height: int = 2560, + start_page_id: int = 0, + end_page_id: int | None = None, +) -> list[Image.Image]: + doc = pdf if isinstance(pdf, PdfDocument) else PdfDocument(pdf) + page_num = len(doc) + + end_page_id = end_page_id if end_page_id is not None and end_page_id >= 0 else page_num - 1 + if end_page_id > page_num - 1: + logger.warning("end_page_id is out of range, use images length") + end_page_id = page_num - 1 + + images = [] + try: + for i in range(start_page_id, end_page_id + 1): + image, _ = page_to_image(doc[i], dpi, max_width_or_height) + images.append(image) + finally: + try: + doc.close() + except Exception: + pass + return images + + +def pdf_to_images_bytes( + pdf: str | bytes | PdfDocument, + dpi: int = 144, + max_width_or_height: int = 2560, + start_page_id: int = 0, + end_page_id: int | None = None, + image_format: str = "PNG", +) -> list[bytes]: + images = pdf_to_images(pdf, dpi, max_width_or_height, start_page_id, end_page_id) + return [image_to_bytes(image, image_format) for image in images] + + +def pdf_to_images_b64strs( + pdf: str | bytes | PdfDocument, + dpi: int = 144, + max_width_or_height: int = 2560, + start_page_id: int = 0, + end_page_id: int | None = None, + image_format: str = "PNG", +) -> list[str]: + images = pdf_to_images(pdf, dpi, max_width_or_height, start_page_id, end_page_id) + return [image_to_b64str(image, image_format) for image in images] diff --git a/mineru/utils/pdf_text_tool.py b/mineru/utils/pdf_text_tool.py new file mode 100644 index 0000000000000000000000000000000000000000..8635743990ba25ba4b6da05103574ade3d934b97 --- /dev/null +++ b/mineru/utils/pdf_text_tool.py @@ -0,0 +1,40 @@ +from typing import List +import math + +import pypdfium2 as pdfium +from pdftext.pdf.chars import get_chars, deduplicate_chars +from pdftext.pdf.pages import get_spans, get_lines, assign_scripts, get_blocks + + +def get_page( + page: pdfium.PdfPage, + quote_loosebox: bool =True, + superscript_height_threshold: float = 0.7, + line_distance_threshold: float = 0.1, +) -> dict: + + textpage = page.get_textpage() + page_bbox: List[float] = page.get_bbox() + page_width = math.ceil(abs(page_bbox[2] - page_bbox[0])) + page_height = math.ceil(abs(page_bbox[1] - page_bbox[3])) + + page_rotation = 0 + try: + page_rotation = page.get_rotation() + except: + pass + + chars = deduplicate_chars(get_chars(textpage, page_bbox, page_rotation, quote_loosebox)) + spans = get_spans(chars, superscript_height_threshold=superscript_height_threshold, line_distance_threshold=line_distance_threshold) + lines = get_lines(spans) + assign_scripts(lines, height_threshold=superscript_height_threshold, line_distance_threshold=line_distance_threshold) + blocks = get_blocks(lines) + + page = { + "bbox": page_bbox, + "width": page_width, + "height": page_height, + "rotation": page_rotation, + "blocks": blocks + } + return page \ No newline at end of file diff --git a/mineru/utils/run_async.py b/mineru/utils/run_async.py new file mode 100644 index 0000000000000000000000000000000000000000..7282ec197b9714dcf4991384c6da1513f8a41d41 --- /dev/null +++ b/mineru/utils/run_async.py @@ -0,0 +1,52 @@ +import asyncio +import threading +from queue import Queue +from typing import Any, AsyncIterable, Coroutine, Iterable, TypeVar + +T = TypeVar("T") + + +def run_async(coroutine: Coroutine[Any, Any, T]) -> T: + if not asyncio.iscoroutine(coroutine): + raise ValueError("a coroutine was expected, got {!r}".format(coroutine)) + + try: + loop = asyncio.get_running_loop() + except RuntimeError: + loop = None + + if loop is not None: + return loop.run_until_complete(coroutine) + else: + return asyncio.run(coroutine) + + +def iter_async(iterable: AsyncIterable[T]) -> Iterable[T]: + if not isinstance(iterable, AsyncIterable): + raise ValueError("an async iterable was expected, got {!r}".format(iterable)) + + queue = Queue() + + async def async_helper(): + try: + async for chunk in iterable: + queue.put(chunk) + queue.put(None) + except Exception as e: + queue.put(e) + + def helper(): + run_async(async_helper()) + + thread = threading.Thread(target=helper, daemon=True) + thread.start() + + while True: + chunk = queue.get() + if chunk is None: + break + if isinstance(chunk, Exception): + raise chunk + yield chunk + + thread.join() diff --git a/magic_pdf/pre_proc/ocr_dict_merge.py b/mineru/utils/span_block_fix.py similarity index 67% rename from magic_pdf/pre_proc/ocr_dict_merge.py rename to mineru/utils/span_block_fix.py index 38ca3652b2d34e09e74b5bc2f8acbaddc11d4917..86d38b8efd35a57eb76ff24147f55622c313738b 100644 --- a/magic_pdf/pre_proc/ocr_dict_merge.py +++ b/mineru/utils/span_block_fix.py @@ -1,24 +1,81 @@ -from magic_pdf.config.ocr_content_type import BlockType, ContentType -from magic_pdf.libs.boxbase import __is_overlaps_y_exceeds_threshold, calculate_overlap_area_in_bbox1_area_ratio +# Copyright (c) Opendatalab. All rights reserved. +from mineru.utils.boxbase import calculate_overlap_area_in_bbox1_area_ratio +from mineru.utils.enum_class import BlockType, ContentType +from mineru.utils.ocr_utils import __is_overlaps_y_exceeds_threshold -# 将每一个line中的span从左到右排序 -def line_sort_spans_by_left_to_right(lines): - line_objects = [] - for line in lines: - # 按照x0坐标排序 - line.sort(key=lambda span: span['bbox'][0]) - line_bbox = [ - min(span['bbox'][0] for span in line), # x0 - min(span['bbox'][1] for span in line), # y0 - max(span['bbox'][2] for span in line), # x1 - max(span['bbox'][3] for span in line), # y1 +def fill_spans_in_blocks(blocks, spans, radio): + """将allspans中的span按位置关系,放入blocks中.""" + block_with_spans = [] + for block in blocks: + block_type = block[7] + block_bbox = block[0:4] + block_dict = { + 'type': block_type, + 'bbox': block_bbox, + } + if block_type in [ + BlockType.IMAGE_BODY, BlockType.IMAGE_CAPTION, BlockType.IMAGE_FOOTNOTE, + BlockType.TABLE_BODY, BlockType.TABLE_CAPTION, BlockType.TABLE_FOOTNOTE + ]: + block_dict['group_id'] = block[-1] + block_spans = [] + for span in spans: + span_bbox = span['bbox'] + if calculate_overlap_area_in_bbox1_area_ratio(span_bbox, block_bbox) > radio and span_block_type_compatible( + span['type'], block_type): + block_spans.append(span) + + block_dict['spans'] = block_spans + block_with_spans.append(block_dict) + + # 从spans删除已经放入block_spans中的span + if len(block_spans) > 0: + for span in block_spans: + spans.remove(span) + + return block_with_spans, spans + + +def span_block_type_compatible(span_type, block_type): + if span_type in [ContentType.TEXT, ContentType.INLINE_EQUATION]: + return block_type in [ + BlockType.TEXT, + BlockType.TITLE, + BlockType.IMAGE_CAPTION, + BlockType.IMAGE_FOOTNOTE, + BlockType.TABLE_CAPTION, + BlockType.TABLE_FOOTNOTE, + BlockType.DISCARDED ] - line_objects.append({ - 'bbox': line_bbox, - 'spans': line, - }) - return line_objects + elif span_type == ContentType.INTERLINE_EQUATION: + return block_type in [BlockType.INTERLINE_EQUATION, BlockType.TEXT] + elif span_type == ContentType.IMAGE: + return block_type in [BlockType.IMAGE_BODY] + elif span_type == ContentType.TABLE: + return block_type in [BlockType.TABLE_BODY] + else: + return False + + +def fix_discarded_block(discarded_block_with_spans): + fix_discarded_blocks = [] + for block in discarded_block_with_spans: + block = fix_text_block(block) + fix_discarded_blocks.append(block) + return fix_discarded_blocks + + +def fix_text_block(block): + # 文本block中的公式span都应该转换成行内type + for span in block['spans']: + if span['type'] == ContentType.INTERLINE_EQUATION: + span['type'] = ContentType.INLINE_EQUATION + block_lines = merge_spans_to_line(block['spans']) + sort_block_lines = line_sort_spans_by_left_to_right(block_lines) + block['lines'] = sort_block_lines + del block['spans'] + return block def merge_spans_to_line(spans, threshold=0.6): @@ -34,11 +91,11 @@ def merge_spans_to_line(spans, threshold=0.6): # 如果当前的span类型为"interline_equation" 或者 当前行中已经有"interline_equation" # image和table类型,同上 if span['type'] in [ - ContentType.InterlineEquation, ContentType.Image, - ContentType.Table + ContentType.INTERLINE_EQUATION, ContentType.IMAGE, + ContentType.TABLE ] or any(s['type'] in [ - ContentType.InterlineEquation, ContentType.Image, - ContentType.Table + ContentType.INTERLINE_EQUATION, ContentType.IMAGE, + ContentType.TABLE ] for s in current_line): # 则开始新行 lines.append(current_line) @@ -60,70 +117,36 @@ def merge_spans_to_line(spans, threshold=0.6): return lines -def span_block_type_compatible(span_type, block_type): - if span_type in [ContentType.Text, ContentType.InlineEquation]: - return block_type in [ - BlockType.Text, - BlockType.Title, - BlockType.ImageCaption, - BlockType.ImageFootnote, - BlockType.TableCaption, - BlockType.TableFootnote, - BlockType.Discarded +# 将每一个line中的span从左到右排序 +def line_sort_spans_by_left_to_right(lines): + line_objects = [] + for line in lines: + # 按照x0坐标排序 + line.sort(key=lambda span: span['bbox'][0]) + line_bbox = [ + min(span['bbox'][0] for span in line), # x0 + min(span['bbox'][1] for span in line), # y0 + max(span['bbox'][2] for span in line), # x1 + max(span['bbox'][3] for span in line), # y1 ] - elif span_type == ContentType.InterlineEquation: - return block_type in [BlockType.InterlineEquation, BlockType.Text] - elif span_type == ContentType.Image: - return block_type in [BlockType.ImageBody] - elif span_type == ContentType.Table: - return block_type in [BlockType.TableBody] - else: - return False - - -def fill_spans_in_blocks(blocks, spans, radio): - """将allspans中的span按位置关系,放入blocks中.""" - block_with_spans = [] - for block in blocks: - block_type = block[7] - block_bbox = block[0:4] - block_dict = { - 'type': block_type, - 'bbox': block_bbox, - } - if block_type in [ - BlockType.ImageBody, BlockType.ImageCaption, BlockType.ImageFootnote, - BlockType.TableBody, BlockType.TableCaption, BlockType.TableFootnote - ]: - block_dict['group_id'] = block[-1] - block_spans = [] - for span in spans: - span_bbox = span['bbox'] - if calculate_overlap_area_in_bbox1_area_ratio(span_bbox, block_bbox) > radio and span_block_type_compatible(span['type'], block_type): - block_spans.append(span) - - block_dict['spans'] = block_spans - block_with_spans.append(block_dict) - - # 从spans删除已经放入block_spans中的span - if len(block_spans) > 0: - for span in block_spans: - spans.remove(span) - - return block_with_spans, spans + line_objects.append({ + 'bbox': line_bbox, + 'spans': line, + }) + return line_objects -def fix_block_spans_v2(block_with_spans): +def fix_block_spans(block_with_spans): fix_blocks = [] for block in block_with_spans: block_type = block['type'] - if block_type in [BlockType.Text, BlockType.Title, - BlockType.ImageCaption, BlockType.ImageFootnote, - BlockType.TableCaption, BlockType.TableFootnote + if block_type in [BlockType.TEXT, BlockType.TITLE, + BlockType.IMAGE_CAPTION, BlockType.IMAGE_CAPTION, + BlockType.TABLE_CAPTION, BlockType.TABLE_FOOTNOTE ]: block = fix_text_block(block) - elif block_type in [BlockType.InterlineEquation, BlockType.ImageBody, BlockType.TableBody]: + elif block_type in [BlockType.INTERLINE_EQUATION, BlockType.IMAGE_BODY, BlockType.TABLE_BODY]: block = fix_interline_block(block) else: continue @@ -131,29 +154,9 @@ def fix_block_spans_v2(block_with_spans): return fix_blocks -def fix_discarded_block(discarded_block_with_spans): - fix_discarded_blocks = [] - for block in discarded_block_with_spans: - block = fix_text_block(block) - fix_discarded_blocks.append(block) - return fix_discarded_blocks - - -def fix_text_block(block): - # 文本block中的公式span都应该转换成行内type - for span in block['spans']: - if span['type'] == ContentType.InterlineEquation: - span['type'] = ContentType.InlineEquation - block_lines = merge_spans_to_line(block['spans']) - sort_block_lines = line_sort_spans_by_left_to_right(block_lines) - block['lines'] = sort_block_lines - del block['spans'] - return block - - def fix_interline_block(block): block_lines = merge_spans_to_line(block['spans']) sort_block_lines = line_sort_spans_by_left_to_right(block_lines) block['lines'] = sort_block_lines del block['spans'] - return block + return block \ No newline at end of file diff --git a/mineru/utils/span_pre_proc.py b/mineru/utils/span_pre_proc.py new file mode 100644 index 0000000000000000000000000000000000000000..3931ac8d1467511af70fc3cdaaf24e3a34182966 --- /dev/null +++ b/mineru/utils/span_pre_proc.py @@ -0,0 +1,327 @@ +# Copyright (c) Opendatalab. All rights reserved. +import re +import statistics + +import cv2 +import numpy as np +from loguru import logger + +from mineru.utils.boxbase import calculate_overlap_area_in_bbox1_area_ratio, calculate_iou, \ + get_minbox_if_overlap_by_ratio +from mineru.utils.enum_class import BlockType, ContentType +from mineru.utils.pdf_image_tools import get_crop_img +from mineru.utils.pdf_text_tool import get_page + + +def remove_outside_spans(spans, all_bboxes, all_discarded_blocks): + def get_block_bboxes(blocks, block_type_list): + return [block[0:4] for block in blocks if block[7] in block_type_list] + + image_bboxes = get_block_bboxes(all_bboxes, [BlockType.IMAGE_BODY]) + table_bboxes = get_block_bboxes(all_bboxes, [BlockType.TABLE_BODY]) + other_block_type = [] + for block_type in BlockType.__dict__.values(): + if not isinstance(block_type, str): + continue + if block_type not in [BlockType.IMAGE_BODY, BlockType.TABLE_BODY]: + other_block_type.append(block_type) + other_block_bboxes = get_block_bboxes(all_bboxes, other_block_type) + discarded_block_bboxes = get_block_bboxes(all_discarded_blocks, [BlockType.DISCARDED]) + + new_spans = [] + + for span in spans: + span_bbox = span['bbox'] + span_type = span['type'] + + if any(calculate_overlap_area_in_bbox1_area_ratio(span_bbox, block_bbox) > 0.4 for block_bbox in + discarded_block_bboxes): + new_spans.append(span) + continue + + if span_type == ContentType.IMAGE: + if any(calculate_overlap_area_in_bbox1_area_ratio(span_bbox, block_bbox) > 0.5 for block_bbox in + image_bboxes): + new_spans.append(span) + elif span_type == ContentType.TABLE: + if any(calculate_overlap_area_in_bbox1_area_ratio(span_bbox, block_bbox) > 0.5 for block_bbox in + table_bboxes): + new_spans.append(span) + else: + if any(calculate_overlap_area_in_bbox1_area_ratio(span_bbox, block_bbox) > 0.5 for block_bbox in + other_block_bboxes): + new_spans.append(span) + + return new_spans + + +def remove_overlaps_low_confidence_spans(spans): + dropped_spans = [] + # 删除重叠spans中置信度低的的那些 + for span1 in spans: + for span2 in spans: + if span1 != span2: + # span1 或 span2 任何一个都不应该在 dropped_spans 中 + if span1 in dropped_spans or span2 in dropped_spans: + continue + else: + if calculate_iou(span1['bbox'], span2['bbox']) > 0.9: + if span1['score'] < span2['score']: + span_need_remove = span1 + else: + span_need_remove = span2 + if ( + span_need_remove is not None + and span_need_remove not in dropped_spans + ): + dropped_spans.append(span_need_remove) + + if len(dropped_spans) > 0: + for span_need_remove in dropped_spans: + spans.remove(span_need_remove) + + return spans, dropped_spans + + +def remove_overlaps_min_spans(spans): + dropped_spans = [] + # 删除重叠spans中较小的那些 + for span1 in spans: + for span2 in spans: + if span1 != span2: + # span1 或 span2 任何一个都不应该在 dropped_spans 中 + if span1 in dropped_spans or span2 in dropped_spans: + continue + else: + overlap_box = get_minbox_if_overlap_by_ratio(span1['bbox'], span2['bbox'], 0.65) + if overlap_box is not None: + span_need_remove = next((span for span in spans if span['bbox'] == overlap_box), None) + if span_need_remove is not None and span_need_remove not in dropped_spans: + dropped_spans.append(span_need_remove) + if len(dropped_spans) > 0: + for span_need_remove in dropped_spans: + spans.remove(span_need_remove) + + return spans, dropped_spans + + +def __replace_ligatures(text: str): + ligatures = { + 'fi': 'fi', 'fl': 'fl', 'ff': 'ff', 'ffi': 'ffi', 'ffl': 'ffl', 'ſt': 'ft', 'st': 'st' + } + return re.sub('|'.join(map(re.escape, ligatures.keys())), lambda m: ligatures[m.group()], text) + +def __replace_unicode(text: str): + ligatures = { + '\r\n': '', '\u0002': '-', + } + return re.sub('|'.join(map(re.escape, ligatures.keys())), lambda m: ligatures[m.group()], text) + + +"""pdf_text dict方案 char级别""" +def txt_spans_extract(pdf_page, spans, pil_img, scale, all_bboxes, all_discarded_blocks): + + page_dict = get_page(pdf_page) + + page_all_chars = [] + page_all_lines = [] + for block in page_dict['blocks']: + for line in block['lines']: + if 0 < abs(line['rotation']) < 90: + # 旋转角度在0-90度之间的行,直接跳过 + continue + page_all_lines.append(line) + for span in line['spans']: + for char in span['chars']: + page_all_chars.append(char) + + # 计算所有sapn的高度的中位数 + span_height_list = [] + for span in spans: + if span['type'] in [ContentType.TEXT]: + span_height = span['bbox'][3] - span['bbox'][1] + span['height'] = span_height + span['width'] = span['bbox'][2] - span['bbox'][0] + span_height_list.append(span_height) + if len(span_height_list) == 0: + return spans + else: + median_span_height = statistics.median(span_height_list) + + useful_spans = [] + unuseful_spans = [] + # 纵向span的两个特征:1. 高度超过多个line 2. 高宽比超过某个值 + vertical_spans = [] + for span in spans: + if span['type'] in [ContentType.TEXT]: + for block in all_bboxes + all_discarded_blocks: + if block[7] in [BlockType.IMAGE_BODY, BlockType.TABLE_BODY, BlockType.INTERLINE_EQUATION]: + continue + if calculate_overlap_area_in_bbox1_area_ratio(span['bbox'], block[0:4]) > 0.5: + if span['height'] > median_span_height * 3 and span['height'] > span['width'] * 3: + vertical_spans.append(span) + elif block in all_bboxes: + useful_spans.append(span) + else: + unuseful_spans.append(span) + break + + """垂直的span框直接用line进行填充""" + if len(vertical_spans) > 0: + for pdfium_line in page_all_lines: + for span in vertical_spans: + if calculate_overlap_area_in_bbox1_area_ratio(pdfium_line['bbox'].bbox, span['bbox']) > 0.5: + for pdfium_span in pdfium_line['spans']: + span['content'] += pdfium_span['text'] + break + + for span in vertical_spans: + if len(span['content']) == 0: + spans.remove(span) + + """水平的span框先用char填充,再用ocr填充空的span框""" + new_spans = [] + + for span in useful_spans + unuseful_spans: + if span['type'] in [ContentType.TEXT]: + span['chars'] = [] + new_spans.append(span) + + need_ocr_spans = fill_char_in_spans(new_spans, page_all_chars) + + """对未填充的span进行ocr""" + if len(need_ocr_spans) > 0: + + for span in need_ocr_spans: + # 对span的bbox截图再ocr + span_pil_img = get_crop_img(span['bbox'], pil_img, scale) + span_img = cv2.cvtColor(np.array(span_pil_img), cv2.COLOR_RGB2BGR) + # 计算span的对比度,低于0.20的span不进行ocr + if calculate_contrast(span_img, img_mode='bgr') <= 0.17: + spans.remove(span) + continue + + span['content'] = '' + span['score'] = 1.0 + span['np_img'] = span_img + + return spans + + +def fill_char_in_spans(spans, all_chars): + + # 简单从上到下排一下序 + spans = sorted(spans, key=lambda x: x['bbox'][1]) + + for char in all_chars: + + for span in spans: + if calculate_char_in_span(char['bbox'], span['bbox'], char['char']): + span['chars'].append(char) + break + + need_ocr_spans = [] + for span in spans: + chars_to_content(span) + # 有的span中虽然没有字但有一两个空的占位符,用宽高和content长度过滤 + if len(span['content']) * span['height'] < span['width'] * 0.5: + # logger.info(f"maybe empty span: {len(span['content'])}, {span['height']}, {span['width']}") + need_ocr_spans.append(span) + del span['height'], span['width'] + return need_ocr_spans + + +LINE_STOP_FLAG = ('.', '!', '?', '。', '!', '?', ')', ')', '"', '”', ':', ':', ';', ';', ']', '】', '}', '}', '>', '》', '、', ',', ',', '-', '—', '–',) +LINE_START_FLAG = ('(', '(', '"', '“', '【', '{', '《', '<', '「', '『', '【', '[',) + +Span_Height_Radio = 0.33 # 字符的中轴和span的中轴高度差不能超过1/3span高度 +def calculate_char_in_span(char_bbox, span_bbox, char, span_height_radio=Span_Height_Radio): + char_center_x = (char_bbox[0] + char_bbox[2]) / 2 + char_center_y = (char_bbox[1] + char_bbox[3]) / 2 + span_center_y = (span_bbox[1] + span_bbox[3]) / 2 + span_height = span_bbox[3] - span_bbox[1] + + if ( + span_bbox[0] < char_center_x < span_bbox[2] + and span_bbox[1] < char_center_y < span_bbox[3] + and abs(char_center_y - span_center_y) < span_height * span_height_radio # 字符的中轴和span的中轴高度差不能超过Span_Height_Radio + ): + return True + else: + # 如果char是LINE_STOP_FLAG,就不用中心点判定,换一种方案(左边界在span区域内,高度判定和之前逻辑一致) + # 主要是给结尾符号一个进入span的机会,这个char还应该离span右边界较近 + if char in LINE_STOP_FLAG: + if ( + (span_bbox[2] - span_height) < char_bbox[0] < span_bbox[2] + and char_center_x > span_bbox[0] + and span_bbox[1] < char_center_y < span_bbox[3] + and abs(char_center_y - span_center_y) < span_height * span_height_radio + ): + return True + elif char in LINE_START_FLAG: + if ( + span_bbox[0] < char_bbox[2] < (span_bbox[0] + span_height) + and char_center_x < span_bbox[2] + and span_bbox[1] < char_center_y < span_bbox[3] + and abs(char_center_y - span_center_y) < span_height * span_height_radio + ): + return True + else: + return False + + +def chars_to_content(span): + # 检查span中的char是否为空 + if len(span['chars']) == 0: + pass + else: + # 给chars按char_idx排序 + span['chars'] = sorted(span['chars'], key=lambda x: x['char_idx']) + + # Calculate the width of each character + char_widths = [char['bbox'][2] - char['bbox'][0] for char in span['chars']] + # Calculate the median width + median_width = statistics.median(char_widths) + + content = '' + for char in span['chars']: + + # 如果下一个char的x0和上一个char的x1距离超过0.25个字符宽度,则需要在中间插入一个空格 + char1 = char + char2 = span['chars'][span['chars'].index(char) + 1] if span['chars'].index(char) + 1 < len(span['chars']) else None + if char2 and char2['bbox'][0] - char1['bbox'][2] > median_width * 0.25 and char['char'] != ' ' and char2['char'] != ' ': + content += f"{char['char']} " + else: + content += char['char'] + + content = __replace_unicode(content) + content = __replace_ligatures(content) + content = __replace_ligatures(content) + span['content'] = content.strip() + + del span['chars'] + + +def calculate_contrast(img, img_mode) -> float: + """ + 计算给定图像的对比度。 + :param img: 图像,类型为numpy.ndarray + :Param img_mode = 图像的色彩通道,'rgb' 或 'bgr' + :return: 图像的对比度值 + """ + if img_mode == 'rgb': + # 将RGB图像转换为灰度图 + gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) + elif img_mode == 'bgr': + # 将BGR图像转换为灰度图 + gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + else: + raise ValueError("Invalid image mode. Please provide 'rgb' or 'bgr'.") + + # 计算均值和标准差 + mean_value = np.mean(gray_img) + std_dev = np.std(gray_img) + # 对比度定义为标准差除以平均值(加上小常数避免除零错误) + contrast = std_dev / (mean_value + 1e-6) + # logger.debug(f"contrast: {contrast}") + return round(contrast, 2) \ No newline at end of file diff --git a/mineru/version.py b/mineru/version.py new file mode 100644 index 0000000000000000000000000000000000000000..5a6bc65ed94515a041237159e5d2c89402f12a58 --- /dev/null +++ b/mineru/version.py @@ -0,0 +1 @@ +__version__ = "2.0.0" \ No newline at end of file diff --git a/next_docs/en/.readthedocs.yaml b/next_docs/en/.readthedocs.yaml deleted file mode 100644 index 99e6a055aad044187a82b59285286cf79566a0d9..0000000000000000000000000000000000000000 --- a/next_docs/en/.readthedocs.yaml +++ /dev/null @@ -1,16 +0,0 @@ -version: 2 - -build: - os: ubuntu-22.04 - tools: - python: "3.10" - -formats: - - epub - -python: - install: - - requirements: next_docs/requirements.txt - -sphinx: - configuration: next_docs/en/conf.py diff --git a/next_docs/en/Makefile b/next_docs/en/Makefile deleted file mode 100644 index d4bb2cbb9eddb1bb1b4f366623044af8e4830919..0000000000000000000000000000000000000000 --- a/next_docs/en/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/next_docs/en/_static/image/MinerU-logo-hq.png b/next_docs/en/_static/image/MinerU-logo-hq.png deleted file mode 100644 index 7b33fcda2ab95e693c978e914f8b6b95fd84cc87..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/MinerU-logo-hq.png and /dev/null differ diff --git a/next_docs/en/_static/image/MinerU-logo.png b/next_docs/en/_static/image/MinerU-logo.png deleted file mode 100644 index 2e6fdf3a9ec43217155c0d9239fe4d8b6f913611..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/MinerU-logo.png and /dev/null differ diff --git a/next_docs/en/_static/image/ReadTheDocs.svg b/next_docs/en/_static/image/ReadTheDocs.svg deleted file mode 100644 index de907442fa897899e90ab62e5a3c95a1af44b118..0000000000000000000000000000000000000000 --- a/next_docs/en/_static/image/ReadTheDocs.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - -Created with Fabric.js 5.2.4 - - - - - - - - - - - - - Read The Docs - - - - - - Read The Docs - - \ No newline at end of file diff --git a/next_docs/en/_static/image/datalab_logo.png b/next_docs/en/_static/image/datalab_logo.png deleted file mode 100644 index 5019ae7cfdef185058cf402504275df18e9b1403..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/datalab_logo.png and /dev/null differ diff --git a/next_docs/en/_static/image/flowchart_en.png b/next_docs/en/_static/image/flowchart_en.png deleted file mode 100644 index b490011ea7a9edebeb9edbf3980fc971d89bb76a..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/flowchart_en.png and /dev/null differ diff --git a/next_docs/en/_static/image/flowchart_zh_cn.png b/next_docs/en/_static/image/flowchart_zh_cn.png deleted file mode 100644 index 32e0a14233972666cf4507af178c77cfe41e3311..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/flowchart_zh_cn.png and /dev/null differ diff --git a/next_docs/en/_static/image/inference_result.png b/next_docs/en/_static/image/inference_result.png deleted file mode 100644 index 7fb907103a077e484b5daea0f8e299d414b3f727..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/inference_result.png and /dev/null differ diff --git a/next_docs/en/_static/image/layout_example.png b/next_docs/en/_static/image/layout_example.png deleted file mode 100644 index 14e2116f6fa8acd3099220a8d235420fe1e9af92..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/layout_example.png and /dev/null differ diff --git a/next_docs/en/_static/image/logo.png b/next_docs/en/_static/image/logo.png deleted file mode 100644 index 09ab46b232b443ba72d82a3c7d608afb725f4478..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/logo.png and /dev/null differ diff --git a/next_docs/en/_static/image/pipeline.drawio.svg b/next_docs/en/_static/image/pipeline.drawio.svg deleted file mode 100644 index b74666430e65951f3e8b85ec9951a0b1eb13b5e6..0000000000000000000000000000000000000000 --- a/next_docs/en/_static/image/pipeline.drawio.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
    Dataset
    Inference
    Result
    Pipeline
    Result
    /data/abc.pdf
    /data/a.jpg

    s3://data/a.pdf
    draw layout result
    dump markdown file

    draw span result
    draw model result
    dump inference result

    doc_analyze
    pipe_ocr_mode
    \ No newline at end of file diff --git a/next_docs/en/_static/image/poly.png b/next_docs/en/_static/image/poly.png deleted file mode 100644 index 14af772668b003c53c7c773e39addf5006836e13..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/poly.png and /dev/null differ diff --git a/next_docs/en/_static/image/project_panorama_en.png b/next_docs/en/_static/image/project_panorama_en.png deleted file mode 100644 index 19616da641076c037c47919c0d3de9efb8e409da..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/project_panorama_en.png and /dev/null differ diff --git a/next_docs/en/_static/image/project_panorama_zh_cn.png b/next_docs/en/_static/image/project_panorama_zh_cn.png deleted file mode 100644 index 3cd6843e05b827cb0a7c9cc31855de0d3f4645c5..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/project_panorama_zh_cn.png and /dev/null differ diff --git a/next_docs/en/_static/image/spans_example.png b/next_docs/en/_static/image/spans_example.png deleted file mode 100644 index 14de87ed7aaa84ccf3db78512ecda419db4f8924..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/spans_example.png and /dev/null differ diff --git a/next_docs/en/_static/image/web_demo_1.png b/next_docs/en/_static/image/web_demo_1.png deleted file mode 100644 index 04adff2686572f05c5f5edfa039a45ab8a5d7736..0000000000000000000000000000000000000000 Binary files a/next_docs/en/_static/image/web_demo_1.png and /dev/null differ diff --git a/next_docs/en/additional_notes/faq.rst b/next_docs/en/additional_notes/faq.rst deleted file mode 100644 index 6f08d334fcd32a69c82690d94b46e81cfde20d53..0000000000000000000000000000000000000000 --- a/next_docs/en/additional_notes/faq.rst +++ /dev/null @@ -1,88 +0,0 @@ -FAQ -========================== - -1. When using the command ``pip install magic-pdf[full]`` on newer versions of macOS, the error ``zsh: no matches found: magic-pdf[full]`` occurs. -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -On macOS, the default shell has switched from Bash to Z shell, which has -special handling logic for certain types of string matching. This can -lead to the “no matches found” error. You can try disabling the globbing -feature in the command line and then run the installation command again. - -.. code:: bash - - setopt no_nomatch - pip install magic-pdf[full] - -2. Encountering the error ``pickle.UnpicklingError: invalid load key, 'v'.`` during use -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This might be due to an incomplete download of the model file. You can -try re-downloading the model file and then try again. Reference: -https://github.com/opendatalab/MinerU/issues/143 - -3. Where should the model files be downloaded and how should the ``/models-dir`` configuration be set? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The path for the model files is configured in “magic-pdf.json”. just -like: - -.. code:: json - - { - "models-dir": "/tmp/models" - } - -This path is an absolute path, not a relative path. You can obtain the -absolute path in the models directory using the “pwd” command. -Reference: -https://github.com/opendatalab/MinerU/issues/155#issuecomment-2230216874 - -4. Encountered the error ``ImportError: libGL.so.1: cannot open shared object file: No such file or directory`` in Ubuntu 22.04 on WSL2 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The ``libgl`` library is missing in Ubuntu 22.04 on WSL2. You can -install the ``libgl`` library with the following command to resolve the -issue: - -.. code:: bash - - sudo apt-get install libgl1-mesa-glx - -Reference: https://github.com/opendatalab/MinerU/issues/388 - -5. Encountered error ``ModuleNotFoundError: No module named 'fairscale'`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You need to uninstall the module and reinstall it: - -.. code:: bash - - pip uninstall fairscale - pip install fairscale - -Reference: https://github.com/opendatalab/MinerU/issues/411 - -6. On some newer devices like the H100, the text parsed during OCR using CUDA acceleration is garbled. -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The compatibility of cuda11 with new graphics cards is poor, and the -CUDA version used by Paddle needs to be upgraded. - -.. code:: bash - - pip install paddlepaddle-gpu==3.0.0b1 -i https://www.paddlepaddle.org.cn/packages/stable/cu123/ - -Reference: https://github.com/opendatalab/MinerU/issues/558 - - -7. On some Linux servers, the program immediately reports an error ``Illegal instruction (core dumped)`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This might be because the server's CPU does not support the AVX/AVX2 -instruction set, or the CPU itself supports it but has been disabled by -the system administrator. You can try contacting the system -administrator to remove the restriction or change to a different server. - -References: https://github.com/opendatalab/MinerU/issues/591 , -https://github.com/opendatalab/MinerU/issues/736 diff --git a/next_docs/en/additional_notes/glossary.rst b/next_docs/en/additional_notes/glossary.rst deleted file mode 100644 index 8f3b54915e4a4f558590eb06c7bc4331ccde2397..0000000000000000000000000000000000000000 --- a/next_docs/en/additional_notes/glossary.rst +++ /dev/null @@ -1,14 +0,0 @@ - - -Glossary -=========== - -1. jsonl - Newline-delimited (\n), and each line must be a valid, independent JSON object. - Currently, All the function shipped with **MinerU** assume that json object must contain one field named with either **path** or **file_location** - - -2. magic-pdf.json - TODO - - diff --git a/next_docs/en/additional_notes/known_issues.rst b/next_docs/en/additional_notes/known_issues.rst deleted file mode 100644 index 7542bc514c76c1284c8b551a72876dac20d60767..0000000000000000000000000000000000000000 --- a/next_docs/en/additional_notes/known_issues.rst +++ /dev/null @@ -1,20 +0,0 @@ -Known Issues -============ - -- Reading order is determined by the model based on the spatial - distribution of readable content, and may be out of order in some - areas under extremely complex layouts. -- Vertical text is not supported. -- Tables of contents and lists are recognized through rules, and some - uncommon list formats may not be recognized. -- Only one level of headings is supported; hierarchical headings are - not currently supported. -- Code blocks are not yet supported in the layout model. -- Comic books, art albums, primary school textbooks, and exercises - cannot be parsed well. -- Table recognition may result in row/column recognition errors in - complex tables. -- OCR recognition may produce inaccurate characters in PDFs of - lesser-known languages (e.g., diacritical marks in Latin script, - easily confused characters in Arabic script). -- Some formulas may not render correctly in Markdown. \ No newline at end of file diff --git a/next_docs/en/api.rst b/next_docs/en/api.rst deleted file mode 100644 index efdbf56717c01bcf3af8ca5f7840fc2254bb613b..0000000000000000000000000000000000000000 --- a/next_docs/en/api.rst +++ /dev/null @@ -1,11 +0,0 @@ - -.. toctree:: - :maxdepth: 2 - - api/dataset - api/data_reader_writer - api/read_api - api/schemas - api/io - api/pipe_operators - api/model_operators \ No newline at end of file diff --git a/next_docs/en/api/data_reader_writer.rst b/next_docs/en/api/data_reader_writer.rst deleted file mode 100644 index af1df677ef29f30915762e0a2c1dc181eb147c6b..0000000000000000000000000000000000000000 --- a/next_docs/en/api/data_reader_writer.rst +++ /dev/null @@ -1,44 +0,0 @@ - -Data Reader Writer -=================== - -.. autoclass:: magic_pdf.data.data_reader_writer.DataReader - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.data_reader_writer.DataWriter - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.data_reader_writer.S3DataReader - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.data_reader_writer.S3DataWriter - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.data_reader_writer.FileBasedDataReader - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.data_reader_writer.FileBasedDataWriter - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.data_reader_writer.MultiBucketS3DataReader - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.data_reader_writer.MultiBucketS3DataWriter - :members: - :inherited-members: - :show-inheritance: - diff --git a/next_docs/en/api/dataset.rst b/next_docs/en/api/dataset.rst deleted file mode 100644 index 20ec8ce98a353a83f59c49f4afa7d8a63426c4d5..0000000000000000000000000000000000000000 --- a/next_docs/en/api/dataset.rst +++ /dev/null @@ -1,28 +0,0 @@ -Dataset -======== - -.. autoclass:: magic_pdf.data.dataset.PageableData - :members: - :inherited-members: - :show-inheritance: - - -.. autoclass:: magic_pdf.data.dataset.Dataset - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.dataset.ImageDataset - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.dataset.PymuDocDataset - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.dataset.Doc - :members: - :inherited-members: - :show-inheritance: diff --git a/next_docs/en/api/io.rst b/next_docs/en/api/io.rst deleted file mode 100644 index ac3dd98d9a2c6d106763bf4dd1276e5a4347cd5b..0000000000000000000000000000000000000000 --- a/next_docs/en/api/io.rst +++ /dev/null @@ -1,33 +0,0 @@ -IO -== - -.. autoclass:: magic_pdf.data.io.base.IOReader - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.io.base.IOWriter - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.io.s3.S3Reader - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.io.s3.S3Writer - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.io.http.HttpReader - :members: - :inherited-members: - :show-inheritance: - -.. autoclass:: magic_pdf.data.io.http.HttpWriter - :members: - :inherited-members: - :show-inheritance: - diff --git a/next_docs/en/api/model_operators.rst b/next_docs/en/api/model_operators.rst deleted file mode 100644 index 7f62632d494e2facf78ccf2eab5922cc2aa87f62..0000000000000000000000000000000000000000 --- a/next_docs/en/api/model_operators.rst +++ /dev/null @@ -1,8 +0,0 @@ - -Model Api -========== - -.. autoclass:: magic_pdf.operators.InferenceResultBase - :members: - :inherited-members: - :show-inheritance: diff --git a/next_docs/en/api/pipe_operators.rst b/next_docs/en/api/pipe_operators.rst deleted file mode 100644 index 52b0b9d892f85a72cc9155d1d8dbdd392eedca27..0000000000000000000000000000000000000000 --- a/next_docs/en/api/pipe_operators.rst +++ /dev/null @@ -1,9 +0,0 @@ - - -Pipeline Api -============= - -.. autoclass:: magic_pdf.operators.pipes.PipeResult - :members: - :inherited-members: - :show-inheritance: diff --git a/next_docs/en/api/read_api.rst b/next_docs/en/api/read_api.rst deleted file mode 100644 index 661630893ec897dc45a1bca8b6c5ae245263d6fa..0000000000000000000000000000000000000000 --- a/next_docs/en/api/read_api.rst +++ /dev/null @@ -1,6 +0,0 @@ -read_api -========= - -.. automodule:: magic_pdf.data.read_api - :members: - :inherited-members: diff --git a/next_docs/en/api/schemas.rst b/next_docs/en/api/schemas.rst deleted file mode 100644 index 03a180050958491b3918b62c7d42e5e9354f1d4d..0000000000000000000000000000000000000000 --- a/next_docs/en/api/schemas.rst +++ /dev/null @@ -1,10 +0,0 @@ - -schemas -=========== - -.. autopydantic_model:: magic_pdf.data.schemas.S3Config - :members: - -.. autopydantic_model:: magic_pdf.data.schemas.PageInfo - :members: - diff --git a/next_docs/en/conf.py b/next_docs/en/conf.py deleted file mode 100644 index 857ef27e88b60884afd2e5806dd1c6a911ffd59c..0000000000000000000000000000000000000000 --- a/next_docs/en/conf.py +++ /dev/null @@ -1,151 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. - -import os -import subprocess -import sys - -from sphinx.ext import autodoc -from docutils import nodes -from docutils.parsers.rst import Directive - -def install(package): - subprocess.check_call([sys.executable, '-m', 'pip', 'install', package]) - - -requirements_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'requirements.txt')) -if os.path.exists(requirements_path): - with open(requirements_path) as f: - packages = f.readlines() - for package in packages: - install(package.strip()) - -sys.path.insert(0, os.path.abspath('../..')) - -# -- Project information ----------------------------------------------------- - -project = 'MinerU' -copyright = '2024, MinerU Contributors' -author = 'OpenDataLab' - -# The full version, including alpha/beta/rc tags -version_file = '../../magic_pdf/libs/version.py' -with open(version_file) as f: - exec(compile(f.read(), version_file, 'exec')) -__version__ = locals()['__version__'] -# The short X.Y version -version = __version__ -# The full version, including alpha/beta/rc tags -release = __version__ - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.napoleon', - 'sphinx.ext.viewcode', - 'sphinx.ext.intersphinx', - 'sphinx_copybutton', - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.inheritance_diagram', - 'myst_parser', - 'sphinxarg.ext', - 'sphinxcontrib.autodoc_pydantic', -] - -# class hierarchy diagram -inheritance_graph_attrs = dict(rankdir="LR", size='"8.0, 12.0"', fontsize=14, ratio='compress') -inheritance_node_attrs = dict(shape='ellipse', fontsize=14, height=0.75) -inheritance_edge_attrs = dict(arrow='vee') - -autodoc_pydantic_model_show_json = True -autodoc_pydantic_model_show_config_summary = False - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# Exclude the prompt "$" when copying code -copybutton_prompt_text = r'\$ ' -copybutton_prompt_is_regexp = True - -language = 'en' - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'sphinx_book_theme' -html_logo = '_static/image/logo.png' -html_theme_options = { - 'path_to_docs': 'next_docs/en', - 'repository_url': 'https://github.com/opendatalab/MinerU', - 'use_repository_button': True, -} -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] - -# Mock out external dependencies here. -autodoc_mock_imports = [ - 'cpuinfo', - 'torch', - 'transformers', - 'psutil', - 'prometheus_client', - 'sentencepiece', - 'vllm.cuda_utils', - 'vllm._C', - # 'numpy', - 'tqdm', -] - - -class MockedClassDocumenter(autodoc.ClassDocumenter): - """Remove note about base class when a class is derived from object.""" - - def add_line(self, line: str, source: str, *lineno: int) -> None: - if line == ' Bases: :py:class:`object`': - return - super().add_line(line, source, *lineno) - - -autodoc.ClassDocumenter = MockedClassDocumenter - -navigation_with_keys = False - - -# add custom directive - - -class VideoDirective(Directive): - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = True - option_spec = {} - - def run(self): - url = self.arguments[0] - video_node = nodes.raw('', f'', format='html') - return [video_node] - -def setup(app): - app.add_directive('video', VideoDirective) \ No newline at end of file diff --git a/next_docs/en/index.rst b/next_docs/en/index.rst deleted file mode 100644 index 3c983fbbbf40a2a461d3faf53c293abf0847f7db..0000000000000000000000000000000000000000 --- a/next_docs/en/index.rst +++ /dev/null @@ -1,111 +0,0 @@ -.. xtuner documentation master file, created by - sphinx-quickstart on Tue Jan 9 16:33:06 2024. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to the MinerU Documentation -============================================== - -.. figure:: ./_static/image/logo.png - :align: center - :alt: mineru - :class: no-scaled-link - -.. raw:: html - -

    - A one-stop, open-source, high-quality data extraction tool - -

    - -

    - - Star - Watch - Fork -

    - - -Project Introduction --------------------- - -MinerU is a tool that converts PDFs into machine-readable formats (e.g., -markdown, JSON), allowing for easy extraction into any format. MinerU -was born during the pre-training process of -`InternLM `__. We focus on solving -symbol conversion issues in scientific literature and hope to contribute -to technological development in the era of large models. Compared to -well-known commercial products, MinerU is still young. If you encounter -any issues or if the results are not as expected, please submit an issue -on `issue `__ and **attach -the relevant PDF**. - -.. video:: https://github.com/user-attachments/assets/4bea02c9-6d54-4cd6-97ed-dff14340982c - - -Key Features ------------- - -- Remove headers, footers, footnotes, page numbers, etc., to ensure - semantic coherence. -- Output text in human-readable order, suitable for single-column, - multi-column, and complex layouts. -- Preserve the structure of the original document, including headings, - paragraphs, lists, etc. -- Extract images, image descriptions, tables, table titles, and - footnotes. -- Automatically recognize and convert formulas in the document to LaTeX - format. -- Automatically recognize and convert tables in the document to LaTeX - or HTML format. -- Automatically detect scanned PDFs and garbled PDFs and enable OCR - functionality. -- OCR supports detection and recognition of 84 languages. -- Supports multiple output formats, such as multimodal and NLP - Markdown, JSON sorted by reading order, and rich intermediate - formats. -- Supports various visualization results, including layout - visualization and span visualization, for efficient confirmation of - output quality. -- Supports both CPU and GPU environments. -- Compatible with Windows, Linux, and Mac platforms. - - -.. tip:: - - Get started with MinerU by trying the `online demo `_ or :doc:`installing it locally `. - - -User Guide -------------- -.. toctree:: - :maxdepth: 2 - :caption: User Guide - - user_guide - - -API Reference -------------- - -If you are looking for information on a specific function, class or -method, this part of the documentation is for you. - -.. toctree:: - :maxdepth: 2 - :caption: API - - api - - -Additional Notes ------------------- -.. toctree:: - :maxdepth: 1 - :caption: Additional Notes - - additional_notes/known_issues - additional_notes/faq - additional_notes/glossary - - diff --git a/next_docs/en/make.bat b/next_docs/en/make.bat deleted file mode 100644 index 954237b9b9f2b248bb1397a15c055c0af1cad03e..0000000000000000000000000000000000000000 --- a/next_docs/en/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=_build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/next_docs/en/user_guide.rst b/next_docs/en/user_guide.rst deleted file mode 100644 index 398513d32da411f943a540d40c005d993091af03..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide.rst +++ /dev/null @@ -1,12 +0,0 @@ - - -.. toctree:: - :maxdepth: 2 - - user_guide/install - user_guide/usage - user_guide/quick_start - user_guide/tutorial - user_guide/data - user_guide/inference_result - user_guide/pipe_result diff --git a/next_docs/en/user_guide/data.rst b/next_docs/en/user_guide/data.rst deleted file mode 100644 index a418ab5614fd67e4e8e22d5030cf45c1c993469c..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/data.rst +++ /dev/null @@ -1,19 +0,0 @@ - - -Data -========= - -.. toctree:: - :maxdepth: 2 - - data/dataset - - data/read_api - - data/data_reader_writer - - data/io - - - - diff --git a/next_docs/en/user_guide/data/data_reader_writer.rst b/next_docs/en/user_guide/data/data_reader_writer.rst deleted file mode 100644 index 4056ba86560e006c5945bc3e337203242ffecb4b..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/data/data_reader_writer.rst +++ /dev/null @@ -1,236 +0,0 @@ - -Data Reader Writer -==================== - -Aims for read or write bytes from different media, You can implement new classes to meet the needs of your personal scenarios -if MinerU have not provide the suitable classes. It is easy to implement new classes, the only one requirement is to inherit from -``DataReader`` or ``DataWriter`` - -.. code:: python - - class SomeReader(DataReader): - def read(self, path: str) -> bytes: - pass - - def read_at(self, path: str, offset: int = 0, limit: int = -1) -> bytes: - pass - - - class SomeWriter(DataWriter): - def write(self, path: str, data: bytes) -> None: - pass - - def write_string(self, path: str, data: str) -> None: - pass - - -Reader may curious about the difference between :doc:`io` and this section. Those two sections look very similarity at first glance. -:doc:`io` provides fundamental functions, while This section thinks more at application level. Customer can build they own classes to meet -their own applications need which may share same IO function. That is why we have :doc:`io`. - - -Important Classes ------------------ - -.. code:: python - - class FileBasedDataReader(DataReader): - def __init__(self, parent_dir: str = ''): - pass - - - class FileBasedDataWriter(DataWriter): - def __init__(self, parent_dir: str = '') -> None: - pass - -Class ``FileBasedDataReader`` initialized with unary param ``parent_dir``, That means that every method ``FileBasedDataReader`` provided will have features as follow. - -Features: - #. read content from the absolute path file, ``parent_dir`` will be ignored. - #. read the relative path, file will first join with ``parent_dir``, then read content from the merged path - - -.. note:: - - ``FileBasedDataWriter`` shares the same behavior with ``FileBaseDataReader`` - - -.. code:: python - - class MultiS3Mixin: - def __init__(self, default_prefix: str, s3_configs: list[S3Config]): - pass - - class MultiBucketS3DataReader(DataReader, MultiS3Mixin): - pass - -All read-related method that class ``MultiBucketS3DataReader`` provided will have features as follow. - -Features: - #. read object with full s3-format path, for example ``s3://test_bucket/test_object``, ``default_prefix`` will be ignored. - #. read object with relative path, file will join ``default_prefix`` and trim the ``bucket_name`` firstly, then read the content. ``bucket_name`` is the first element of the result after split ``default_prefix`` with delimiter ``\`` - -.. note:: - ``MultiBucketS3DataWriter`` shares the same behavior with ``MultiBucketS3DataReader`` - - -.. code:: python - - class S3DataReader(MultiBucketS3DataReader): - pass - -``S3DataReader`` is build on top of MultiBucketS3DataReader which only support for bucket. So is ``S3DataWriter``. - - -Read Examples ------------- - -.. code:: python - - import os - from magic_pdf.data.data_reader_writer import * - from magic_pdf.data.data_reader_writer import MultiBucketS3DataReader - from magic_pdf.data.schemas import S3Config - - # file based related - file_based_reader1 = FileBasedDataReader('') - - ## will read file abc - file_based_reader1.read('abc') - - file_based_reader2 = FileBasedDataReader('/tmp') - - ## will read /tmp/abc - file_based_reader2.read('abc') - - ## will read /tmp/logs/message.txt - file_based_reader2.read('/tmp/logs/message.txt') - - # multi bucket s3 releated - bucket = "bucket" # replace with real bucket - ak = "ak" # replace with real access key - sk = "sk" # replace with real secret key - endpoint_url = "endpoint_url" # replace with real endpoint_url - - bucket_2 = "bucket_2" # replace with real bucket - ak_2 = "ak_2" # replace with real access key - sk_2 = "sk_2" # replace with real secret key - endpoint_url_2 = "endpoint_url_2" # replace with real endpoint_url - - test_prefix = 'test/unittest' - multi_bucket_s3_reader1 = MultiBucketS3DataReader(f"{bucket}/{test_prefix}", [S3Config( - bucket_name=bucket, access_key=ak, secret_key=sk, endpoint_url=endpoint_url - ), - S3Config( - bucket_name=bucket_2, - access_key=ak_2, - secret_key=sk_2, - endpoint_url=endpoint_url_2, - )]) - - ## will read s3://{bucket}/{test_prefix}/abc - multi_bucket_s3_reader1.read('abc') - - ## will read s3://{bucket}/{test_prefix}/efg - multi_bucket_s3_reader1.read(f's3://{bucket}/{test_prefix}/efg') - - ## will read s3://{bucket2}/{test_prefix}/abc - multi_bucket_s3_reader1.read(f's3://{bucket_2}/{test_prefix}/abc') - - # s3 related - s3_reader1 = S3DataReader( - test_prefix, - bucket, - ak, - sk, - endpoint_url - ) - - ## will read s3://{bucket}/{test_prefix}/abc - s3_reader1.read('abc') - - ## will read s3://{bucket}/efg - s3_reader1.read(f's3://{bucket}/efg') - - -Write Examples ---------------- - -.. code:: python - - import os - from magic_pdf.data.data_reader_writer import * - from magic_pdf.data.data_reader_writer import MultiBucketS3DataWriter - from magic_pdf.data.schemas import S3Config - - # file based related - file_based_writer1 = FileBasedDataWriter("") - - ## will write 123 to abc - file_based_writer1.write("abc", "123".encode()) - - ## will write 123 to abc - file_based_writer1.write_string("abc", "123") - - file_based_writer2 = FileBasedDataWriter("/tmp") - - ## will write 123 to /tmp/abc - file_based_writer2.write_string("abc", "123") - - ## will write 123 to /tmp/logs/message.txt - file_based_writer2.write_string("/tmp/logs/message.txt", "123") - - # multi bucket s3 releated - bucket = "bucket" # replace with real bucket - ak = "ak" # replace with real access key - sk = "sk" # replace with real secret key - endpoint_url = "endpoint_url" # replace with real endpoint_url - - bucket_2 = "bucket_2" # replace with real bucket - ak_2 = "ak_2" # replace with real access key - sk_2 = "sk_2" # replace with real secret key - endpoint_url_2 = "endpoint_url_2" # replace with real endpoint_url - - test_prefix = "test/unittest" - multi_bucket_s3_writer1 = MultiBucketS3DataWriter( - f"{bucket}/{test_prefix}", - [ - S3Config( - bucket_name=bucket, access_key=ak, secret_key=sk, endpoint_url=endpoint_url - ), - S3Config( - bucket_name=bucket_2, - access_key=ak_2, - secret_key=sk_2, - endpoint_url=endpoint_url_2, - ), - ], - ) - - ## will write 123 to s3://{bucket}/{test_prefix}/abc - multi_bucket_s3_writer1.write_string("abc", "123") - - ## will write 123 to s3://{bucket}/{test_prefix}/abc - multi_bucket_s3_writer1.write("abc", "123".encode()) - - ## will write 123 to s3://{bucket}/{test_prefix}/efg - multi_bucket_s3_writer1.write(f"s3://{bucket}/{test_prefix}/efg", "123".encode()) - - ## will write 123 to s3://{bucket_2}/{test_prefix}/abc - multi_bucket_s3_writer1.write(f's3://{bucket_2}/{test_prefix}/abc', '123'.encode()) - - # s3 related - s3_writer1 = S3DataWriter(test_prefix, bucket, ak, sk, endpoint_url) - - ## will write 123 to s3://{bucket}/{test_prefix}/abc - s3_writer1.write("abc", "123".encode()) - - ## will write 123 to s3://{bucket}/{test_prefix}/abc - s3_writer1.write_string("abc", "123") - - ## will write 123 to s3://{bucket}/efg - s3_writer1.write(f"s3://{bucket}/efg", "123".encode()) - - - -Check :doc:`../../api/data_reader_writer` for more details diff --git a/next_docs/en/user_guide/data/dataset.rst b/next_docs/en/user_guide/data/dataset.rst deleted file mode 100644 index 51fc40d35b8893800de576984d2f297b81d7c0db..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/data/dataset.rst +++ /dev/null @@ -1,40 +0,0 @@ - - -Dataset -=========== - - -Import Classes ------------------ - -Dataset -^^^^^^^^ - -Each pdfs or image will form one ``Dataset``. As we all know, Pdf has two categories, :ref:`digital_method_section` or :ref:`ocr_method_section`. -Will get ``ImageDataset`` which is subclass of ``Dataset`` with images and get ``PymuDocDataset`` from pdf files. -The difference between ``ImageDataset`` and ``PymuDocDataset`` is that ``ImageDataset`` only support ``OCR`` parse method, -while ``PymuDocDataset`` support both ``OCR`` and ``TXT`` - -.. note:: - - In fact some pdf may generated by images, that means it can not support ``TXT`` methods. Currently it is something the user needs to ensure does not happen - - - -Pdf Parse Methods ------------------- - -.. _ocr_method_section: -OCR -^^^^ -Extract chars via ``Optical Character Recognition`` technical. - -.. _digital_method_section: -TXT -^^^^^^^^ -Extract chars via third-party library, currently we use ``pymupdf``. - - - -Check :doc:`../../api/dataset` for more details - diff --git a/next_docs/en/user_guide/data/io.rst b/next_docs/en/user_guide/data/io.rst deleted file mode 100644 index 01285682a5865780f0ff634470f1fb02844f1f51..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/data/io.rst +++ /dev/null @@ -1,25 +0,0 @@ - -IO -=== - -Aims for read or write bytes from different media, Currently We provide ``S3Reader``, ``S3Writer`` for AWS S3 compatible media -and ``HttpReader``, ``HttpWriter`` for remote Http file. You can implement new classes to meet the needs of your personal scenarios -if MinerU have not provide the suitable classes. It is easy to implement new classes, the only one requirement is to inherit from -``IOReader`` or ``IOWriter`` - -.. code:: python - - class SomeReader(IOReader): - def read(self, path: str) -> bytes: - pass - - def read_at(self, path: str, offset: int = 0, limit: int = -1) -> bytes: - pass - - - class SomeWriter(IOWriter): - def write(self, path: str, data: bytes) -> None: - pass - -Check :doc:`../../api/io` for more details - diff --git a/next_docs/en/user_guide/data/read_api.rst b/next_docs/en/user_guide/data/read_api.rst deleted file mode 100644 index bdb005252d1fdc76c77e1697289bba65268e86a9..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/data/read_api.rst +++ /dev/null @@ -1,106 +0,0 @@ - -read_api -========== - -Read the content from file or directory to create ``Dataset``, Currently we provided serval functions that cover some scenarios. -if you have new scenarios that is common to most of the users, you can post it on the offical github issues with detail descriptions. -Also it is easy to implement your own read-related funtions. - - -Important Functions -------------------- - - -read_jsonl -^^^^^^^^^^^^^^^^ - -Read the contet from jsonl which may located on local machine or remote s3. if you want to know more about jsonl, please goto :doc:`../../additional_notes/glossary` - -.. code:: python - - from magic_pdf.data.read_api import * - from magic_pdf.data.data_reader_writer import MultiBucketS3DataReader - from magic_pdf.data.schemas import S3Config - - # read jsonl from local machine - datasets = read_jsonl("tt.jsonl", None) # replace with real jsonl file - - # read jsonl from remote s3 - - bucket = "bucket_1" # replace with real s3 bucket - ak = "access_key_1" # replace with real s3 access key - sk = "secret_key_1" # replace with real s3 secret key - endpoint_url = "endpoint_url_1" # replace with real s3 endpoint url - - bucket_2 = "bucket_2" # replace with real s3 bucket - ak_2 = "access_key_2" # replace with real s3 access key - sk_2 = "secret_key_2" # replace with real s3 secret key - endpoint_url_2 = "endpoint_url_2" # replace with real s3 endpoint url - - s3configs = [ - S3Config( - bucket_name=bucket, access_key=ak, secret_key=sk, endpoint_url=endpoint_url - ), - S3Config( - bucket_name=bucket_2, - access_key=ak_2, - secret_key=sk_2, - endpoint_url=endpoint_url_2, - ), - ] - - s3_reader = MultiBucketS3DataReader(bucket, s3configs) - - datasets = read_jsonl(f"s3://bucket_1/tt.jsonl", s3_reader) # replace with real s3 jsonl file - -read_local_pdfs -^^^^^^^^^^^^^^^^^ - -Read pdf from path or directory. - - -.. code:: python - - from magic_pdf.data.read_api import * - - # read pdf path - datasets = read_local_pdfs("tt.pdf") - - # read pdfs under directory - datasets = read_local_pdfs("pdfs/") - - -read_local_images -^^^^^^^^^^^^^^^^^^^ - -Read images from path or directory - -.. code:: python - - from magic_pdf.data.read_api import * - - # read from image path - datasets = read_local_images("tt.png") # replace with real file path - - # read files from directory that endswith suffix in suffixes array - datasets = read_local_images("images/", suffixes=[".png", ".jpg"]) # replace with real directory - - -read_local_office -^^^^^^^^^^^^^^^^^^^^ -Read MS-Office files from path or directory - -.. code:: python - - from magic_pdf.data.read_api import * - - # read from image path - datasets = read_local_office("tt.doc") # replace with real file path - - # read files from directory that endswith suffix in suffixes array - datasets = read_local_office("docs/") # replace with real directory - - - - -Check :doc:`../../api/read_api` for more details \ No newline at end of file diff --git a/next_docs/en/user_guide/inference_result.rst b/next_docs/en/user_guide/inference_result.rst deleted file mode 100644 index 86a78f14fccfda0431428fe1783bbddab0a544eb..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/inference_result.rst +++ /dev/null @@ -1,144 +0,0 @@ - -Inference Result -================== - -.. admonition:: Tip - :class: tip - - Please first navigate to :doc:`tutorial/pipeline` to get an initial understanding of how the pipeline works; this will help in understanding the content of this section. - -The **InferenceResult** class is a container for storing model inference results and implements a series of methods related to these results, such as draw_model, dump_model. -Checkout :doc:`../api/model_operators` for more details about **InferenceResult** - - -Model Inference Result ------------------------ - -Structure Definition -^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code:: python - - from pydantic import BaseModel, Field - from enum import IntEnum - - class CategoryType(IntEnum): - title = 0 # Title - plain_text = 1 # Text - abandon = 2 # Includes headers, footers, page numbers, and page annotations - figure = 3 # Image - figure_caption = 4 # Image description - table = 5 # Table - table_caption = 6 # Table description - table_footnote = 7 # Table footnote - isolate_formula = 8 # Block formula - formula_caption = 9 # Formula label - - embedding = 13 # Inline formula - isolated = 14 # Block formula - text = 15 # OCR recognition result - - - class PageInfo(BaseModel): - page_no: int = Field(description="Page number, the first page is 0", ge=0) - height: int = Field(description="Page height", gt=0) - width: int = Field(description="Page width", ge=0) - - class ObjectInferenceResult(BaseModel): - category_id: CategoryType = Field(description="Category", ge=0) - poly: list[float] = Field(description="Quadrilateral coordinates, representing the coordinates of the top-left, top-right, bottom-right, and bottom-left points respectively") - score: float = Field(description="Confidence of the inference result") - latex: str | None = Field(description="LaTeX parsing result", default=None) - html: str | None = Field(description="HTML parsing result", default=None) - - class PageInferenceResults(BaseModel): - layout_dets: list[ObjectInferenceResult] = Field(description="Page recognition results", ge=0) - page_info: PageInfo = Field(description="Page metadata") - - -Example -^^^^^^^^^^^ - -.. code:: json - - [ - { - "layout_dets": [ - { - "category_id": 2, - "poly": [ - 99.1906967163086, - 100.3119125366211, - 730.3707885742188, - 100.3119125366211, - 730.3707885742188, - 245.81326293945312, - 99.1906967163086, - 245.81326293945312 - ], - "score": 0.9999997615814209 - } - ], - "page_info": { - "page_no": 0, - "height": 2339, - "width": 1654 - } - }, - { - "layout_dets": [ - { - "category_id": 5, - "poly": [ - 99.13092803955078, - 2210.680419921875, - 497.3183898925781, - 2210.680419921875, - 497.3183898925781, - 2264.78076171875, - 99.13092803955078, - 2264.78076171875 - ], - "score": 0.9999997019767761 - } - ], - "page_info": { - "page_no": 1, - "height": 2339, - "width": 1654 - } - } - ] - -The format of the poly coordinates is [x0, y0, x1, y1, x2, y2, x3, y3], -representing the coordinates of the top-left, top-right, bottom-right, -and bottom-left points respectively. |Poly Coordinate Diagram| - - - -Inference Result -------------------------- - - -.. code:: python - - from magic_pdf.operators.models import InferenceResult - from magic_pdf.data.dataset import Dataset - - dataset : Dataset = some_data_set # not real dataset - - # The inference results of all pages, ordered by page number, are stored in a list as the inference results of MinerU - model_inference_result: list[PageInferenceResults] = [] - - Inference_result = InferenceResult(model_inference_result, dataset) - - - -some_model.pdf -^^^^^^^^^^^^^^^^^^^^ - -.. figure:: ../_static/image/inference_result.png - - - -.. |Poly Coordinate Diagram| image:: ../_static/image/poly.png diff --git a/next_docs/en/user_guide/install.rst b/next_docs/en/user_guide/install.rst deleted file mode 100644 index e1eb30301ec3bc704cd925a812dbcfb995cd94b7..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/install.rst +++ /dev/null @@ -1,12 +0,0 @@ - -Installation -============== - -.. toctree:: - :maxdepth: 1 - - install/install - install//boost_with_cuda - install/download_model_weight_files - install/config - diff --git a/next_docs/en/user_guide/install/boost_with_cuda.rst b/next_docs/en/user_guide/install/boost_with_cuda.rst deleted file mode 100644 index 40f0580a44e90c01c461c90286db553f0ad56f1d..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/install/boost_with_cuda.rst +++ /dev/null @@ -1,255 +0,0 @@ - -Boost With Cuda -================ - - -If your device supports CUDA and meets the GPU requirements of the -mainline environment, you can use GPU acceleration. Please select the -appropriate guide based on your system: - -- :ref:`ubuntu_22_04_lts_section` -- :ref:`windows_10_or_11_section` - - -.. _ubuntu_22_04_lts_section: - -Ubuntu 22.04 LTS ------------------ - -1. Check if NVIDIA Drivers Are Installed -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code:: sh - - nvidia-smi - -If you see information similar to the following, it means that the -NVIDIA drivers are already installed, and you can skip Step 2. - -.. note:: - - ``CUDA Version`` should be >= 12.4, If the displayed version number is less than 12.4, please upgrade the driver. - -.. code:: text - - +---------------------------------------------------------------------------------------+ - | NVIDIA-SMI 570.133.07 Driver Version: 572.83 CUDA Version: 12.8 | - |-----------------------------------------+----------------------+----------------------+ - | GPU Name TCC/WDDM | Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | - | | | MIG M. | - |=========================================+======================+======================| - | 0 NVIDIA GeForce RTX 3060 Ti WDDM | 00000000:01:00.0 On | N/A | - | 0% 51C P8 12W / 200W | 1489MiB / 8192MiB | 5% Default | - | | | N/A | - +-----------------------------------------+----------------------+----------------------+ - -2. Install the Driver -~~~~~~~~~~~~~~~~~~~~~ - -If no driver is installed, use the following command: - -.. code:: sh - - sudo apt-get update - sudo apt-get install nvidia-driver-570-server - -Install the proprietary driver and restart your computer after -installation. - -.. code:: sh - - reboot - -3. Install Anaconda -~~~~~~~~~~~~~~~~~~~ - -If Anaconda is already installed, skip this step. - -.. code:: sh - - wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh - bash Anaconda3-2024.06-1-Linux-x86_64.sh - -In the final step, enter ``yes``, close the terminal, and reopen it. - -4. Create an Environment Using Conda -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Specify Python version 3.10~3.13. - -.. code:: sh - - conda create -n mineru 'python=3.12' -y - conda activate mineru - -5. Install Applications -~~~~~~~~~~~~~~~~~~~~~~~ - -.. code:: sh - - pip install -U magic-pdf[full] - -.. admonition:: TIP - :class: tip - - After installation, you can check the version of ``magic-pdf`` using the following command: - -.. code:: sh - - magic-pdf --version - - -6. Download Models -~~~~~~~~~~~~~~~~~~ - -Refer to detailed instructions on :doc:`download_model_weight_files` - -7. Understand the Location of the Configuration File -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -After completing the `6. Download Models <#6-download-models>`__ step, -the script will automatically generate a ``magic-pdf.json`` file in the -user directory and configure the default model path. You can find the -``magic-pdf.json`` file in your user directory. - -.. admonition:: TIP - :class: tip - - The user directory for Linux is “/home/username”. - -8. First Run -~~~~~~~~~~~~ - -Download a sample file from the repository and test it. - -.. code:: sh - - wget https://github.com/opendatalab/MinerU/raw/master/demo/pdfs/small_ocr.pdf - magic-pdf -p small_ocr.pdf -o ./output - -9. Test CUDA Acceleration -~~~~~~~~~~~~~~~~~~~~~~~~~ - -If your graphics card has at least **8GB** of VRAM, follow these steps -to test CUDA acceleration: - -1. Modify the value of ``"device-mode"`` in the ``magic-pdf.json`` - configuration file located in your home directory. - - .. code:: json - - { - "device-mode": "cuda" - } - -2. Test CUDA acceleration with the following command: - - .. code:: sh - - magic-pdf -p small_ocr.pdf -o ./output - - -.. _windows_10_or_11_section: - -Windows 10/11 --------------- - -1. Install CUDA -~~~~~~~~~~~~~~~~~~~~~~~~~ - -You need to install a CUDA version that is compatible with torch's requirements. For details, please refer to the [official PyTorch website](https://pytorch.org/get-started/locally/). - -- CUDA 11.8 https://developer.nvidia.com/cuda-11-8-0-download-archive -- CUDA 12.4 https://developer.nvidia.com/cuda-12-4-0-download-archive -- CUDA 12.6 https://developer.nvidia.com/cuda-12-6-0-download-archive -- CUDA 12.8 https://developer.nvidia.com/cuda-12-8-0-download-archive - - -2. Install Anaconda -~~~~~~~~~~~~~~~~~~~ - -If Anaconda is already installed, you can skip this step. - -Download link: https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Windows-x86_64.exe - -3. Create an Environment Using Conda -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - conda create -n mineru 'python=3.12' -y - conda activate mineru - -4. Install Applications -~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - pip install -U magic-pdf[full] - -.. admonition:: Tip - :class: tip - - After installation, you can check the version of ``magic-pdf``: - - .. code:: bash - - magic-pdf --version - - -5. Download Models -~~~~~~~~~~~~~~~~~~ - -Refer to detailed instructions on :doc:`download_model_weight_files` - -6. Understand the Location of the Configuration File -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -After completing the `5. Download Models <#5-download-models>`__ step, -the script will automatically generate a ``magic-pdf.json`` file in the -user directory and configure the default model path. You can find the -``magic-pdf.json`` file in your 【user directory】 . - -.. admonition:: Tip - :class: tip - - The user directory for Windows is “C:/Users/username”. - -7. First Run -~~~~~~~~~~~~ - -Download a sample file from the repository and test it. - -.. code:: powershell - - wget https://github.com/opendatalab/MinerU/raw/master/demo/pdfs/small_ocr.pdf -O small_ocr.pdf - magic-pdf -p small_ocr.pdf -o ./output - -8. Test CUDA Acceleration -~~~~~~~~~~~~~~~~~~~~~~~~~ - -If your graphics card has at least 8GB of VRAM, follow these steps to -test CUDA-accelerated parsing performance. - -1. **Overwrite the installation of torch and torchvision** supporting CUDA.(Please select the appropriate index-url based on your CUDA version. For more details, refer to the [PyTorch official website](https://pytorch.org/get-started/locally/).) - -.. code:: sh - - pip install --force-reinstall torch torchvision --index-url https://download.pytorch.org/whl/cu124 - - -2. **Modify the value of ``"device-mode"``** in the ``magic-pdf.json`` - configuration file located in your user directory. - - .. code:: json - - { - "device-mode": "cuda" - } - -3. **Run the following command to test CUDA acceleration**: - - :: - - magic-pdf -p small_ocr.pdf -o ./output diff --git a/next_docs/en/user_guide/install/config.rst b/next_docs/en/user_guide/install/config.rst deleted file mode 100644 index 2759a8934c7738db88d0955f0226f114d5ce9d69..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/install/config.rst +++ /dev/null @@ -1,168 +0,0 @@ - - -Config -========= - -File **magic-pdf.json** is typically located in the **${HOME}** directory under a Linux system or in the **C:\Users\{username}** directory under a Windows system. - -.. admonition:: Tip - :class: tip - - You can override the default location of config file via the following command: - - export MINERU_TOOLS_CONFIG_JSON=new_magic_pdf.json - - - -magic-pdf.json ----------------- - -.. code:: json - - { - "bucket_info":{ - "bucket-name-1":["ak", "sk", "endpoint"], - "bucket-name-2":["ak", "sk", "endpoint"] - }, - "models-dir":"/tmp/models", - "layoutreader-model-dir":"/tmp/layoutreader", - "device-mode":"cpu", - "layout-config": { - "model": "doclayout_yolo" - }, - "formula-config": { - "mfd_model": "yolo_v8_mfd", - "mfr_model": "unimernet_small", - "enable": true - }, - "table-config": { - "model": "rapid_table", - "enable": true, - "max_time": 400 - }, - "config_version": "1.0.0" - } - - - - -bucket_info -^^^^^^^^^^^^^^ -Store the access_key, secret_key and endpoint of AWS S3 Compatible storage config - -Example: - -.. code:: text - - { - "image_bucket":[{access_key}, {secret_key}, {endpoint}], - "video_bucket":[{access_key}, {secret_key}, {endpoint}] - } - - -models-dir -^^^^^^^^^^^^ - -Store the models download from **huggingface** or **modelshop**. You do not need to modify this field if you download the model using the scripts shipped with **MinerU** - - -layoutreader-model-dir -^^^^^^^^^^^^^^^^^^^^^^^ - -Store the models download from **huggingface** or **modelshop**. You do not need to modify this field if you download the model using the scripts shipped with **MinerU** - - -devide-mode -^^^^^^^^^^^^^^ - -This field have two options, **cpu** or **cuda**. - -**cpu**: inference via cpu - -**cuda**: using cuda to accelerate inference - - -layout-config -^^^^^^^^^^^^^^^ - -.. code:: json - - { - "model": "doclayout_yolo" - } - -layout model can not be disabled now. - - -formula-config -^^^^^^^^^^^^^^^^ - -.. code:: json - - { - "mfd_model": "yolo_v8_mfd", - "mfr_model": "unimernet_small", - "enable": true - } - - -mfd_model -"""""""""" - -Specify the formula detection model, options are ['yolo_v8_mfd'] - - -mfr_model -"""""""""" -Specify the formula recognition model, options are ['unimernet_small'] - -Check `UniMERNet `_ for more details - - -enable -"""""""" - -on-off flag, options are [true, false]. **true** means enable formula inference, **false** means disable formula inference - - -table-config -^^^^^^^^^^^^^^^^ - -.. code:: json - - { - "model": "rapid_table", - "enable": true, - "max_time": 400 - } - -model -"""""""" - -Specify the table inference model, options are ['rapid_table'] - - -max_time -""""""""" - -Since table recognition is a time-consuming process, we set a timeout period. If the process exceeds this time, the table recognition will be terminated. - - - -enable -""""""" - -on-off flag, options are [true, false]. **true** means enable table inference, **false** means disable table inference - - -config_version -^^^^^^^^^^^^^^^^ - -The version of config schema. - - -.. admonition:: Tip - :class: tip - - Check `Config Schema `_ for the latest details - diff --git a/next_docs/en/user_guide/install/download_model_weight_files.rst b/next_docs/en/user_guide/install/download_model_weight_files.rst deleted file mode 100644 index 446c34423fc70bd96ae43fffb1656206689e615f..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/install/download_model_weight_files.rst +++ /dev/null @@ -1,37 +0,0 @@ - -Download Model Weight Files -============================== - -Model downloads are divided into initial downloads and updates to the -model directory. Please refer to the corresponding documentation for -instructions on how to proceed. - -Initial download of model files ------------------------------- - -1. Download the Model from Hugging Face -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Use a Python Script to Download Model Files from Hugging Face - -.. code:: bash - - pip install huggingface_hub - wget https://github.com/opendatalab/MinerU/raw/master/scripts/download_models_hf.py -O download_models_hf.py - python download_models_hf.py - -The Python script will automatically download the model files and -configure the model directory in the configuration file. - -The configuration file can be found in the user directory, with the -filename ``magic-pdf.json``. - -How to update models previously downloaded ------------------------------------------ - -1. Models downloaded via Hugging Face or Model Scope -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you previously downloaded models via Hugging Face or Model Scope, you -can rerun the Python script used for the initial download. This will -automatically update the model directory to the latest version. diff --git a/next_docs/en/user_guide/install/install.rst b/next_docs/en/user_guide/install/install.rst deleted file mode 100644 index 5e6fdf72ba8b62cc66ab10968a4a64d67db833a1..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/install/install.rst +++ /dev/null @@ -1,142 +0,0 @@ - -Install -=============================================================== -If you encounter any installation issues, please first consult the :doc:`../../additional_notes/faq`. -If the parsing results are not as expected, refer to the :doc:`../../additional_notes/known_issues`. - -Also you can try `online demo `_ without installation. - -.. admonition:: Warning - :class: tip - - **Pre-installation Notice—Hardware and Software Environment Support** - - To ensure the stability and reliability of the project, we only optimize - and test for specific hardware and software environments during - development. This ensures that users deploying and running the project - on recommended system configurations will get the best performance with - the fewest compatibility issues. - - By focusing resources on the mainline environment, our team can more - efficiently resolve potential bugs and develop new features. - - In non-mainline environments, due to the diversity of hardware and - software configurations, as well as third-party dependency compatibility - issues, we cannot guarantee 100% project availability. Therefore, for - users who wish to use this project in non-recommended environments, we - suggest carefully reading the documentation and FAQ first. Most issues - already have corresponding solutions in the FAQ. We also encourage - community feedback to help us gradually expand support. - -.. raw:: html - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Operating System
    Linux after 2019Windows 10 / 11macOS 11+
    CPUx86_64 / arm64x86_64(unsupported ARM Windows)x86_64 / arm64
    Memory Requirements16GB or more, recommended 32GB+
    Storage Requirements20GB or more, with a preference for SSD
    Python Version3.10~3.13
    Nvidia Driver Versionlatest (Proprietary Driver)latestNone
    CUDA EnvironmentRefer to the PyTorch official websiteNone
    CANN Environment(NPU support)8.0+(Ascend 910b)NoneNone
    GPU/MPS Hardware Support ListGPU VRAM 6GB or moreAll GPUs with Tensor Cores produced from Volta(2017) onwards.
    - More than 6GB VRAM
    Apple silicon
    - - - -Create an environment ---------------------------- - -.. code-block:: shell - - conda create -n mineru 'python=3.12' -y - conda activate mineru - pip install -U "magic-pdf[full]" - - -Download model weight files ------------------------------- - -.. code-block:: shell - - pip install huggingface_hub - wget https://github.com/opendatalab/MinerU/raw/master/scripts/download_models_hf.py -O download_models_hf.py - python download_models_hf.py - - - -Install LibreOffice[Optional] ----------------------------------- - -This section is required for handle **doc**, **docx**, **ppt**, **pptx** filetype, You can **skip** this section if no need for those filetype processing. - - -Linux/Macos Platform -"""""""""""""""""""""" - -.. code:: - - apt-get/yum/brew install libreoffice - - -Windows Platform -"""""""""""""""""""" - -.. code:: - - install libreoffice - append "install_dir\LibreOffice\program" to ENVIRONMENT PATH - - -.. tip:: - - The MinerU is installed, Check out :doc:`../usage/command_line` to convert your first pdf **or** reading the following sections for more details about install - - diff --git a/next_docs/en/user_guide/pipe_result.rst b/next_docs/en/user_guide/pipe_result.rst deleted file mode 100644 index 82c36aa882c0b4c92823a801ff6b06e140817319..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/pipe_result.rst +++ /dev/null @@ -1,335 +0,0 @@ - - -Pipe Result -============== - -.. admonition:: Tip - :class: tip - - Please first navigate to :doc:`tutorial/pipeline` to get an initial understanding of how the pipeline works; this will help in understanding the content of this section. - - -The **PipeResult** class is a container for storing pipeline processing results and implements a series of methods related to these results, such as draw_layout, draw_span. -Checkout :doc:`../api/pipe_operators` for more details about **PipeResult** - - - -Structure Definitions -------------------------------- - -**some_pdf_middle.json** - -+----------------+--------------------------------------------------------------+ -| Field Name | Description | -| | | -+================+==============================================================+ -| pdf_info | list, each element is a dict representing the parsing result | -| | of each PDF page, see the table below for details | -+----------------+--------------------------------------------------------------+ -| \_ | ocr \| txt, used to indicate the mode used in this | -| parse_type | intermediate parsing state | -| | | -+----------------+--------------------------------------------------------------+ -| \_version_name | string, indicates the version of magic-pdf used in this | -| | parsing | -| | | -+----------------+--------------------------------------------------------------+ - -**pdf_info** - -Field structure description - -+-------------------------+------------------------------------------------------------+ -| Field | Description | -| Name | | -+=========================+============================================================+ -| preproc_blocks | Intermediate result after PDF preprocessing, not yet | -| | segmented | -+-------------------------+------------------------------------------------------------+ -| layout_bboxes | Layout segmentation results, containing layout direction | -| | (vertical, horizontal), and bbox, sorted by reading order | -+-------------------------+------------------------------------------------------------+ -| page_idx | Page number, starting from 0 | -| | | -+-------------------------+------------------------------------------------------------+ -| page_size | Page width and height | -| | | -+-------------------------+------------------------------------------------------------+ -| \_layout_tree | Layout tree structure | -| | | -+-------------------------+------------------------------------------------------------+ -| images | list, each element is a dict representing an img_block | -+-------------------------+------------------------------------------------------------+ -| tables | list, each element is a dict representing a table_block | -+-------------------------+------------------------------------------------------------+ -| interline_equation | list, each element is a dict representing an | -| | interline_equation_block | -| | | -+-------------------------+------------------------------------------------------------+ -| discarded_blocks | List, block information returned by the model that needs | -| | to be dropped | -| | | -+-------------------------+------------------------------------------------------------+ -| para_blocks | Result after segmenting preproc_blocks | -| | | -+-------------------------+------------------------------------------------------------+ - -In the above table, ``para_blocks`` is an array of dicts, each dict -representing a block structure. A block can support up to one level of -nesting. - -**block** - -The outer block is referred to as a first-level block, and the fields in -the first-level block include: - -+------------------------+-------------------------------------------------------------+ -| Field | Description | -| Name | | -+========================+=============================================================+ -| type | Block type (table|image) | -+------------------------+-------------------------------------------------------------+ -| bbox | Block bounding box coordinates | -+------------------------+-------------------------------------------------------------+ -| blocks | list, each element is a dict representing a second-level | -| | block | -+------------------------+-------------------------------------------------------------+ - -There are only two types of first-level blocks: “table” and “image”. All -other blocks are second-level blocks. - -The fields in a second-level block include: - -+----------------------+----------------------------------------------------------------+ -| Field | Description | -| Name | | -+======================+================================================================+ -| | Block type | -| type | | -+----------------------+----------------------------------------------------------------+ -| | Block bounding box coordinates | -| bbox | | -+----------------------+----------------------------------------------------------------+ -| | list, each element is a dict representing a line, used to | -| lines | describe the composition of a line of information | -+----------------------+----------------------------------------------------------------+ - -Detailed explanation of second-level block types - -================== ====================== -type Description -================== ====================== -image_body Main body of the image -image_caption Image description text -table_body Main body of the table -table_caption Table description text -table_footnote Table footnote -text Text block -title Title block -interline_equation Block formula -================== ====================== - -**line** - -The field format of a line is as follows: - -+---------------------+----------------------------------------------------------------+ -| Field | Description | -| Name | | -+=====================+================================================================+ -| | Bounding box coordinates of the line | -| bbox | | -+---------------------+----------------------------------------------------------------+ -| spans | list, each element is a dict representing a span, used to | -| | describe the composition of the smallest unit | -+---------------------+----------------------------------------------------------------+ - -**span** - -+---------------------+-----------------------------------------------------------+ -| Field | Description | -| Name | | -+=====================+===========================================================+ -| bbox | Bounding box coordinates of the span | -+---------------------+-----------------------------------------------------------+ -| type | Type of the span | -+---------------------+-----------------------------------------------------------+ -| content | Text spans use content, chart spans use img_path to store | -| \| | the actual text or screenshot path information | -| img_path | | -+---------------------+-----------------------------------------------------------+ - -The types of spans are as follows: - -================== ============== -type Description -================== ============== -image Image -table Table -text Text -inline_equation Inline formula -interline_equation Block formula -================== ============== - -**Summary** - -A span is the smallest storage unit for all elements. - -The elements stored within para_blocks are block information. - -The block structure is as follows: - -First-level block (if any) -> Second-level block -> Line -> Span - -.. _example-1: - -example -^^^^^^^ - -.. code:: json - - { - "pdf_info": [ - { - "preproc_blocks": [ - { - "type": "text", - "bbox": [ - 52, - 61.956024169921875, - 294, - 82.99800872802734 - ], - "lines": [ - { - "bbox": [ - 52, - 61.956024169921875, - 294, - 72.0000228881836 - ], - "spans": [ - { - "bbox": [ - 54.0, - 61.956024169921875, - 296.2261657714844, - 72.0000228881836 - ], - "content": "dependent on the service headway and the reliability of the departure ", - "type": "text", - "score": 1.0 - } - ] - } - ] - } - ], - "layout_bboxes": [ - { - "layout_bbox": [ - 52, - 61, - 294, - 731 - ], - "layout_label": "V", - "sub_layout": [] - } - ], - "page_idx": 0, - "page_size": [ - 612.0, - 792.0 - ], - "_layout_tree": [], - "images": [], - "tables": [], - "interline_equations": [], - "discarded_blocks": [], - "para_blocks": [ - { - "type": "text", - "bbox": [ - 52, - 61.956024169921875, - 294, - 82.99800872802734 - ], - "lines": [ - { - "bbox": [ - 52, - 61.956024169921875, - 294, - 72.0000228881836 - ], - "spans": [ - { - "bbox": [ - 54.0, - 61.956024169921875, - 296.2261657714844, - 72.0000228881836 - ], - "content": "dependent on the service headway and the reliability of the departure ", - "type": "text", - "score": 1.0 - } - ] - } - ] - } - ] - } - ], - "_parse_type": "txt", - "_version_name": "0.6.1" - } - - -Pipeline Result ------------------- - -.. code:: python - - from magic_pdf.pdf_parse_union_core_v2 import pdf_parse_union - from magic_pdf.operators.pipes import PipeResult - from magic_pdf.data.dataset import Dataset - - res = pdf_parse_union(*args, **kwargs) - res['_parse_type'] = PARSE_TYPE_OCR - res['_version_name'] = __version__ - if 'lang' in kwargs and kwargs['lang'] is not None: - res['lang'] = kwargs['lang'] - - dataset : Dataset = some_dataset # not real dataset - pipeResult = PipeResult(res, dataset) - - - -some_pdf_layout.pdf -~~~~~~~~~~~~~~~~~~~ - -Each page layout consists of one or more boxes. The number at the top -left of each box indicates its sequence number. Additionally, in -``layout.pdf``, different content blocks are highlighted with different -background colors. - -.. figure:: ../_static/image/layout_example.png - :alt: layout example - - layout example - -some_pdf_spans.pdf -~~~~~~~~~~~~~~~~~~ - -All spans on the page are drawn with different colored line frames -according to the span type. This file can be used for quality control, -allowing for quick identification of issues such as missing text or -unrecognized inline formulas. - -.. figure:: ../_static/image/spans_example.png - :alt: spans example - - spans example diff --git a/next_docs/en/user_guide/quick_start.rst b/next_docs/en/user_guide/quick_start.rst deleted file mode 100644 index 41187dff6a731ae04fbab1b43e9e880f08e41df2..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/quick_start.rst +++ /dev/null @@ -1,12 +0,0 @@ - -Quick Start -============== - -Want to learn about the usage methods under different scenarios ? This page gives good examples about multiple usage cases match your needs. - -.. toctree:: - :maxdepth: 1 - - quick_start/convert_pdf - quick_start/convert_image - quick_start/convert_ms_office diff --git a/next_docs/en/user_guide/quick_start/convert_image.rst b/next_docs/en/user_guide/quick_start/convert_image.rst deleted file mode 100644 index 0b680480ab449bff7a8e3366162f13a95b4680d3..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/quick_start/convert_image.rst +++ /dev/null @@ -1,47 +0,0 @@ - - -Convert Image -=============== - - -Command Line -^^^^^^^^^^^^^ - -.. code:: python - - # make sure the file have correct suffix - magic-pdf -p a.png -o output -m auto - - -API -^^^^^^ - -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import FileBasedDataWriter - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - from magic_pdf.data.read_api import read_local_images - - # prepare env - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - os.makedirs(local_image_dir, exist_ok=True) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter( - local_md_dir - ) - - # proc - ## Create Dataset Instance - input_file = "some_image.jpg" # replace with real image file - - input_file_name = input_file.split(".")[0] - ds = read_local_images(input_file)[0] - - # ocr mode - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md( - md_writer, f"{input_file_name}.md", image_dir - ) diff --git a/next_docs/en/user_guide/quick_start/convert_ms_office.rst b/next_docs/en/user_guide/quick_start/convert_ms_office.rst deleted file mode 100644 index 9cd9550ebfcc755107483e92aa11777487882e32..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/quick_start/convert_ms_office.rst +++ /dev/null @@ -1,60 +0,0 @@ - - -Convert Doc -============= - -.. admonition:: Warning - :class: tip - - When processing MS-Office files, we first use third-party software to convert the MS-Office files to PDF. - - For certain MS-Office files, the quality of the converted PDF files may not be very high, which can affect the quality of the final output. - - - -Command Line -^^^^^^^^^^^^^ - -.. code:: python - - # replace with real ms-office file, we support MS-DOC, MS-DOCX, MS-PPT, MS-PPTX now - magic-pdf -p a.doc -o output -m auto - - -API -^^^^^^^^ -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import FileBasedDataWriter, FileBasedDataReader - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - from magic_pdf.data.read_api import read_local_office - from magic_pdf.config.enums import SupportedPdfParseMethod - - - # prepare env - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - os.makedirs(local_image_dir, exist_ok=True) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter( - local_md_dir - ) - - # proc - ## Create Dataset Instance - input_file = "some_doc.doc" # replace with real ms-office file, we support MS-DOC, MS-DOCX, MS-PPT, MS-PPTX now - - input_file_name = input_file.split(".")[0] - ds = read_local_office(input_file)[0] - - - ## inference - if ds.classify() == SupportedPdfParseMethod.OCR: - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md( - md_writer, f"{input_file_name}.md", image_dir) - else: - ds.apply(doc_analyze, ocr=False).pipe_txt_mode(image_writer).dump_md( - md_writer, f"{input_file_name}.md", image_dir) diff --git a/next_docs/en/user_guide/quick_start/convert_pdf.rst b/next_docs/en/user_guide/quick_start/convert_pdf.rst deleted file mode 100644 index 1f1ae57ae598432546b3ac3761462bd37cc97793..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/quick_start/convert_pdf.rst +++ /dev/null @@ -1,56 +0,0 @@ - - -Convert PDF -============ - -Command Line -^^^^^^^^^^^^^ - -.. code:: python - - # make sure the file have correct suffix - magic-pdf -p a.pdf -o output -m auto - - -API -^^^^^^ -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import FileBasedDataWriter, FileBasedDataReader - from magic_pdf.data.dataset import PymuDocDataset - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - - # args - pdf_file_name = "abc.pdf" # replace with the real pdf path - name_without_suff = pdf_file_name.split(".")[0] - - # prepare env - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - os.makedirs(local_image_dir, exist_ok=True) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter( - local_md_dir - ) - - # read bytes - reader1 = FileBasedDataReader("") - pdf_bytes = reader1.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ## inference - if ds.classify() == SupportedPdfParseMethod.OCR: - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md( - md_writer, f"{name_without_suff}.md", image_dir - ) - - else: - ds.apply(doc_analyze, ocr=False).pipe_txt_mode(image_writer).dump_md( - md_writer, f"{name_without_suff}.md", image_dir - ) diff --git a/next_docs/en/user_guide/tutorial.rst b/next_docs/en/user_guide/tutorial.rst deleted file mode 100644 index c2a4afb85081095f4168bb005686cb4a5ac29ed8..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/tutorial.rst +++ /dev/null @@ -1,11 +0,0 @@ - -Tutorial -=========== - -From the beginning to the end, Show how to using mineru via a minimal project - -.. toctree:: - :maxdepth: 1 - - tutorial/pipeline - diff --git a/next_docs/en/user_guide/tutorial/output_file_description.rst b/next_docs/en/user_guide/tutorial/output_file_description.rst deleted file mode 100644 index abcec0d4b188cca9ff6e8aa754f8957fadbea047..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/tutorial/output_file_description.rst +++ /dev/null @@ -1,412 +0,0 @@ - -Output File Description -========================= - -After executing the ``magic-pdf`` command, in addition to outputting -files related to markdown, several other files unrelated to markdown -will also be generated. These files will be introduced one by one. - -some_pdf_layout.pdf -~~~~~~~~~~~~~~~~~~~ - -Each page layout consists of one or more boxes. The number at the top -left of each box indicates its sequence number. Additionally, in -``layout.pdf``, different content blocks are highlighted with different -background colors. - -.. figure:: ../../_static/image/layout_example.png - :alt: layout example - - layout example - -some_pdf_spans.pdf -~~~~~~~~~~~~~~~~~~ - -All spans on the page are drawn with different colored line frames -according to the span type. This file can be used for quality control, -allowing for quick identification of issues such as missing text or -unrecognized inline formulas. - -.. figure:: ../../_static/image/spans_example.png - :alt: spans example - - spans example - -some_pdf_model.json -~~~~~~~~~~~~~~~~~~~ - -Structure Definition -^^^^^^^^^^^^^^^^^^^^ - -.. code:: python - - from pydantic import BaseModel, Field - from enum import IntEnum - - class CategoryType(IntEnum): - title = 0 # Title - plain_text = 1 # Text - abandon = 2 # Includes headers, footers, page numbers, and page annotations - figure = 3 # Image - figure_caption = 4 # Image description - table = 5 # Table - table_caption = 6 # Table description - table_footnote = 7 # Table footnote - isolate_formula = 8 # Block formula - formula_caption = 9 # Formula label - - embedding = 13 # Inline formula - isolated = 14 # Block formula - text = 15 # OCR recognition result - - - class PageInfo(BaseModel): - page_no: int = Field(description="Page number, the first page is 0", ge=0) - height: int = Field(description="Page height", gt=0) - width: int = Field(description="Page width", ge=0) - - class ObjectInferenceResult(BaseModel): - category_id: CategoryType = Field(description="Category", ge=0) - poly: list[float] = Field(description="Quadrilateral coordinates, representing the coordinates of the top-left, top-right, bottom-right, and bottom-left points respectively") - score: float = Field(description="Confidence of the inference result") - latex: str | None = Field(description="LaTeX parsing result", default=None) - html: str | None = Field(description="HTML parsing result", default=None) - - class PageInferenceResults(BaseModel): - layout_dets: list[ObjectInferenceResult] = Field(description="Page recognition results", ge=0) - page_info: PageInfo = Field(description="Page metadata") - - - # The inference results of all pages, ordered by page number, are stored in a list as the inference results of MinerU - inference_result: list[PageInferenceResults] = [] - -The format of the poly coordinates is [x0, y0, x1, y1, x2, y2, x3, y3], -representing the coordinates of the top-left, top-right, bottom-right, -and bottom-left points respectively. |Poly Coordinate Diagram| - -example -^^^^^^^ - -.. code:: json - - [ - { - "layout_dets": [ - { - "category_id": 2, - "poly": [ - 99.1906967163086, - 100.3119125366211, - 730.3707885742188, - 100.3119125366211, - 730.3707885742188, - 245.81326293945312, - 99.1906967163086, - 245.81326293945312 - ], - "score": 0.9999997615814209 - } - ], - "page_info": { - "page_no": 0, - "height": 2339, - "width": 1654 - } - }, - { - "layout_dets": [ - { - "category_id": 5, - "poly": [ - 99.13092803955078, - 2210.680419921875, - 497.3183898925781, - 2210.680419921875, - 497.3183898925781, - 2264.78076171875, - 99.13092803955078, - 2264.78076171875 - ], - "score": 0.9999997019767761 - } - ], - "page_info": { - "page_no": 1, - "height": 2339, - "width": 1654 - } - } - ] - -some_pdf_middle.json -~~~~~~~~~~~~~~~~~~~~ - -+----------------+--------------------------------------------------------------+ -| Field Name | Description | -| | | -+================+==============================================================+ -| pdf_info | list, each element is a dict representing the parsing result | -| | of each PDF page, see the table below for details | -+----------------+--------------------------------------------------------------+ -| \_ | ocr \| txt, used to indicate the mode used in this | -| parse_type | intermediate parsing state | -| | | -+----------------+--------------------------------------------------------------+ -| \_version_name | string, indicates the version of magic-pdf used in this | -| | parsing | -| | | -+----------------+--------------------------------------------------------------+ - -**pdf_info** - -Field structure description - -+-------------------------+------------------------------------------------------------+ -| Field | Description | -| Name | | -+=========================+============================================================+ -| preproc_blocks | Intermediate result after PDF preprocessing, not yet | -| | segmented | -+-------------------------+------------------------------------------------------------+ -| layout_bboxes | Layout segmentation results, containing layout direction | -| | (vertical, horizontal), and bbox, sorted by reading order | -+-------------------------+------------------------------------------------------------+ -| page_idx | Page number, starting from 0 | -| | | -+-------------------------+------------------------------------------------------------+ -| page_size | Page width and height | -| | | -+-------------------------+------------------------------------------------------------+ -| \_layout_tree | Layout tree structure | -| | | -+-------------------------+------------------------------------------------------------+ -| images | list, each element is a dict representing an img_block | -+-------------------------+------------------------------------------------------------+ -| tables | list, each element is a dict representing a table_block | -+-------------------------+------------------------------------------------------------+ -| interline_equation | list, each element is a dict representing an | -| | interline_equation_block | -| | | -+-------------------------+------------------------------------------------------------+ -| discarded_blocks | List, block information returned by the model that needs | -| | to be dropped | -| | | -+-------------------------+------------------------------------------------------------+ -| para_blocks | Result after segmenting preproc_blocks | -| | | -+-------------------------+------------------------------------------------------------+ - -In the above table, ``para_blocks`` is an array of dicts, each dict -representing a block structure. A block can support up to one level of -nesting. - -**block** - -The outer block is referred to as a first-level block, and the fields in -the first-level block include: - -+------------------------+-------------------------------------------------------------+ -| Field | Description | -| Name | | -+========================+=============================================================+ -| type | Block type (table|image) | -+------------------------+-------------------------------------------------------------+ -| bbox | Block bounding box coordinates | -+------------------------+-------------------------------------------------------------+ -| blocks | list, each element is a dict representing a second-level | -| | block | -+------------------------+-------------------------------------------------------------+ - -There are only two types of first-level blocks: “table” and “image”. All -other blocks are second-level blocks. - -The fields in a second-level block include: - -+----------------------+----------------------------------------------------------------+ -| Field | Description | -| Name | | -+======================+================================================================+ -| | Block type | -| type | | -+----------------------+----------------------------------------------------------------+ -| | Block bounding box coordinates | -| bbox | | -+----------------------+----------------------------------------------------------------+ -| | list, each element is a dict representing a line, used to | -| lines | describe the composition of a line of information | -+----------------------+----------------------------------------------------------------+ - -Detailed explanation of second-level block types - -================== ====================== -type Description -================== ====================== -image_body Main body of the image -image_caption Image description text -table_body Main body of the table -table_caption Table description text -table_footnote Table footnote -text Text block -title Title block -interline_equation Block formula -================== ====================== - -**line** - -The field format of a line is as follows: - -+---------------------+----------------------------------------------------------------+ -| Field | Description | -| Name | | -+=====================+================================================================+ -| | Bounding box coordinates of the line | -| bbox | | -+---------------------+----------------------------------------------------------------+ -| spans | list, each element is a dict representing a span, used to | -| | describe the composition of the smallest unit | -+---------------------+----------------------------------------------------------------+ - -**span** - -+---------------------+-----------------------------------------------------------+ -| Field | Description | -| Name | | -+=====================+===========================================================+ -| bbox | Bounding box coordinates of the span | -+---------------------+-----------------------------------------------------------+ -| type | Type of the span | -+---------------------+-----------------------------------------------------------+ -| content | Text spans use content, chart spans use img_path to store | -| \| | the actual text or screenshot path information | -| img_path | | -+---------------------+-----------------------------------------------------------+ - -The types of spans are as follows: - -================== ============== -type Description -================== ============== -image Image -table Table -text Text -inline_equation Inline formula -interline_equation Block formula -================== ============== - -**Summary** - -A span is the smallest storage unit for all elements. - -The elements stored within para_blocks are block information. - -The block structure is as follows: - -First-level block (if any) -> Second-level block -> Line -> Span - -.. _example-1: - -example -^^^^^^^ - -.. code:: json - - { - "pdf_info": [ - { - "preproc_blocks": [ - { - "type": "text", - "bbox": [ - 52, - 61.956024169921875, - 294, - 82.99800872802734 - ], - "lines": [ - { - "bbox": [ - 52, - 61.956024169921875, - 294, - 72.0000228881836 - ], - "spans": [ - { - "bbox": [ - 54.0, - 61.956024169921875, - 296.2261657714844, - 72.0000228881836 - ], - "content": "dependent on the service headway and the reliability of the departure ", - "type": "text", - "score": 1.0 - } - ] - } - ] - } - ], - "layout_bboxes": [ - { - "layout_bbox": [ - 52, - 61, - 294, - 731 - ], - "layout_label": "V", - "sub_layout": [] - } - ], - "page_idx": 0, - "page_size": [ - 612.0, - 792.0 - ], - "_layout_tree": [], - "images": [], - "tables": [], - "interline_equations": [], - "discarded_blocks": [], - "para_blocks": [ - { - "type": "text", - "bbox": [ - 52, - 61.956024169921875, - 294, - 82.99800872802734 - ], - "lines": [ - { - "bbox": [ - 52, - 61.956024169921875, - 294, - 72.0000228881836 - ], - "spans": [ - { - "bbox": [ - 54.0, - 61.956024169921875, - 296.2261657714844, - 72.0000228881836 - ], - "content": "dependent on the service headway and the reliability of the departure ", - "type": "text", - "score": 1.0 - } - ] - } - ] - } - ] - } - ], - "_parse_type": "txt", - "_version_name": "0.6.1" - } - -.. |Poly Coordinate Diagram| image:: ../../_static/image/poly.png diff --git a/next_docs/en/user_guide/tutorial/pipeline.rst b/next_docs/en/user_guide/tutorial/pipeline.rst deleted file mode 100644 index d5438bffa7b998a5b82301367cc0c24000ca362e..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/tutorial/pipeline.rst +++ /dev/null @@ -1,182 +0,0 @@ - - -Pipeline -========== - - -Minimal Example -^^^^^^^^^^^^^^^^^ - -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import FileBasedDataWriter, FileBasedDataReader - from magic_pdf.data.dataset import PymuDocDataset - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - - # args - pdf_file_name = "abc.pdf" # replace with the real pdf path - name_without_suff = pdf_file_name.split(".")[0] - - # prepare env - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - os.makedirs(local_image_dir, exist_ok=True) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter( - local_md_dir - ) - - # read bytes - reader1 = FileBasedDataReader("") - pdf_bytes = reader1.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md(md_writer, f"{name_without_suff}.md", image_dir) - -Running the above code will result in the following - - -.. code:: bash - - output/ - ├── abc.md - └── images - - -Excluding the setup of the environment, such as creating directories and importing dependencies, the actual code snippet for converting pdf to markdown is as follows - - -.. code:: python - - # read bytes - reader1 = FileBasedDataReader("") - pdf_bytes = reader1.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md(md_writer, f"{name_without_suff}.md", image_dir) - -``ds.apply(doc_analyze, ocr=True)`` generates an ``InferenceResult`` object. The ``InferenceResult`` object, when executing the ``pipe_ocr_mode`` method, produces a ``PipeResult`` object. -The ``PipeResult`` object, upon executing ``dump_md``, generates a ``markdown`` file at the specified location. - - -The pipeline execution process is illustrated in the following diagram - - -.. image:: ../../_static/image/pipeline.drawio.svg - -.. raw:: html - -

    - -Currently, the process is divided into three stages: data, inference, and processing, which correspond to the ``Dataset``, ``InferenceResult``, and ``PipeResult`` entities in the diagram. -These stages are linked together through methods like ``apply``, ``doc_analyze``, or ``pipe_ocr_mode`` - - -.. admonition:: Tip - :class: tip - - For more detailed information about ``Dataset``, ``InferenceResult``, and ``PipeResult``, please refer to :doc:`../../api/dataset`, :doc:`../../api/model_operators`, :doc:`../../api/pipe_operators` - - -Pipeline Composition -^^^^^^^^^^^^^^^^^^^^^ - -.. code:: python - - class Dataset(ABC): - @abstractmethod - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(self, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - pass - - class InferenceResult(InferenceResultBase): - - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(inference_result, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - return proc(copy.deepcopy(self._infer_res), *args, **kwargs) - - def pipe_ocr_mode( - self, - imageWriter: DataWriter, - start_page_id=0, - end_page_id=None, - debug_mode=False, - lang=None, - ) -> PipeResult: - pass - - class PipeResult: - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(pipeline_result, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - return proc(copy.deepcopy(self._pipe_res), *args, **kwargs) - - -The ``Dataset``, ``InferenceResult``, and ``PipeResult`` classes all have an ``apply`` method, which can be used to chain different stages of the computation. -As shown below, ``MinerU`` provides a set of methods to compose these classes. - - -.. code:: python - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md(md_writer, f"{name_without_suff}.md", image_dir) - - -Users can implement their own functions for chaining as needed. For example, a user could use the ``apply`` method to create a function that counts the number of pages in a ``pdf`` file. - - -.. code:: python - - from magic_pdf.data.data_reader_writer import FileBasedDataReader - from magic_pdf.data.dataset import PymuDocDataset - - # args - pdf_file_name = "abc.pdf" # replace with the real pdf path - - # read bytes - reader1 = FileBasedDataReader("") - pdf_bytes = reader1.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - def count_page(ds)-> int: - return len(ds) - - print("page number: ", ds.apply(count_page)) # will output the page count of `abc.pdf` diff --git a/next_docs/en/user_guide/usage.rst b/next_docs/en/user_guide/usage.rst deleted file mode 100644 index b2d04280a16a8791d5a29b454825739b49cd2093..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/usage.rst +++ /dev/null @@ -1,12 +0,0 @@ - - -Usage -======== - -.. toctree:: - :maxdepth: 1 - - usage/command_line - usage/api - usage/docker - diff --git a/next_docs/en/user_guide/usage/api.rst b/next_docs/en/user_guide/usage/api.rst deleted file mode 100644 index 36c49a0e233ebee05d1c67b45d43dec01a8cc00e..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/usage/api.rst +++ /dev/null @@ -1,279 +0,0 @@ - -Api Usage -=========== - - -PDF ----- - -Local File Example -^^^^^^^^^^^^^^^^^^ - -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import FileBasedDataWriter, FileBasedDataReader - from magic_pdf.data.dataset import PymuDocDataset - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - from magic_pdf.config.enums import SupportedPdfParseMethod - - # args - pdf_file_name = "abc.pdf" # replace with the real pdf path - name_without_suff = pdf_file_name.split(".")[0] - - # prepare env - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - os.makedirs(local_image_dir, exist_ok=True) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter( - local_md_dir - ) - - # read bytes - reader1 = FileBasedDataReader("") - pdf_bytes = reader1.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ## inference - if ds.classify() == SupportedPdfParseMethod.OCR: - infer_result = ds.apply(doc_analyze, ocr=True) - - ## pipeline - pipe_result = infer_result.pipe_ocr_mode(image_writer) - - else: - infer_result = ds.apply(doc_analyze, ocr=False) - - ## pipeline - pipe_result = infer_result.pipe_txt_mode(image_writer) - - ### draw model result on each page - infer_result.draw_model(os.path.join(local_md_dir, f"{name_without_suff}_model.pdf")) - - ### get model inference result - model_inference_result = infer_result.get_infer_res() - - ### draw layout result on each page - pipe_result.draw_layout(os.path.join(local_md_dir, f"{name_without_suff}_layout.pdf")) - - ### draw spans result on each page - pipe_result.draw_span(os.path.join(local_md_dir, f"{name_without_suff}_spans.pdf")) - - ### get markdown content - md_content = pipe_result.get_markdown(image_dir) - - ### dump markdown - pipe_result.dump_md(md_writer, f"{name_without_suff}.md", image_dir) - - ### get content list content - content_list_content = pipe_result.get_content_list(image_dir) - - ### dump content list - pipe_result.dump_content_list(md_writer, f"{name_without_suff}_content_list.json", image_dir) - - ### get middle json - middle_json_content = pipe_result.get_middle_json() - - ### dump middle json - pipe_result.dump_middle_json(md_writer, f'{name_without_suff}_middle.json') - - - -S3 File Example -^^^^^^^^^^^^^^^^ - -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import S3DataReader, S3DataWriter - from magic_pdf.data.dataset import PymuDocDataset - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - from magic_pdf.config.enums import SupportedPdfParseMethod - - bucket_name = "{Your S3 Bucket Name}" # replace with real bucket name - ak = "{Your S3 access key}" # replace with real s3 access key - sk = "{Your S3 secret key}" # replace with real s3 secret key - endpoint_url = "{Your S3 endpoint_url}" # replace with real s3 endpoint_url - - reader = S3DataReader('unittest/tmp/', bucket_name, ak, sk, endpoint_url) # replace `unittest/tmp` with the real s3 prefix - writer = S3DataWriter('unittest/tmp', bucket_name, ak, sk, endpoint_url) - image_writer = S3DataWriter('unittest/tmp/images', bucket_name, ak, sk, endpoint_url) - md_writer = S3DataWriter('unittest/tmp', bucket_name, ak, sk, endpoint_url) - - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - # args - pdf_file_name = ( - f"s3://{bucket_name}/unittest/tmp/bug5-11.pdf" # replace with the real s3 path - ) - - # prepare env - local_dir = "output" - name_without_suff = os.path.basename(pdf_file_name).split(".")[0] - - # read bytes - pdf_bytes = reader.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ## inference - if ds.classify() == SupportedPdfParseMethod.OCR: - infer_result = ds.apply(doc_analyze, ocr=True) - - ## pipeline - pipe_result = infer_result.pipe_ocr_mode(image_writer) - - else: - infer_result = ds.apply(doc_analyze, ocr=False) - - ## pipeline - pipe_result = infer_result.pipe_txt_mode(image_writer) - - ### draw model result on each page - infer_result.draw_model(os.path.join(local_md_dir, f"{name_without_suff}_model.pdf")) - - ### get model inference result - model_inference_result = infer_result.get_infer_res() - - ### draw layout result on each page - pipe_result.draw_layout(os.path.join(local_md_dir, f"{name_without_suff}_layout.pdf")) - - ### draw spans result on each page - pipe_result.draw_span(os.path.join(local_md_dir, f"{name_without_suff}_spans.pdf")) - - ### dump markdown - pipe_result.dump_md(md_writer, f"{name_without_suff}.md", image_dir) - - ### dump content list - pipe_result.dump_content_list(md_writer, f"{name_without_suff}_content_list.json", image_dir) - - ### get markdown content - md_content = pipe_result.get_markdown(image_dir) - - ### get content list content - content_list_content = pipe_result.get_content_list(image_dir) - - ### get middle json - middle_json_content = pipe_result.get_middle_json() - - ### dump middle json - pipe_result.dump_middle_json(md_writer, f'{name_without_suff}_middle.json') - -MS-Office ----------- - -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import FileBasedDataWriter, FileBasedDataReader - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - from magic_pdf.data.read_api import read_local_office - - # prepare env - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - os.makedirs(local_image_dir, exist_ok=True) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter( - local_md_dir - ) - - # proc - ## Create Dataset Instance - input_file = "some_ppt.ppt" # replace with real ms-office file - - input_file_name = input_file.split(".")[0] - ds = read_local_office(input_file)[0] - - ds.apply(doc_analyze, ocr=True).pipe_txt_mode(image_writer).dump_md( - md_writer, f"{input_file_name}.md", image_dir - ) - -This code snippet can be used to manipulate **ppt**, **pptx**, **doc**, **docx** file - - -Image ---------- - -Single Image File -^^^^^^^^^^^^^^^^^^^ - -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import FileBasedDataWriter - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - from magic_pdf.data.read_api import read_local_images - - # prepare env - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - os.makedirs(local_image_dir, exist_ok=True) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter( - local_md_dir - ) - - # proc - ## Create Dataset Instance - input_file = "some_image.jpg" # replace with real image file - - input_file_name = input_file.split(".")[0] - ds = read_local_images(input_file)[0] - - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md( - md_writer, f"{input_file_name}.md", image_dir - ) - - -Directory That Contains Images -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import FileBasedDataWriter - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - from magic_pdf.data.read_api import read_local_images - - # prepare env - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - os.makedirs(local_image_dir, exist_ok=True) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter( - local_md_dir - ) - - # proc - ## Create Dataset Instance - input_directory = "some_image_dir/" # replace with real directory that contains images - - - dss = read_local_images(input_directory, suffixes=['.png', '.jpg']) - - count = 0 - for ds in dss: - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md( - md_writer, f"{count}.md", image_dir - ) - count += 1 - - -Check :doc:`../data/data_reader_writer` for more [reader | writer] examples and check :doc:`../../api/pipe_operators` or :doc:`../../api/model_operators` for api details diff --git a/next_docs/en/user_guide/usage/command_line.rst b/next_docs/en/user_guide/usage/command_line.rst deleted file mode 100644 index 1fc90f2a82360e625b5b264c70331fca1ae2ae42..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/usage/command_line.rst +++ /dev/null @@ -1,77 +0,0 @@ - - -Command Line -=================== - -.. code:: bash - - magic-pdf --help - Usage: magic-pdf [OPTIONS] - - Options: - -v, --version display the version and exit - -p, --path PATH local filepath or directory. support PDF, PPT, - PPTX, DOC, DOCX, PNG, JPG files [required] - -o, --output-dir PATH output local directory [required] - -m, --method [ocr|txt|auto] the method for parsing pdf. ocr: using ocr - technique to extract information from pdf. txt: - suitable for the text-based pdf only and - outperform ocr. auto: automatically choose the - best method for parsing pdf from ocr and txt. - without method specified, auto will be used by - default. - -l, --lang TEXT Input the languages in the pdf (if known) to - improve OCR accuracy. Optional. You should - input "Abbreviation" with language form url: ht - tps://paddlepaddle.github.io/PaddleOCR/en/ppocr - /blog/multi_languages.html#5-support-languages- - and-abbreviations - -d, --debug BOOLEAN Enables detailed debugging information during - the execution of the CLI commands. - -s, --start INTEGER The starting page for PDF parsing, beginning - from 0. - -e, --end INTEGER The ending page for PDF parsing, beginning from - 0. - --help Show this message and exit. - - - ## show version - magic-pdf -v - - ## command line example - magic-pdf -p {some_pdf} -o {some_output_dir} -m auto - - -.. admonition:: Important - :class: tip - - The file must endswith with the following suffix. - .pdf - .png - .jpg - .ppt - .pptx - .doc - .docx - - -``{some_pdf}`` can be a single PDF file or a directory containing -multiple PDFs. The results will be saved in the ``{some_output_dir}`` -directory. The output file list is as follows: - -.. code:: text - - ├── some_pdf.md # markdown file - ├── images # directory for storing images - ├── some_pdf_layout.pdf # layout diagram - ├── some_pdf_middle.json # MinerU intermediate processing result - ├── some_pdf_model.json # model inference result - ├── some_pdf_origin.pdf # original PDF file - ├── some_pdf_spans.pdf # smallest granularity bbox position information diagram - └── some_pdf_content_list.json # Rich text JSON arranged in reading order - -.. admonition:: Tip - :class: tip - - - For more information about the output files, please refer to the :doc:`../inference_result` or :doc:`../pipe_result` diff --git a/next_docs/en/user_guide/usage/docker.rst b/next_docs/en/user_guide/usage/docker.rst deleted file mode 100644 index 0f911df5e3fbe7b1721c6fdab922861bdf4f7095..0000000000000000000000000000000000000000 --- a/next_docs/en/user_guide/usage/docker.rst +++ /dev/null @@ -1,24 +0,0 @@ - - -Docker -======= - -.. admonition:: Important - :class: tip - - Docker requires a GPU with at least 16GB of VRAM, and all acceleration features are enabled by default. - - Before running this Docker, you can use the following command to check if your device supports CUDA acceleration on Docker. - - .. code-block:: bash - - bash docker run --rm --gpus=all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi - - -.. code:: sh - - wget https://github.com/opendatalab/MinerU/raw/master/Dockerfile - docker build -t mineru:latest . - docker run --rm -it --gpus=all mineru:latest /bin/bash - magic-pdf --help - diff --git a/next_docs/requirements.txt b/next_docs/requirements.txt deleted file mode 100644 index e99b02528c253fff8f8cb6a487e420bb5954bfde..0000000000000000000000000000000000000000 --- a/next_docs/requirements.txt +++ /dev/null @@ -1,17 +0,0 @@ -numpy==1.26.4 -click==8.1.7 -fast-langdetect==0.2.2 -Brotli==1.1.0 -boto3>=1.28.43 -loguru>=0.6.0 -myst-parser -Pillow==8.4.0 -pydantic>=2.7.2,<2.8.0 -PyMuPDF>=1.24.9 -pdfminer.six==20231228 -sphinx -sphinx-argparse>=0.5.2 -sphinx-book-theme>=1.1.3 -sphinx-copybutton>=0.5.2 -sphinx_rtd_theme>=3.0.1 -autodoc_pydantic>=2.2.0 diff --git a/next_docs/zh_cn/.readthedocs.yaml b/next_docs/zh_cn/.readthedocs.yaml deleted file mode 100644 index 5df2ecffb46f4b11fd1832a229c94ae407f2da56..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/.readthedocs.yaml +++ /dev/null @@ -1,16 +0,0 @@ -version: 2 - -build: - os: ubuntu-22.04 - tools: - python: "3.10" - -formats: - - epub - -python: - install: - - requirements: next_docs/requirements.txt - -sphinx: - configuration: next_docs/zh_cn/conf.py diff --git a/next_docs/zh_cn/Makefile b/next_docs/zh_cn/Makefile deleted file mode 100644 index d4bb2cbb9eddb1bb1b4f366623044af8e4830919..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/next_docs/zh_cn/_static/image/MinerU-logo-hq.png b/next_docs/zh_cn/_static/image/MinerU-logo-hq.png deleted file mode 100644 index 7b33fcda2ab95e693c978e914f8b6b95fd84cc87..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/MinerU-logo-hq.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/MinerU-logo.png b/next_docs/zh_cn/_static/image/MinerU-logo.png deleted file mode 100644 index 2e6fdf3a9ec43217155c0d9239fe4d8b6f913611..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/MinerU-logo.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/ReadTheDocs.svg b/next_docs/zh_cn/_static/image/ReadTheDocs.svg deleted file mode 100644 index de907442fa897899e90ab62e5a3c95a1af44b118..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/_static/image/ReadTheDocs.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - -Created with Fabric.js 5.2.4 - - - - - - - - - - - - - Read The Docs - - - - - - Read The Docs - - \ No newline at end of file diff --git a/next_docs/zh_cn/_static/image/datalab_logo.png b/next_docs/zh_cn/_static/image/datalab_logo.png deleted file mode 100644 index 5019ae7cfdef185058cf402504275df18e9b1403..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/datalab_logo.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/flowchart_en.png b/next_docs/zh_cn/_static/image/flowchart_en.png deleted file mode 100644 index b490011ea7a9edebeb9edbf3980fc971d89bb76a..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/flowchart_en.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/flowchart_zh_cn.png b/next_docs/zh_cn/_static/image/flowchart_zh_cn.png deleted file mode 100644 index 32e0a14233972666cf4507af178c77cfe41e3311..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/flowchart_zh_cn.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/inference_result.png b/next_docs/zh_cn/_static/image/inference_result.png deleted file mode 100644 index 7fb907103a077e484b5daea0f8e299d414b3f727..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/inference_result.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/layout_example.png b/next_docs/zh_cn/_static/image/layout_example.png deleted file mode 100644 index 14e2116f6fa8acd3099220a8d235420fe1e9af92..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/layout_example.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/logo.png b/next_docs/zh_cn/_static/image/logo.png deleted file mode 100644 index 2e6fdf3a9ec43217155c0d9239fe4d8b6f913611..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/logo.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/pipeline.drawio.svg b/next_docs/zh_cn/_static/image/pipeline.drawio.svg deleted file mode 100644 index b74666430e65951f3e8b85ec9951a0b1eb13b5e6..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/_static/image/pipeline.drawio.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
    Dataset
    Inference
    Result
    Pipeline
    Result
    /data/abc.pdf
    /data/a.jpg

    s3://data/a.pdf
    draw layout result
    dump markdown file

    draw span result
    draw model result
    dump inference result

    doc_analyze
    pipe_ocr_mode
    \ No newline at end of file diff --git a/next_docs/zh_cn/_static/image/poly.png b/next_docs/zh_cn/_static/image/poly.png deleted file mode 100644 index 14af772668b003c53c7c773e39addf5006836e13..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/poly.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/project_panorama_en.png b/next_docs/zh_cn/_static/image/project_panorama_en.png deleted file mode 100644 index 19616da641076c037c47919c0d3de9efb8e409da..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/project_panorama_en.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/project_panorama_zh_cn.png b/next_docs/zh_cn/_static/image/project_panorama_zh_cn.png deleted file mode 100644 index 3cd6843e05b827cb0a7c9cc31855de0d3f4645c5..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/project_panorama_zh_cn.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/spans_example.png b/next_docs/zh_cn/_static/image/spans_example.png deleted file mode 100644 index 14de87ed7aaa84ccf3db78512ecda419db4f8924..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/spans_example.png and /dev/null differ diff --git a/next_docs/zh_cn/_static/image/web_demo_1.png b/next_docs/zh_cn/_static/image/web_demo_1.png deleted file mode 100644 index 04adff2686572f05c5f5edfa039a45ab8a5d7736..0000000000000000000000000000000000000000 Binary files a/next_docs/zh_cn/_static/image/web_demo_1.png and /dev/null differ diff --git a/next_docs/zh_cn/additional_notes/faq.rst b/next_docs/zh_cn/additional_notes/faq.rst deleted file mode 100644 index d4eefb9d21b7c1fda976b9cdb62f158c07e4364b..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/additional_notes/faq.rst +++ /dev/null @@ -1,72 +0,0 @@ -常见问题解答 -============ - -1.在较新版本的mac上使用命令安装pip install magic-pdf[full] zsh: no matches found: magic-pdf[full] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -在 macOS 上,默认的 shell 从 Bash 切换到了 Z shell,而 Z shell 对于某些类型的字符串匹配有特殊的处理逻辑,这可能导致no matches found错误。 可以通过在命令行禁用globbing特性,再尝试运行安装命令 - -.. code:: bash - - setopt no_nomatch - pip install magic-pdf[full] - -2.使用过程中遇到_pickle.UnpicklingError: invalid load key, ‘v’.错误 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -可能是由于模型文件未下载完整导致,可尝试重新下载模型文件后再试。参考:https://github.com/opendatalab/MinerU/issues/143 - -3.模型文件应该下载到哪里/models-dir的配置应该怎么填 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -模型文件的路径输入是在”magic-pdf.json”中通过 - -.. code:: json - - { - "models-dir": "/tmp/models" - } - -进行配置的。这个路径是绝对路径而不是相对路径,绝对路径的获取可在models目录中通过命令 “pwd” 获取。 -参考:https://github.com/opendatalab/MinerU/issues/155#issuecomment-2230216874 - -4.在WSL2的Ubuntu22.04中遇到报错\ ``ImportError: libGL.so.1: cannot open shared object file: No such file or directory`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -WSL2的Ubuntu22.04中缺少\ ``libgl``\ 库,可通过以下命令安装\ ``libgl``\ 库解决: - -.. code:: bash - - sudo apt-get install libgl1-mesa-glx - -参考:https://github.com/opendatalab/MinerU/issues/388 - -5.遇到报错 ``ModuleNotFoundError : Nomodulenamed 'fairscale'`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -需要卸载该模块并重新安装 - -.. code:: bash - - pip uninstall fairscale - pip install fairscale - -参考:https://github.com/opendatalab/MinerU/issues/411 - -6.在部分较新的设备如H100上,使用CUDA加速OCR时解析出的文字乱码。 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -cuda11对新显卡的兼容性不好,需要升级paddle使用的cuda版本 - -.. code:: bash - - pip install paddlepaddle-gpu==3.0.0b1 -i https://www.paddlepaddle.org.cn/packages/stable/cu123/ - -参考:https://github.com/opendatalab/MinerU/issues/558 - -7.在部分Linux服务器上,程序一运行就报错 ``非法指令 (核心已转储)`` 或 ``Illegal instruction (core dumped)`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -可能是因为服务器CPU不支持AVX/AVX2指令集,或cpu本身支持但被运维禁用了,可以尝试联系运维解除限制或更换服务器。 - -参考:https://github.com/opendatalab/MinerU/issues/591 ,https://github.com/opendatalab/MinerU/issues/736 diff --git a/next_docs/zh_cn/additional_notes/glossary.rst b/next_docs/zh_cn/additional_notes/glossary.rst deleted file mode 100644 index cc2c58224a7515351cf52549ae2e2217740fe2e3..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/additional_notes/glossary.rst +++ /dev/null @@ -1,11 +0,0 @@ - - -名词解释 -=========== - -1. jsonl - TODO: add description - -2. magic-pdf.json - TODO: add description - diff --git a/next_docs/zh_cn/additional_notes/known_issues.rst b/next_docs/zh_cn/additional_notes/known_issues.rst deleted file mode 100644 index 68b6d39c3c30af3013ef1209ff52b104b1a6ba91..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/additional_notes/known_issues.rst +++ /dev/null @@ -1,13 +0,0 @@ -已知问题 -============ - -- 阅读顺序基于模型对可阅读内容在空间中的分布进行排序,在极端复杂的排版下可能会部分区域乱序 -- 不支持竖排文字 -- 目录和列表通过规则进行识别,少部分不常见的列表形式可能无法识别 -- 标题只有一级,目前不支持标题分级 -- 代码块在layout模型里还没有支持 -- 漫画书、艺术图册、小学教材、习题尚不能很好解析 -- 表格识别在复杂表格上可能会出现行/列识别错误 -- 在小语种PDF上,OCR识别可能会出现字符不准确的情况(如拉丁文的重音符号、阿拉伯文易混淆字符等) -- 部分公式可能会无法在markdown中渲染 - diff --git a/next_docs/zh_cn/conf.py b/next_docs/zh_cn/conf.py deleted file mode 100644 index df7481df49dbb2b69fe76985a4f91d448756f259..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/conf.py +++ /dev/null @@ -1,151 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. - -import os -import subprocess -import sys - -from sphinx.ext import autodoc -from docutils import nodes -from docutils.parsers.rst import Directive - -def install(package): - subprocess.check_call([sys.executable, '-m', 'pip', 'install', package]) - - -requirements_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'requirements.txt')) -if os.path.exists(requirements_path): - with open(requirements_path) as f: - packages = f.readlines() - for package in packages: - install(package.strip()) - -sys.path.insert(0, os.path.abspath('../..')) - -# -- Project information ----------------------------------------------------- - -project = 'MinerU' -copyright = '2024, MinerU Contributors' -author = 'OpenDataLab' - -# The full version, including alpha/beta/rc tags -version_file = '../../magic_pdf/libs/version.py' -with open(version_file) as f: - exec(compile(f.read(), version_file, 'exec')) -__version__ = locals()['__version__'] -# The short X.Y version -version = __version__ -# The full version, including alpha/beta/rc tags -release = __version__ - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.napoleon', - 'sphinx.ext.viewcode', - 'sphinx.ext.intersphinx', - 'sphinx_copybutton', - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.inheritance_diagram', - 'myst_parser', - 'sphinxarg.ext', - 'sphinxcontrib.autodoc_pydantic', -] - -# class hierarchy diagram -inheritance_graph_attrs = dict(rankdir="LR", size='"8.0, 12.0"', fontsize=14, ratio='compress') -inheritance_node_attrs = dict(shape='ellipse', fontsize=14, height=0.75) -inheritance_edge_attrs = dict(arrow='vee') - -autodoc_pydantic_model_show_json = True -autodoc_pydantic_model_show_config_summary = False - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# Exclude the prompt "$" when copying code -copybutton_prompt_text = r'\$ ' -copybutton_prompt_is_regexp = True - -language = 'zh_CN' - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'sphinx_book_theme' -html_logo = '_static/image/logo.png' -html_theme_options = { - 'path_to_docs': 'next_docs/zh_cn', - 'repository_url': 'https://github.com/opendatalab/MinerU', - 'use_repository_button': True, -} -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] - -# Mock out external dependencies here. -autodoc_mock_imports = [ - 'cpuinfo', - 'torch', - 'transformers', - 'psutil', - 'prometheus_client', - 'sentencepiece', - 'vllm.cuda_utils', - 'vllm._C', - 'numpy', - 'tqdm', -] - - -class MockedClassDocumenter(autodoc.ClassDocumenter): - """Remove note about base class when a class is derived from object.""" - - def add_line(self, line: str, source: str, *lineno: int) -> None: - if line == ' Bases: :py:class:`object`': - return - super().add_line(line, source, *lineno) - - -autodoc.ClassDocumenter = MockedClassDocumenter - -navigation_with_keys = False - - -# add custom directive - - -class VideoDirective(Directive): - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = True - option_spec = {} - - def run(self): - url = self.arguments[0] - video_node = nodes.raw('', f'', format='html') - return [video_node] - -def setup(app): - app.add_directive('video', VideoDirective) \ No newline at end of file diff --git a/next_docs/zh_cn/index.rst b/next_docs/zh_cn/index.rst deleted file mode 100644 index 4d86a21e960c3f3808a019148334bfab70485a06..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/index.rst +++ /dev/null @@ -1,81 +0,0 @@ -.. xtuner documentation master file, created by - sphinx-quickstart on Tue Jan 9 16:33:06 2024. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -欢迎来到 MinerU 文档库 -============================================== - -.. figure:: ./_static/image/logo.png - :align: center - :alt: mineru - :class: no-scaled-link - -.. raw:: html - -

    - 一站式、高质量的开源文档提取工具 - -

    - -

    - - Star - Watch - Fork -

    - - -项目介绍 --------------------- - -MinerU是一款将PDF转化为机器可读格式的工具(如markdown、json),可以很方便地抽取为任意格式。 -MinerU诞生于\ `书生-浦语 `__\ 的预训练过程中,我们将会集中精力解决科技文献中的符号转化问题,希望在大模型时代为科技发展做出贡献。 -相比国内外知名商用产品MinerU还很年轻,如果遇到问题或者结果不及预期请到\ `issue `__\ 提交问题,同时\ **附上相关PDF**\ 。 - -.. video:: https://github.com/user-attachments/assets/4bea02c9-6d54-4cd6-97ed-dff14340982c - -主要功能 --------- - -- 删除页眉、页脚、脚注、页码等元素,确保语义连贯 -- 输出符合人类阅读顺序的文本,适用于单栏、多栏及复杂排版 -- 保留原文档的结构,包括标题、段落、列表等 -- 提取图像、图片描述、表格、表格标题及脚注 -- 自动识别并转换文档中的公式为LaTeX格式 -- 自动识别并转换文档中的表格为LaTeX或HTML格式 -- 自动检测扫描版PDF和乱码PDF,并启用OCR功能 -- OCR支持84种语言的检测与识别 -- 支持多种输出格式,如多模态与NLP的Markdown、按阅读顺序排序的JSON、含有丰富信息的中间格式等 -- 支持多种可视化结果,包括layout可视化、span可视化等,便于高效确认输出效果与质检 -- 支持CPU和GPU环境 -- 兼容Windows、Linux和Mac平台 - - -用户指南 -------------- -.. toctree:: - :maxdepth: 2 - :caption: 用户指南 - - user_guide - - -API 接口 -------------- -本章节主要介绍函数、类、类方法的细节信息 - -目前只提供英文版本的接口文档,请切换到英文版本的接口文档! - - -附录 ------------------- -.. toctree:: - :maxdepth: 1 - :caption: 附录 - - additional_notes/known_issues - additional_notes/faq - additional_notes/glossary - - diff --git a/next_docs/zh_cn/make.bat b/next_docs/zh_cn/make.bat deleted file mode 100644 index 954237b9b9f2b248bb1397a15c055c0af1cad03e..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=_build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/next_docs/zh_cn/user_guide.rst b/next_docs/zh_cn/user_guide.rst deleted file mode 100644 index 621996c341e4aa3bb4a3039b3cd48cef8eb79821..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide.rst +++ /dev/null @@ -1,10 +0,0 @@ - - -.. toctree:: - :maxdepth: 2 - - user_guide/install - user_guide/quick_start - user_guide/tutorial - user_guide/data - diff --git a/next_docs/zh_cn/user_guide/data.rst b/next_docs/zh_cn/user_guide/data.rst deleted file mode 100644 index 455c731df83470b5bdd4529e70dc99453771379d..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/data.rst +++ /dev/null @@ -1,20 +0,0 @@ - - -数据 -========= - -.. toctree:: - :maxdepth: 2 - :caption: 数据 - - data/dataset - - data/read_api - - data/data_reader_writer - - data/io - - - - diff --git a/next_docs/zh_cn/user_guide/data/data_reader_writer.rst b/next_docs/zh_cn/user_guide/data/data_reader_writer.rst deleted file mode 100644 index f7c637796d7da3f73d93b8267b9b6b513b0c2b3c..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/data/data_reader_writer.rst +++ /dev/null @@ -1,218 +0,0 @@ - -数据读取和写入类 -================= - -旨在从不同的媒介读取或写入字节。如果 MinerU 没有提供合适的类,你可以实现新的类以满足个人场景的需求。实现新的类非常容易,唯一的要求是继承自 DataReader 或 DataWriter。 - -.. code:: python - - class SomeReader(DataReader): - def read(self, path: str) -> bytes: - pass - - def read_at(self, path: str, offset: int = 0, limit: int = -1) -> bytes: - pass - - - class SomeWriter(DataWriter): - def write(self, path: str, data: bytes) -> None: - pass - - def write_string(self, path: str, data: str) -> None: - pass - -读者可能会对 io 和本节的区别感到好奇。乍一看,这两部分非常相似。io 提供基本功能,而本节则更注重应用层面。用户可以构建自己的类以满足特定应用需求,这些类可能共享相同的基本 IO 功能。这就是为什么我们有 io。 - -重要类 ------------- -.. code:: python - - class FileBasedDataReader(DataReader): - def __init__(self, parent_dir: str = ''): - pass - - - class FileBasedDataWriter(DataWriter): - def __init__(self, parent_dir: str = '') -> None: - pass - -类 FileBasedDataReader 使用单个参数 parent_dir 初始化。这意味着 FileBasedDataReader 提供的每个方法将具有以下特性: - -#. 从绝对路径文件读取内容,parent_dir 将被忽略。 -#. 从相对路径读取文件,首先将路径与 parent_dir 连接,然后从合并后的路径读取内容。 - -.. note:: - - `FileBasedDataWriter` 与 `FileBasedDataReader` 具有相同的行为。 - -.. code:: python - - class MultiS3Mixin: - def __init__(self, default_prefix: str, s3_configs: list[S3Config]): - pass - - class MultiBucketS3DataReader(DataReader, MultiS3Mixin): - pass - -MultiBucketS3DataReader 提供的所有读取相关方法将具有以下特性: - -#. 从完整的 S3 格式路径读取对象,例如 s3://test_bucket/test_object,default_prefix 将被忽略。 -#. 从相对路径读取对象,首先将路径与 default_prefix 连接并去掉 bucket_name,然后读取内容。bucket_name 是将 default_prefix 用分隔符 \ 分割后的第一个元素。 - -.. note:: - MultiBucketS3DataWriter 与 MultiBucketS3DataReader 具有类似的行为。 - -.. code:: python - - class S3DataReader(MultiBucketS3DataReader): - pass - -S3DataReader 基于 MultiBucketS3DataReader 构建,但仅支持单个桶。S3DataWriter 也是类似的情况。 - -读取示例 ---------- -.. code:: python - - import os - from magic_pdf.data.data_reader_writer import * - from magic_pdf.data.data_reader_writer import MultiBucketS3DataReader - from magic_pdf.data.schemas import S3Config - - # 初始化 reader - file_based_reader1 = FileBasedDataReader('') - - ## 读本地文件 abc - file_based_reader1.read('abc') - - file_based_reader2 = FileBasedDataReader('/tmp') - - ## 读本地文件 /tmp/abc - file_based_reader2.read('abc') - - ## 读本地文件 /tmp/logs/message.txt - file_based_reader2.read('/tmp/logs/message.txt') - - # 初始化多桶 s3 reader - bucket = "bucket" # 替换为有效的 bucket - ak = "ak" # 替换为有效的 access key - sk = "sk" # 替换为有效的 secret key - endpoint_url = "endpoint_url" # 替换为有效的 endpoint_url - - bucket_2 = "bucket_2" # 替换为有效的 bucket - ak_2 = "ak_2" # 替换为有效的 access key - sk_2 = "sk_2" # 替换为有效的 secret key - endpoint_url_2 = "endpoint_url_2" # 替换为有效的 endpoint_url - - test_prefix = 'test/unittest' - multi_bucket_s3_reader1 = MultiBucketS3DataReader(f"{bucket}/{test_prefix}", [S3Config( - bucket_name=bucket, access_key=ak, secret_key=sk, endpoint_url=endpoint_url - ), - S3Config( - bucket_name=bucket_2, - access_key=ak_2, - secret_key=sk_2, - endpoint_url=endpoint_url_2, - )]) - - ## 读文件 s3://{bucket}/{test_prefix}/abc - multi_bucket_s3_reader1.read('abc') - - ## 读文件 s3://{bucket}/{test_prefix}/efg - multi_bucket_s3_reader1.read(f's3://{bucket}/{test_prefix}/efg') - - ## 读文件 s3://{bucket2}/{test_prefix}/abc - multi_bucket_s3_reader1.read(f's3://{bucket_2}/{test_prefix}/abc') - - # 初始化 s3 reader - s3_reader1 = S3DataReader( - test_prefix, - bucket, - ak, - sk, - endpoint_url - ) - - ## 读文件 s3://{bucket}/{test_prefix}/abc - s3_reader1.read('abc') - - ## 读文件 s3://{bucket}/efg - s3_reader1.read(f's3://{bucket}/efg') - - -写入示例 ----------- -.. code:: python - - import os - from magic_pdf.data.data_reader_writer import * - from magic_pdf.data.data_reader_writer import MultiBucketS3DataWriter - from magic_pdf.data.schemas import S3Config - - # 初始化 reader - file_based_writer1 = FileBasedDataWriter("") - - ## 写数据 123 to abc - file_based_writer1.write("abc", "123".encode()) - - ## 写数据 123 to abc - file_based_writer1.write_string("abc", "123") - - file_based_writer2 = FileBasedDataWriter("/tmp") - - ## 写数据 123 to /tmp/abc - file_based_writer2.write_string("abc", "123") - - ## 写数据 123 to /tmp/logs/message.txt - file_based_writer2.write_string("/tmp/logs/message.txt", "123") - - # 初始化多桶 s3 writer - bucket = "bucket" # 替换为有效的 bucket - ak = "ak" # 替换为有效的 access key - sk = "sk" # 替换为有效的 secret key - endpoint_url = "endpoint_url" # 替换为有效的 endpoint_url - - bucket_2 = "bucket_2" # 替换为有效的 bucket - ak_2 = "ak_2" # 替换为有效的 access key - sk_2 = "sk_2" # 替换为有效的 secret key - endpoint_url_2 = "endpoint_url_2" # 替换为有效的 endpoint_url - - test_prefix = "test/unittest" - multi_bucket_s3_writer1 = MultiBucketS3DataWriter( - f"{bucket}/{test_prefix}", - [ - S3Config( - bucket_name=bucket, access_key=ak, secret_key=sk, endpoint_url=endpoint_url - ), - S3Config( - bucket_name=bucket_2, - access_key=ak_2, - secret_key=sk_2, - endpoint_url=endpoint_url_2, - ), - ], - ) - - ## 写数据 123 to s3://{bucket}/{test_prefix}/abc - multi_bucket_s3_writer1.write_string("abc", "123") - - ## 写数据 123 to s3://{bucket}/{test_prefix}/abc - multi_bucket_s3_writer1.write("abc", "123".encode()) - - ## 写数据 123 to s3://{bucket}/{test_prefix}/efg - multi_bucket_s3_writer1.write(f"s3://{bucket}/{test_prefix}/efg", "123".encode()) - - ## 写数据 123 to s3://{bucket_2}/{test_prefix}/abc - multi_bucket_s3_writer1.write(f's3://{bucket_2}/{test_prefix}/abc', '123'.encode()) - - # 初始化 s3 writer - s3_writer1 = S3DataWriter(test_prefix, bucket, ak, sk, endpoint_url) - - ## 写数据 123 to s3://{bucket}/{test_prefix}/abc - s3_writer1.write("abc", "123".encode()) - - ## 写数据 123 to s3://{bucket}/{test_prefix}/abc - s3_writer1.write_string("abc", "123") - - ## 写数据 123 to s3://{bucket}/efg - s3_writer1.write(f"s3://{bucket}/efg", "123".encode()) - diff --git a/next_docs/zh_cn/user_guide/data/dataset.rst b/next_docs/zh_cn/user_guide/data/dataset.rst deleted file mode 100644 index dcbced134a68ca52b9a402047982d7024d49b335..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/data/dataset.rst +++ /dev/null @@ -1,31 +0,0 @@ - -数据集 -====== - -导入数据类 ------------ - -数据集 -^^^^^^^^ - -每个 PDF 或图像将形成一个 Dataset。众所周知,PDF 有两种类别::ref:`TXT ` 或 :ref:`OCR ` 方法部分。从图像中可以获得 ImageDataset,它是 Dataset 的子类;从 PDF 文件中可以获得 PymuDocDataset。ImageDataset 和 PymuDocDataset 之间的区别在于 ImageDataset 仅支持 OCR 解析方法,而 PymuDocDataset 支持 OCR 和 TXT 两种方法。 - -.. note:: - - 实际上,有些 PDF 可能是由图像生成的,这意味着它们不支持 `TXT` 方法。目前,由用户保证不会调用 `TXT` 方法来解析图像生成的 PDF - -PDF 解析方法 ---------------- - -.. _ocr_method_section: - -OCR -^^^^ -通过 光学字符识别 技术提取字符。 - -.. _digital_method_section: - -TXT -^^^^^^^^ -通过第三方库提取字符,目前我们使用的是 pymupdf。 - diff --git a/next_docs/zh_cn/user_guide/data/io.rst b/next_docs/zh_cn/user_guide/data/io.rst deleted file mode 100644 index 8a2b1cac2af7d8571db57d2122f9beb73b28b316..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/data/io.rst +++ /dev/null @@ -1,21 +0,0 @@ - - -IO -==== - -旨在从不同的媒介读取或写入字节。目前,我们提供了 S3Reader 和 S3Writer 用于兼容 AWS S3 的媒介,以及 HttpReader 和 HttpWriter 用于远程 HTTP 文件。如果 MinerU 没有提供合适的类,你可以实现新的类以满足个人场景的需求。实现新的类非常容易,唯一的要求是继承自 IOReader 或 IOWriter。 - -.. code:: python - - class SomeReader(IOReader): - def read(self, path: str) -> bytes: - pass - - def read_at(self, path: str, offset: int = 0, limit: int = -1) -> bytes: - pass - - - class SomeWriter(IOWriter): - def write(self, path: str, data: bytes) -> None: - pass - diff --git a/next_docs/zh_cn/user_guide/data/read_api.rst b/next_docs/zh_cn/user_guide/data/read_api.rst deleted file mode 100644 index e2eac85e5f3a375b5029b192053d0da3019fe520..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/data/read_api.rst +++ /dev/null @@ -1,82 +0,0 @@ - - -read_api -========= - -从文件或目录读取内容以创建 Dataset。目前,我们提供了几个覆盖某些场景的函数。如果你有新的、大多数用户都会遇到的场景,可以在官方 GitHub 问题页面上发布详细描述。同时,实现你自己的读取相关函数也非常容易。 - -重要函数 ---------- - -read_jsonl -^^^^^^^^^^^^^^^^ - -从本地机器或远程 S3 上的 JSONL 文件读取内容。如果你想了解更多关于 JSONL 的信息,请参阅 :doc:`../../additional_notes/glossary`。 - -.. code:: python - - from magic_pdf.data.read_api import * - from magic_pdf.data.data_reader_writer import MultiBucketS3DataReader - from magic_pdf.data.schemas import S3Config - - # 读取本地 jsonl 文件 - datasets = read_jsonl("tt.jsonl", None) # 替换为有效的文件 - - # 读取 s3 jsonl 文件 - - bucket = "bucket_1" # 替换为有效的 s3 bucket - ak = "access_key_1" # 替换为有效的 s3 access key - sk = "secret_key_1" # 替换为有效的 s3 secret key - endpoint_url = "endpoint_url_1" # 替换为有效的 s3 endpoint url - - bucket_2 = "bucket_2" # 替换为有效的 s3 bucket - ak_2 = "access_key_2" # 替换为有效的 s3 access key - sk_2 = "secret_key_2" # 替换为有效的 s3 secret key - endpoint_url_2 = "endpoint_url_2" # 替换为有效的 s3 endpoint url - - s3configs = [ - S3Config( - bucket_name=bucket, access_key=ak, secret_key=sk, endpoint_url=endpoint_url - ), - S3Config( - bucket_name=bucket_2, - access_key=ak_2, - secret_key=sk_2, - endpoint_url=endpoint_url_2, - ), - ] - - s3_reader = MultiBucketS3DataReader(bucket, s3configs) - - datasets = read_jsonl(f"s3://bucket_1/tt.jsonl", s3_reader) # 替换为有效的 s3 jsonl file - - -read_local_pdfs -^^^^^^^^^^^^^^^^ - -从路径或目录读取 PDF 文件。 - -.. code:: python - - from magic_pdf.data.read_api import * - - # 读取 PDF 路径 - datasets = read_local_pdfs("tt.pdf") # 替换为有效的文件 - - # 读取目录下的 PDF 文件 - datasets = read_local_pdfs("pdfs/") # 替换为有效的文件目录 - -read_local_images -^^^^^^^^^^^^^^^^^^^ - -从路径或目录读取图像。 - -.. code:: python - - from magic_pdf.data.read_api import * - - # 从图像路径读取 - datasets = read_local_images("tt.png") # 替换为有效的文件 - - # 从目录读取以 suffixes 数组中指定后缀结尾的文件 - datasets = read_local_images("images/", suffixes=["png", "jpg"]) # 替换为有效的文件目录 diff --git a/next_docs/zh_cn/user_guide/install.rst b/next_docs/zh_cn/user_guide/install.rst deleted file mode 100644 index 6eabe63db161b493a0a39fa5c5fa3040856bcca2..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/install.rst +++ /dev/null @@ -1,13 +0,0 @@ - -安装 -============== - -.. toctree:: - :maxdepth: 1 - :caption: 安装文档 - - install/install - install//boost_with_cuda - install/download_model_weight_files - - diff --git a/next_docs/zh_cn/user_guide/install/boost_with_cuda.rst b/next_docs/zh_cn/user_guide/install/boost_with_cuda.rst deleted file mode 100644 index e522d24560475a5be0d91a6d886600002a200861..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/install/boost_with_cuda.rst +++ /dev/null @@ -1,272 +0,0 @@ -使用 CUDA 加速 -================ - -如果您的设备支持 CUDA 并符合主线环境的 GPU 要求,您可以使用 GPU 加速。请选择适合您系统的指南: - -- :ref:`ubuntu_22_04_lts_section` -- :ref:`windows_10_or_11_section` -- 使用 Docker 快速部署 - -.. admonition:: Important - :class: tip - - Docker 需要至少 6GB 显存的 GPU,并且所有加速功能默认启用。 - - 在运行此 Docker 容器之前,您可以使用以下命令检查您的设备是否支持 Docker 上的 CUDA 加速。 - - .. code-block:: sh - - docker run --rm --gpus=all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi - -.. code:: sh - - wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/docker/china/Dockerfile -O Dockerfile - docker build -t mineru:latest . - docker run -it --name mineru --gpus=all mineru:latest /bin/bash -c "echo 'source /opt/mineru_venv/bin/activate' >> ~/.bashrc && exec bash" - magic-pdf --help - - -.. _ubuntu_22_04_lts_section: - -Ubuntu 22.04 LTS ----------------- -1. 检测是否已安装 nvidia 驱动 ---------------------------- - -.. code:: bash - - nvidia-smi - -如果看到类似如下的信息,说明已经安装了 nvidia 驱动,可以跳过步骤2 - -.. admonition:: Important - :class: tip - - ``CUDA Version`` 显示的版本号应 >= 12.4,如显示的版本号小于12.4,请升级驱动 - -.. code:: text - - +---------------------------------------------------------------------------------------+ - | NVIDIA-SMI 570.133.07 Driver Version: 572.83 CUDA Version: 12.8 | - |-----------------------------------------+----------------------+----------------------+ - | GPU Name TCC/WDDM | Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | - | | | MIG M. | - |=========================================+======================+======================| - | 0 NVIDIA GeForce RTX 3060 Ti WDDM | 00000000:01:00.0 On | N/A | - | 0% 51C P8 12W / 200W | 1489MiB / 8192MiB | 5% Default | - | | | N/A | - +-----------------------------------------+----------------------+----------------------+ - -2. 安装驱动 ------------ - -如没有驱动,则通过如下命令 - -.. code:: bash - - sudo apt-get update - sudo apt-get install nvidia-driver-570-server - -安装专有驱动,安装完成后,重启电脑 - -.. code:: bash - - reboot - -3. 安装 anacoda --------------- - -如果已安装 conda,可以跳过本步骤 - -.. code:: bash - - wget -U NoSuchBrowser/1.0 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2024.06-1-Linux-x86_64.sh - bash Anaconda3-2024.06-1-Linux-x86_64.sh - -最后一步输入yes,关闭终端重新打开 - -4. 使用 conda 创建环境 ---------------------- - -.. code:: bash - - conda create -n mineru 'python<3.13' -y - conda activate mineru - -5. 安装应用 ------------ - -.. code:: bash - - pip install -U magic-pdf[full] -i https://mirrors.aliyun.com/pypi/simple - -.. admonition:: Important - :class: tip - - 下载完成后,务必通过以下命令确认magic-pdf的版本是否正确 - - .. code:: bash - - magic-pdf --version - - 如果版本号小于1.3.0,请到issue中向我们反馈 - -6. 下载模型 ------------ - -详细参考 :doc:`download_model_weight_files` - -7. 了解配置文件存放的位置 -------------------------- - -完成\ `6.下载模型 <#6-下载模型>`__\ 步骤后,脚本会自动生成用户目录下的magic-pdf.json文件,并自动配置默认模型路径。您可在【用户目录】下找到magic-pdf.json文件。 - -.. admonition:: Tip - :class: tip - - linux用户目录为 “/home/用户名” - -8. 第一次运行 -------------- - -从仓库中下载样本文件,并测试 - -.. code:: bash - - wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/demo/pdfs/small_ocr.pdf - magic-pdf -p small_ocr.pdf -o ./output - -9. 测试CUDA加速 ---------------- - -如果您的显卡显存大于等于 **8GB** -,可以进行以下流程,测试CUDA解析加速效果 - -**1.修改【用户目录】中配置文件 magic-pdf.json 中”device-mode”的值** - -.. code:: json - - { - "device-mode":"cuda" - } - -**2.运行以下命令测试 cuda 加速效果** - -.. code:: bash - - magic-pdf -p small_ocr.pdf -o ./output - - -.. admonition:: Tip - :class: tip - - CUDA 加速是否生效可以根据 log 中输出的各个阶段的耗时来简单判断,通常情况下,cuda应比cpu更快。 - - - -.. _windows_10_or_11_section: - -Windows 10/11 --------------- - -1. 安装 cuda 和 cuDNN ------------------- - -需要安装符合torch要求的cuda版本,torch目前支持11.8/12.4/12.6 - -- CUDA 11.8 https://developer.nvidia.com/cuda-11-8-0-download-archive -- CUDA 12.4 https://developer.nvidia.com/cuda-12-4-0-download-archive -- CUDA 12.6 https://developer.nvidia.com/cuda-12-6-0-download-archive - - -2. 安装 anaconda ---------------- - -如果已安装 conda,可以跳过本步骤 - -下载链接:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2024.06-1-Windows-x86_64.exe - -3. 使用 conda 创建环境 ---------------------- - -.. code:: bash - - conda create -n mineru 'python<3.13' -y - conda activate mineru - -4. 安装应用 ------------ - -.. code:: bash - - pip install -U magic-pdf[full] -i https://mirrors.aliyun.com/pypi/simple - -.. admonition:: Important - :class: tip - - 下载完成后,务必通过以下命令确认magic-pdf的版本是否正确 - - .. code:: bash - - magic-pdf --version - - 如果版本号小于1.3.0,请到issue中向我们反馈 - -5. 下载模型 ------------ - -详细参考 :doc:`download_model_weight_files` - -6. 了解配置文件存放的位置 -------------------------- - -完成\ `5.下载模型 <#5-下载模型>`__\ 步骤后,脚本会自动生成用户目录下的magic-pdf.json文件,并自动配置默认模型路径。您可在【用户目录】下找到 magic-pdf.json 文件。 - -.. admonition:: Tip - :class: tip - - windows 用户目录为 “C:/Users/用户名” - -7. 第一次运行 -------------- - -从仓库中下载样本文件,并测试 - -.. code:: powershell - - wget https://github.com/opendatalab/MinerU/raw/master/demo/pdfs/small_ocr.pdf -O small_ocr.pdf - magic-pdf -p small_ocr.pdf -o ./output - -8. 测试 CUDA 加速 ---------------- - -如果您的显卡显存大于等于 **8GB**,可以进行以下流程,测试 CUDA 解析加速效果 - -**1.覆盖安装支持cuda的torch和torchvision**(请根据cuda版本选择合适的index-url,具体可参考[torch官网](https://pytorch.org/get-started/locally/)) - - -.. code:: bash - - pip install --force-reinstall torch==2.6.0 torchvision==0.21.1 "numpy<2.0.0" --index-url https://download.pytorch.org/whl/cu124 - - -**2.修改【用户目录】中配置文件magic-pdf.json中”device-mode”的值** - -.. code:: json - - { - "device-mode":"cuda" - } - -**3.运行以下命令测试cuda加速效果** - -.. code:: bash - - magic-pdf -p small_ocr.pdf -o ./output - -.. admonition:: Tip - :class: tip - - CUDA 加速是否生效可以根据 log 中输出的各个阶段的耗时来简单判断,通常情况下, cuda会比cpu更快。 - diff --git a/next_docs/zh_cn/user_guide/install/download_model_weight_files.rst b/next_docs/zh_cn/user_guide/install/download_model_weight_files.rst deleted file mode 100644 index 6c2389432e720a231a8fd43efb9da53c1576428c..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/install/download_model_weight_files.rst +++ /dev/null @@ -1,64 +0,0 @@ -下载模型权重文件 -================== - -模型下载分为初始下载和更新到模型目录。请参考相应的文档以获取如何操作的指示。 - -首次下载模型文件 ------------------ - -模型文件可以从 Hugging Face 或 Model Scope下载,由于网络原因,国内用户访问HF可能会失败,请使用 ModelScope。 - - -方法一:从 Hugging Face 下载模型 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -使用python脚本 从Hugging Face下载模型文件 - -.. code:: bash - - pip install huggingface_hub - wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models_hf.py -O download_models_hf.py - python download_models_hf.py - -python脚本会自动下载模型文件并配置好配置文件中的模型目录 - -方法二:从 ModelScope 下载模型 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -使用python脚本从 ModelScope 下载模型文件 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code:: bash - - pip install modelscope - wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models.py -O download_models.py - python download_models.py - -python脚本会自动下载模型文件并配置好配置文件中的模型目录 - -配置文件可以在用户目录中找到,文件名为\ ``magic-pdf.json`` - -.. admonition:: Tip - :class: tip - - windows的用户目录为 “C:\Users\用户名”, linux用户目录为 “/home/用户名”, macOS用户目录为 “/Users/用户名” - -此前下载过模型,如何更新 --------------------- - -1. 通过 git lfs 下载过模型 -^^^^^^^^^^^^^^^^^^^^^^^ - -.. admonition:: Important - :class: tip - - 由于部分用户反馈通过git lfs下载模型文件遇到下载不全和模型文件损坏情况,现已不推荐使用该方式下载。 - - 0.9.x及以后版本由于PDF-Extract-Kit 1.0更换仓库和新增layout排序模型,不能通过 ``git pull``\命令更新,需要使用python脚本一键更新。 - -当magic-pdf <= 0.8.1时,如此前通过 git lfs 下载过模型文件,可以进入到之前的下载目录中,通过 ``git pull`` 命令更新模型。 - -2. 通过 Hugging Face 或 Model Scope 下载过模型 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -如此前通过 HuggingFace 或 Model Scope 下载过模型,可以重复执行此前的模型下载 python 脚本,将会自动将模型目录更新到最新版本。 \ No newline at end of file diff --git a/next_docs/zh_cn/user_guide/install/install.rst b/next_docs/zh_cn/user_guide/install/install.rst deleted file mode 100644 index 5bb0d083638d32980035fa70fd804ed5200836ca..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/install/install.rst +++ /dev/null @@ -1,103 +0,0 @@ - -安装 -===== - -如果您遇到任何安装问题,请首先查阅 :doc:`../../additional_notes/faq`。如果解析结果不如预期,可参考 :doc:`../../additional_notes/known_issues`。 - -.. admonition:: Warning - :class: tip - - **安装前必看——软硬件环境支持说明** - - 为了确保项目的稳定性和可靠性,我们在开发过程中仅对特定的软硬件环境进行优化和测试。这样当用户在推荐的系统配置上部署和运行项目时,能够获得最佳的性能表现和最少的兼容性问题。 - - 通过集中资源和精力于主线环境,我们团队能够更高效地解决潜在的BUG,及时开发新功能。 - - 在非主线环境中,由于硬件、软件配置的多样性,以及第三方依赖项的兼容性问题,我们无法100%保证项目的完全可用性。因此,对于希望在非推荐环境中使用本项目的用户,我们建议先仔细阅读文档以及 :doc:`../../additional_notes/faq` ,大多数问题已经在 :doc:`../../additional_notes/faq` 中有对应的解决方案,除此之外我们鼓励社区反馈问题,以便我们能够逐步扩大支持范围。 - -.. raw:: html - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    操作系统
    Linux after 2019Windows 10 / 11macOS 11+
    CPUx86_64 / arm64x86_64(暂不支持ARM Windows)x86_64 / arm64
    内存大于等于16GB,推荐32G以上
    存储空间大于等于20GB,推荐使用SSD以获得最佳性能
    python版本>=3.9,<=3.12
    Nvidia Driver 版本latest(专有驱动)latestNone
    CUDA环境11.8/12.4/12.611.8/12.4/12.6None
    CANN环境(NPU支持)8.0+(Ascend 910b)NoneNone
    GPU/MPS 硬件支持列表显存6G以上 - Volta(2017)及之后生产的全部带Tensor Core的GPU
    - 6G显存及以上
    apple slicon
    - - -创建环境 -~~~~~~~~~~ - -.. code-block:: shell - - conda create -n mineru 'python<3.13' -y - conda activate mineru - pip install -U "magic-pdf[full]" -i https://mirrors.aliyun.com/pypi/simple - - -下载模型权重文件 -~~~~~~~~~~~~~~~ - -.. code-block:: shell - - pip install huggingface_hub - wget https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/scripts/download_models_hf.py -O download_models_hf.py - python download_models_hf.py - - -MinerU 已安装,查看 :doc:`../quick_start` 或阅读 :doc:`boost_with_cuda` 以加速推理。 - diff --git a/next_docs/zh_cn/user_guide/quick_start.rst b/next_docs/zh_cn/user_guide/quick_start.rst deleted file mode 100644 index 93b1797b036c20223b72d177d727f73619fa6017..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/quick_start.rst +++ /dev/null @@ -1,13 +0,0 @@ - -快速开始 -============== - -从这里开始学习 MinerU 基本使用方法。若还没有安装,请参考安装文档进行安装 - -.. toctree:: - :maxdepth: 1 - :caption: 快速开始 - - quick_start/command_line - quick_start/to_markdown - diff --git a/next_docs/zh_cn/user_guide/quick_start/command_line.rst b/next_docs/zh_cn/user_guide/quick_start/command_line.rst deleted file mode 100644 index e50d9ffd675ade7262d59b8bfa118eefa7e96189..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/quick_start/command_line.rst +++ /dev/null @@ -1,61 +0,0 @@ - - -命令行 -======== - -.. code:: bash - - magic-pdf --help - Usage: magic-pdf [OPTIONS] - - Options: - -v, --version display the version and exit - -p, --path PATH local pdf filepath or directory [required] - -o, --output-dir PATH output local directory [required] - -m, --method [ocr|txt|auto] the method for parsing pdf. ocr: using ocr - technique to extract information from pdf. txt: - suitable for the text-based pdf only and - outperform ocr. auto: automatically choose the - best method for parsing pdf from ocr and txt. - without method specified, auto will be used by - default. - -l, --lang TEXT Input the languages in the pdf (if known) to - improve OCR accuracy. Optional. You should - input "Abbreviation" with language form url: ht - tps://paddlepaddle.github.io/PaddleOCR/en/ppocr - /blog/multi_languages.html#5-support-languages- - and-abbreviations - -d, --debug BOOLEAN Enables detailed debugging information during - the execution of the CLI commands. - -s, --start INTEGER The starting page for PDF parsing, beginning - from 0. - -e, --end INTEGER The ending page for PDF parsing, beginning from - 0. - --help Show this message and exit. - - - ## show version - magic-pdf -v - - ## command line example - magic-pdf -p {some_pdf} -o {some_output_dir} -m auto - -``{some_pdf}`` 可以是单个 PDF 文件或者一个包含多个 PDF 文件的目录。 解析的结果文件存放在目录 ``{some_output_dir}`` 下。 生成的结果文件列表如下所示: - -.. code:: text - - ├── some_pdf.md # markdown 文件 - ├── images # 存放图片目录 - ├── some_pdf_layout.pdf # layout 绘图 (包含layout阅读顺序) - ├── some_pdf_middle.json # minerU 中间处理结果 - ├── some_pdf_model.json # 模型推理结果 - ├── some_pdf_origin.pdf # 原 pdf 文件 - ├── some_pdf_spans.pdf # 最小粒度的bbox位置信息绘图 - └── some_pdf_content_list.json # 按阅读顺序排列的富文本json - - -.. admonition:: Tip - :class: tip - - 欲知更多有关结果文件的信息,请参考 :doc:`../tutorial/output_file_description` - diff --git a/next_docs/zh_cn/user_guide/quick_start/to_markdown.rst b/next_docs/zh_cn/user_guide/quick_start/to_markdown.rst deleted file mode 100644 index c4cbbb5d6d08e52e215ffc037c433602fbc31519..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/quick_start/to_markdown.rst +++ /dev/null @@ -1,134 +0,0 @@ - -转换为 Markdown 文件 -======================== - -本地文件示例 -^^^^^^^^^^^^^^^^^^ - -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import FileBasedDataWriter, FileBasedDataReader - from magic_pdf.data.dataset import PymuDocDataset - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - from magic_pdf.config.enums import SupportedPdfParseMethod - - # args - pdf_file_name = "abc.pdf" # replace with the real pdf path - name_without_suff = pdf_file_name.split(".")[0] - - # prepare env - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - os.makedirs(local_image_dir, exist_ok=True) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter( - local_md_dir - ) - image_dir = str(os.path.basename(local_image_dir)) - - # read bytes - reader1 = FileBasedDataReader("") - pdf_bytes = reader1.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ## inference - if ds.classify() == SupportedPdfParseMethod.OCR: - infer_result = ds.apply(doc_analyze, ocr=True) - - ## pipeline - pipe_result = infer_result.pipe_ocr_mode(image_writer) - - else: - infer_result = ds.apply(doc_analyze, ocr=False) - - ## pipeline - pipe_result = infer_result.pipe_txt_mode(image_writer) - - ### draw model result on each page - infer_result.draw_model(os.path.join(local_md_dir, f"{name_without_suff}_model.pdf")) - - ### draw layout result on each page - pipe_result.draw_layout(os.path.join(local_md_dir, f"{name_without_suff}_layout.pdf")) - - ### draw spans result on each page - pipe_result.draw_span(os.path.join(local_md_dir, f"{name_without_suff}_spans.pdf")) - - ### dump markdown - pipe_result.dump_md(md_writer, f"{name_without_suff}.md", image_dir) - - ### dump content list - pipe_result.dump_content_list(md_writer, f"{name_without_suff}_content_list.json", image_dir) - - -对象存储文件示例 -^^^^^^^^^^^^^^^^ - -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import S3DataReader, S3DataWriter - from magic_pdf.data.dataset import PymuDocDataset - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - - bucket_name = "{Your S3 Bucket Name}" # replace with real bucket name - ak = "{Your S3 access key}" # replace with real s3 access key - sk = "{Your S3 secret key}" # replace with real s3 secret key - endpoint_url = "{Your S3 endpoint_url}" # replace with real s3 endpoint_url - - - reader = S3DataReader('unittest/tmp/', bucket_name, ak, sk, endpoint_url) # replace `unittest/tmp` with the real s3 prefix - writer = S3DataWriter('unittest/tmp', bucket_name, ak, sk, endpoint_url) - image_writer = S3DataWriter('unittest/tmp/images', bucket_name, ak, sk, endpoint_url) - - # args - pdf_file_name = ( - "s3://llm-pdf-text-1/unittest/tmp/bug5-11.pdf" # replace with the real s3 path - ) - - # prepare env - local_dir = "output" - name_without_suff = os.path.basename(pdf_file_name).split(".")[0] - - # read bytes - pdf_bytes = reader.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ## inference - if ds.classify() == SupportedPdfParseMethod.OCR: - infer_result = ds.apply(doc_analyze, ocr=True) - - ## pipeline - pipe_result = infer_result.pipe_ocr_mode(image_writer) - - else: - infer_result = ds.apply(doc_analyze, ocr=False) - - ## pipeline - pipe_result = infer_result.pipe_txt_mode(image_writer) - - ### draw model result on each page - infer_result.draw_model(os.path.join(local_dir, f'{name_without_suff}_model.pdf')) # dump to local - - ### draw layout result on each page - pipe_result.draw_layout(os.path.join(local_dir, f'{name_without_suff}_layout.pdf')) # dump to local - - ### draw spans result on each page - pipe_result.draw_span(os.path.join(local_dir, f'{name_without_suff}_spans.pdf')) # dump to local - - ### dump markdown - pipe_result.dump_md(writer, f'{name_without_suff}.md', "unittest/tmp/images") # dump to remote s3 - - ### dump content list - pipe_result.dump_content_list(md_writer, f"{name_without_suff}_content_list.json", image_dir) - -前去 :doc:`../data/data_reader_writer` 获取更多有关 **读写** 示例 diff --git a/next_docs/zh_cn/user_guide/tutorial.rst b/next_docs/zh_cn/user_guide/tutorial.rst deleted file mode 100644 index 9beeb6c33f51fdbf2dc2cdf3c8c0f360a95df8ee..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/tutorial.rst +++ /dev/null @@ -1,13 +0,0 @@ - -教程 -=========== - -让我们通过构建一个最小项目来学习 MinerU - -.. toctree:: - :maxdepth: 1 - :caption: 教程 - - tutorial/output_file_description - tutorial/pipeline - diff --git a/next_docs/zh_cn/user_guide/tutorial/output_file_description.rst b/next_docs/zh_cn/user_guide/tutorial/output_file_description.rst deleted file mode 100644 index 9618e28662462f7fb2cdc9f74faa32d888dc45c4..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/tutorial/output_file_description.rst +++ /dev/null @@ -1,386 +0,0 @@ - -输出文件格式介绍 -=============== - -``magic-pdf`` 命令执行后除了输出和 markdown -有关的文件以外,还会生成若干个和 markdown -无关的文件。现在将一一介绍这些文件 - -some_pdf_layout.pdf -~~~~~~~~~~~~~~~~~~~ - -每一页的 layout 均由一个或多个框组成。 -每个框左上脚的数字表明它们的序号。此外 layout.pdf -框内用不同的背景色块圈定不同的内容块。 - -.. figure:: ../../_static/image/layout_example.png - :alt: layout 页面示例 - - layout 页面示例 - -some_pdf_spans.pdf -~~~~~~~~~~~~~~~~~~ - -根据 span 类型的不同,采用不同颜色线框绘制页面上所有 -span。该文件可以用于质检,可以快速排查出文本丢失、行间公式未识别等问题。 - -.. figure:: ../../_static/image/spans_example.png - :alt: span 页面示例 - - span 页面示例 - -some_pdf_model.json -~~~~~~~~~~~~~~~~~~~ - -结构定义 -^^^^^^^^ - -.. code:: python - - from pydantic import BaseModel, Field - from enum import IntEnum - - class CategoryType(IntEnum): - title = 0 # 标题 - plain_text = 1 # 文本 - abandon = 2 # 包括页眉页脚页码和页面注释 - figure = 3 # 图片 - figure_caption = 4 # 图片描述 - table = 5 # 表格 - table_caption = 6 # 表格描述 - table_footnote = 7 # 表格注释 - isolate_formula = 8 # 行间公式 - formula_caption = 9 # 行间公式的标号 - - embedding = 13 # 行内公式 - isolated = 14 # 行间公式 - text = 15 # ocr 识别结果 - - - class PageInfo(BaseModel): - page_no: int = Field(description="页码序号,第一页的序号是 0", ge=0) - height: int = Field(description="页面高度", gt=0) - width: int = Field(description="页面宽度", ge=0) - - class ObjectInferenceResult(BaseModel): - category_id: CategoryType = Field(description="类别", ge=0) - poly: list[float] = Field(description="四边形坐标, 分别是 左上,右上,右下,左下 四点的坐标") - score: float = Field(description="推理结果的置信度") - latex: str | None = Field(description="latex 解析结果", default=None) - html: str | None = Field(description="html 解析结果", default=None) - - class PageInferenceResults(BaseModel): - layout_dets: list[ObjectInferenceResult] = Field(description="页面识别结果", ge=0) - page_info: PageInfo = Field(description="页面元信息") - - - # 所有页面的推理结果按照页码顺序依次放到列表中即为 minerU 推理结果 - inference_result: list[PageInferenceResults] = [] - -poly 坐标的格式 [x0, y0, x1, y1, x2, y2, x3, y3], -分别表示左上、右上、右下、左下四点的坐标 |poly 坐标示意图| - -示例数据 -^^^^^^^^ - -.. code:: json - - [ - { - "layout_dets": [ - { - "category_id": 2, - "poly": [ - 99.1906967163086, - 100.3119125366211, - 730.3707885742188, - 100.3119125366211, - 730.3707885742188, - 245.81326293945312, - 99.1906967163086, - 245.81326293945312 - ], - "score": 0.9999997615814209 - } - ], - "page_info": { - "page_no": 0, - "height": 2339, - "width": 1654 - } - }, - { - "layout_dets": [ - { - "category_id": 5, - "poly": [ - 99.13092803955078, - 2210.680419921875, - 497.3183898925781, - 2210.680419921875, - 497.3183898925781, - 2264.78076171875, - 99.13092803955078, - 2264.78076171875 - ], - "score": 0.9999997019767761 - } - ], - "page_info": { - "page_no": 1, - "height": 2339, - "width": 1654 - } - } - ] - -some_pdf_middle.json -~~~~~~~~~~~~~~~~~~~~ - -+--------------------+----------------------------------------------------------+ -| 字段名 | 解释 | -+====================+==========================================================+ -| pdf_info | list,每个元素都是一个 | -| | dict,这个dict是每一页pdf的解析结果,详见下表 | -+--------------------+----------------------------------------------------------+ -| \_parse_type | ocr \| txt,用来标识本次解析的中间态使用的模式 | -+--------------------+----------------------------------------------------------+ -| \_version_name | string,表示本次解析使用的 magic-pdf 的版本号 | -+-------------------------------------------------------------------------------+ - -**pdf_info** 字段结构说明 - -+---------------------+-------------------------------------------------------+ -| 字段名 | 解释 | -+=====================+=======================================================+ -| preproc_blocks | pdf预处理后,未分段的中间结果 | -+---------------------+-------------------------------------------------------+ -| | 布局分割的结果, | -| layout_bboxes | 含有布局的方向(垂直、水平),和bbox,按阅读顺序排序 | -+---------------------+-------------------------------------------------------+ -| page_idx | 页码,从0开始 | -+---------------------+-------------------------------------------------------+ -| page_size | 页面的宽度和高度 | -+---------------------+-------------------------------------------------------+ -| \_layout_tree | 布局树状结构 | -+---------------------+-------------------------------------------------------+ -| images | list,每个元素是一个dict,每个dict表示一个img_block | -+---------------------+-------------------------------------------------------+ -| tables | list,每个元素是一个dict,每个dict表示一个table_block | -+---------------------+-------------------------------------------------------+ -| | list,每个元素是一个 | -| interline_equations | dict,每个dict表示一个interline_equation_block | -+---------------------+-------------------------------------------------------+ -| | List, 模型返回的需要drop的block信息 | -| discarded_blocks | | -+---------------------+-------------------------------------------------------+ -| para_blocks | 将preproc_blocks进行分段之后的结果 | -+---------------------+-------------------------------------------------------+ - -上表中 ``para_blocks`` -是个dict的数组,每个dict是一个block结构,block最多支持一次嵌套 - -**block** - -外层block被称为一级block,一级block中的字段包括 - -====== =============================================== -字段名 解释 -====== =============================================== -type block类型(table|image) -bbox block矩形框坐标 -blocks list,里面的每个元素都是一个dict格式的二级block -====== =============================================== - -一级block只有”table”和”image”两种类型,其余block均为二级block - -二级block中的字段包括 - -+----------+----------------------------------------------------------------+ -| 字 | 解释 | -| 段 | | -| 名 | | -+==========+================================================================+ -| | block类型 | -| type | | -+----------+----------------------------------------------------------------+ -| bbox | block矩形框坐标 | -+----------+----------------------------------------------------------------+ -| lines | list,每个元素都是一个dict表示的line,用来描述一行信息的构成 | -+----------+----------------------------------------------------------------+ - -二级block的类型详解 - -================== ============== -type desc -================== ============== -image_body 图像的本体 -image_caption 图像的描述文本 -image_footnote 图像的脚注 -table_body 表格本体 -table_caption 表格的描述文本 -table_footnote 表格的脚注 -text 文本块 -title 标题块 -index 目录块 -list 列表块 -interline_equation 行间公式块 -================== ============== - -**line** - -line 的 字段格式如下 - -+-----------+-----------------------------------------------------------------+ -| 字 | 解释 | -| 段 | | -| 名 | | -+===========+=================================================================+ -| bbox | line的矩形框坐标 | -+-----------+-----------------------------------------------------------------+ -| spans | list, | -| | 每个元素都是一个dict表示的span,用来描述一个最小组成单元的构成 | -+-----------+-----------------------------------------------------------------+ - -**span** - -+------------+---------------------------------------------------------+ -| 字段名 | 解释 | -+============+=========================================================+ -| bbox | span的矩形框坐标 | -+------------+---------------------------------------------------------+ -| type | span的类型 | -+------------+---------------------------------------------------------+ -| content \| | 文本类型的span使用content,图表类使用img_path | -| img_path | 用来存储实际的文本或者截图路径信息 | -+------------+---------------------------------------------------------+ - -span 的类型有如下几种 - -================== ======== -type desc -================== ======== -image 图片 -table 表格 -text 文本 -inline_equation 行内公式 -interline_equation 行间公式 -================== ======== - -**总结** - -span是所有元素的最小存储单元 - -para_blocks内存储的元素为区块信息 - -区块结构为 - -一级block(如有)->二级block->line->span - -.. _示例数据-1: - -示例数据 -^^^^^^^^ - -.. code:: json - - { - "pdf_info": [ - { - "preproc_blocks": [ - { - "type": "text", - "bbox": [ - 52, - 61.956024169921875, - 294, - 82.99800872802734 - ], - "lines": [ - { - "bbox": [ - 52, - 61.956024169921875, - 294, - 72.0000228881836 - ], - "spans": [ - { - "bbox": [ - 54.0, - 61.956024169921875, - 296.2261657714844, - 72.0000228881836 - ], - "content": "dependent on the service headway and the reliability of the departure ", - "type": "text", - "score": 1.0 - } - ] - } - ] - } - ], - "layout_bboxes": [ - { - "layout_bbox": [ - 52, - 61, - 294, - 731 - ], - "layout_label": "V", - "sub_layout": [] - } - ], - "page_idx": 0, - "page_size": [ - 612.0, - 792.0 - ], - "_layout_tree": [], - "images": [], - "tables": [], - "interline_equations": [], - "discarded_blocks": [], - "para_blocks": [ - { - "type": "text", - "bbox": [ - 52, - 61.956024169921875, - 294, - 82.99800872802734 - ], - "lines": [ - { - "bbox": [ - 52, - 61.956024169921875, - 294, - 72.0000228881836 - ], - "spans": [ - { - "bbox": [ - 54.0, - 61.956024169921875, - 296.2261657714844, - 72.0000228881836 - ], - "content": "dependent on the service headway and the reliability of the departure ", - "type": "text", - "score": 1.0 - } - ] - } - ] - } - ] - } - ], - "_parse_type": "txt", - "_version_name": "0.6.1" - } - -.. |poly 坐标示意图| image:: ../../_static/image/poly.png diff --git a/next_docs/zh_cn/user_guide/tutorial/pipeline.rst b/next_docs/zh_cn/user_guide/tutorial/pipeline.rst deleted file mode 100644 index c8adaa3e2f69858e0099f499623fd5593c4eb156..0000000000000000000000000000000000000000 --- a/next_docs/zh_cn/user_guide/tutorial/pipeline.rst +++ /dev/null @@ -1,179 +0,0 @@ - -流水线管道 -=========== - - -极简示例 -^^^^^^^^ - -.. code:: python - - import os - - from magic_pdf.data.data_reader_writer import FileBasedDataWriter, FileBasedDataReader - from magic_pdf.data.dataset import PymuDocDataset - from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze - - # args - pdf_file_name = "abc.pdf" # replace with the real pdf path - name_without_suff = pdf_file_name.split(".")[0] - - # prepare env - local_image_dir, local_md_dir = "output/images", "output" - image_dir = str(os.path.basename(local_image_dir)) - - os.makedirs(local_image_dir, exist_ok=True) - - image_writer, md_writer = FileBasedDataWriter(local_image_dir), FileBasedDataWriter( - local_md_dir - ) - image_dir = str(os.path.basename(local_image_dir)) - - # read bytes - reader1 = FileBasedDataReader("") - pdf_bytes = reader1.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md(md_writer, f"{name_without_suff}.md", image_dir) - - -运行以上的代码,会得到如下的结果 - -.. code:: bash - - output/ - ├── abc.md - └── images - - -除去初始化环境,如建立目录、导入依赖库等逻辑。真正将 ``pdf`` 转换为 ``markdown`` 的代码片段如下 - -.. code:: - - # read bytes - reader1 = FileBasedDataReader("") - pdf_bytes = reader1.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md(md_writer, f"{name_without_suff}.md", image_dir) - - -``ds.apply(doc_analyze, ocr=True)`` 会生成 ``InferenceResult`` 对象。 ``InferenceResult`` 对象执行 ``pipe_ocr_mode`` 方法会生成 ``PipeResult`` 对象。 -``PipeResult`` 对象执行 ``dump_md`` 会在指定位置生成 ``markdown`` 文件。 - - -pipeline 的执行过程如下图所示 - -.. image:: ../../_static/image/pipeline.drawio.svg - -.. raw:: html - -

    - -目前划分出数据、推理、程序处理三个阶段,分别对应着图上的 ``Dataset``, ``InferenceResult``, ``PipeResult`` 这三个实体。通过 ``apply`` , ``doc_analyze`` 或 ``pipe_ocr_mode`` 等方法链接在一起。 - - -.. admonition:: Tip - :class: tip - - 要想获得更多有关 Dataset、InferenceResult、PipeResult 的使用示例子,请前往 :doc:`../quick_start/to_markdown` - - 要想获得更多有关 Dataset、InferenceResult、PipeResult 的细节信息请前往英文版 MinerU 文档进行查看! - - - -管道组合 -^^^^^^^^^ - -.. code:: python - - class Dataset(ABC): - @abstractmethod - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(self, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - pass - - class InferenceResult(InferenceResultBase): - - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(inference_result, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - return proc(copy.deepcopy(self._infer_res), *args, **kwargs) - - def pipe_ocr_mode( - self, - imageWriter: DataWriter, - start_page_id=0, - end_page_id=None, - debug_mode=False, - lang=None, - ) -> PipeResult: - pass - - class PipeResult: - def apply(self, proc: Callable, *args, **kwargs): - """Apply callable method which. - - Args: - proc (Callable): invoke proc as follows: - proc(pipeline_result, *args, **kwargs) - - Returns: - Any: return the result generated by proc - """ - return proc(copy.deepcopy(self._pipe_res), *args, **kwargs) - -``Dataset`` 、 ``InferenceResult`` 和 ``PipeResult`` 类均有 ``apply`` method。可用于组合不同阶段的运算过程。 -如下所示,``MinerU`` 提供一套组合这些类的计算过程。 - -.. code:: python - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - ds.apply(doc_analyze, ocr=True).pipe_ocr_mode(image_writer).dump_md(md_writer, f"{name_without_suff}.md", image_dir) - -用户可以根据的需求,自行实现一些组合用的函数。比如用户通过 ``apply`` 方法实现一个统计 ``pdf`` 文件页数的功能。 - -.. code:: python - - from magic_pdf.data.data_reader_writer import FileBasedDataReader - from magic_pdf.data.dataset import PymuDocDataset - - # args - pdf_file_name = "abc.pdf" # replace with the real pdf path - - # read bytes - reader1 = FileBasedDataReader("") - pdf_bytes = reader1.read(pdf_file_name) # read the pdf content - - # proc - ## Create Dataset Instance - ds = PymuDocDataset(pdf_bytes) - - def count_page(ds)-> int: - return len(ds) - - print("page number: ", ds.apply(count_page)) # will output the page count of `abc.pdf` diff --git a/projects/README.md b/projects/README.md index 915af5275cb45ee33bb16f3f193d2d0e334f6036..66ac5966ba61871e9f27b422233cfc81e87a9f06 100644 --- a/projects/README.md +++ b/projects/README.md @@ -2,8 +2,10 @@ ## Project List -- [llama_index_rag](./llama_index_rag/README.md): Build a lightweight RAG system based on llama_index -- [gradio_app](./gradio_app/README.md): Build a web app based on gradio -- ~~[web_demo](./web_demo/README.md): MinerU online [demo](https://opendatalab.com/OpenSourceTools/Extractor/PDF/) localized deployment version~~(Deprecated) -- [web_api](./web_api/README.md): Web API Based on FastAPI -- [multi_gpu](./multi_gpu/README.md): Multi-GPU parallel processing based on LitServe +- Projects compatible with version 2.0: + - [gradio_app](./gradio_app/README.md): Web application based on Gradio + +- Projects not yet compatible with version 2.0: + - [web_api](./web_api/README.md): Web API based on FastAPI + - [multi_gpu](./multi_gpu/README.md): Multi-GPU parallel processing based on LitServe + diff --git a/projects/README_zh-CN.md b/projects/README_zh-CN.md index 870b5ea7be3f0210ca18ddc0f80f825b89cfae57..5d4a5ae785aa2b974ac490741fdf61c9edacec55 100644 --- a/projects/README_zh-CN.md +++ b/projects/README_zh-CN.md @@ -2,8 +2,9 @@ ## 项目列表 -- [llama_index_rag](./llama_index_rag/README_zh-CN.md): 基于 llama_index 构建轻量级 RAG 系统 -- [gradio_app](./gradio_app/README_zh-CN.md): 基于 Gradio 的 Web 应用 -- ~~[web_demo](./web_demo/README_zh-CN.md): MinerU在线[demo](https://opendatalab.com/OpenSourceTools/Extractor/PDF/)本地化部署版本~~(已过时) -- [web_api](./web_api/README.md): 基于 FastAPI 的 Web API -- [multi_gpu](./multi_gpu/README.md): 基于 LitServe 的多 GPU 并行处理 +- 已兼容2.0版本的项目列表 + - [gradio_app](./gradio_app/README_zh-CN.md): 基于 Gradio 的 Web 应用 + +- 未兼容2.0版本的项目列表 + - [web_api](./web_api/README.md): 基于 FastAPI 的 Web API + - [multi_gpu](./multi_gpu/README.md): 基于 LitServe 的多 GPU 并行处理 diff --git a/projects/gradio_app/app.py b/projects/gradio_app/app.py index 180fd7e2101f4c8ce49f121a81e54e1349b7e3d0..92d8d5b7abc2c5352893066c0eef1e9bd31dcc06 100644 --- a/projects/gradio_app/app.py +++ b/projects/gradio_app/app.py @@ -4,30 +4,22 @@ import base64 import os import re import time -import uuid import zipfile from pathlib import Path import gradio as gr -import pymupdf from gradio_pdf import PDF from loguru import logger -from magic_pdf.data.data_reader_writer import FileBasedDataReader -from magic_pdf.libs.hash_utils import compute_sha256 -from magic_pdf.tools.common import do_parse, prepare_env +from mineru.cli.common import prepare_env, do_parse, read_fn +from mineru.utils.hash_utils import str_sha256 -def read_fn(path): - disk_rw = FileBasedDataReader(os.path.dirname(path)) - return disk_rw.read(os.path.basename(path)) - - -def parse_pdf(doc_path, output_dir, end_page_id, is_ocr, layout_mode, formula_enable, table_enable, language): +def parse_pdf(doc_path, output_dir, end_page_id, is_ocr, formula_enable, table_enable, language): os.makedirs(output_dir, exist_ok=True) try: - file_name = f'{str(Path(doc_path).stem)}_{time.time()}' + file_name = f'{str(Path(doc_path).stem)}_{time.strftime("%y%m%d_%H%M%S")}' pdf_data = read_fn(doc_path) if is_ocr: parse_method = 'ocr' @@ -35,17 +27,14 @@ def parse_pdf(doc_path, output_dir, end_page_id, is_ocr, layout_mode, formula_en parse_method = 'auto' local_image_dir, local_md_dir = prepare_env(output_dir, file_name, parse_method) do_parse( - output_dir, - file_name, - pdf_data, - [], - parse_method, - False, + output_dir=output_dir, + pdf_file_names=[file_name], + pdf_bytes_list=[pdf_data], + p_lang_list=[language], + parse_method=parse_method, end_page_id=end_page_id, - layout_model=layout_mode, - formula_enable=formula_enable, - table_enable=table_enable, - lang=language, + p_formula_enable=formula_enable, + p_table_enable=table_enable, ) return local_md_dir, file_name except Exception as e: @@ -96,12 +85,11 @@ def replace_image_with_base64(markdown_text, image_dir_path): return re.sub(pattern, replace, markdown_text) -def to_markdown(file_path, end_pages, is_ocr, layout_mode, formula_enable, table_enable, language): +def to_markdown(file_path, end_pages, is_ocr, formula_enable, table_enable, language): file_path = to_pdf(file_path) # 获取识别的md文件以及压缩包文件路径 - local_md_dir, file_name = parse_pdf(file_path, './output', end_pages - 1, is_ocr, - layout_mode, formula_enable, table_enable, language) - archive_zip_path = os.path.join('./output', compute_sha256(local_md_dir) + '.zip') + local_md_dir, file_name = parse_pdf(file_path, './output', end_pages - 1, is_ocr, formula_enable, table_enable, language) + archive_zip_path = os.path.join('./output', str_sha256(local_md_dir) + '.zip') zip_archive_success = compress_directory_to_zip(local_md_dir, archive_zip_path) if zip_archive_success == 0: logger.info('压缩成功') @@ -125,24 +113,6 @@ latex_delimiters = [ ] -def init_model(): - from magic_pdf.model.doc_analyze_by_custom_model import ModelSingleton - try: - model_manager = ModelSingleton() - txt_model = model_manager.get_model(False, False) # noqa: F841 - logger.info('txt_model init final') - ocr_model = model_manager.get_model(True, False) # noqa: F841 - logger.info('ocr_model init final') - return 0 - except Exception as e: - logger.exception(e) - return -1 - - -model_init = init_model() -logger.info(f'model_init: {model_init}') - - with open('header.html', 'r') as file: header = file.read() @@ -171,24 +141,30 @@ all_lang = [] all_lang.extend([*other_lang, *add_lang]) +def safe_stem(file_path): + stem = Path(file_path).stem + # 只保留字母、数字、下划线和点,其他字符替换为下划线 + return re.sub(r'[^\w.]', '_', stem) + + def to_pdf(file_path): - with pymupdf.open(file_path) as f: - if f.is_pdf: - return file_path - else: - pdf_bytes = f.convert_to_pdf() - # 将pdfbytes 写入到uuid.pdf中 - # 生成唯一的文件名 - unique_filename = f'{uuid.uuid4()}.pdf' - # 构建完整的文件路径 - tmp_file_path = os.path.join(os.path.dirname(file_path), unique_filename) + if file_path is None: + return None + + pdf_bytes = read_fn(file_path) - # 将字节数据写入文件 - with open(tmp_file_path, 'wb') as tmp_pdf_file: - tmp_pdf_file.write(pdf_bytes) + # unique_filename = f'{uuid.uuid4()}.pdf' + unique_filename = f'{safe_stem(file_path)}.pdf' - return tmp_file_path + # 构建完整的文件路径 + tmp_file_path = os.path.join(os.path.dirname(file_path), unique_filename) + + # 将字节数据写入文件 + with open(tmp_file_path, 'wb') as tmp_pdf_file: + tmp_pdf_file.write(pdf_bytes) + + return tmp_file_path if __name__ == '__main__': @@ -196,14 +172,16 @@ if __name__ == '__main__': gr.HTML(header) with gr.Row(): with gr.Column(variant='panel', scale=5): - file = gr.File(label='Please upload a PDF or image', file_types=['.pdf', '.png', '.jpeg', '.jpg']) - max_pages = gr.Slider(1, 20, 10, step=1, label='Max convert pages') with gr.Row(): - layout_mode = gr.Dropdown(['doclayout_yolo'], label='Layout model', value='doclayout_yolo') - language = gr.Dropdown(all_lang, label='Language', value='ch') + file = gr.File(label='Please upload a PDF or image', file_types=['.pdf', '.png', '.jpeg', '.jpg']) + with gr.Row(equal_height=True): + with gr.Column(scale=4): + max_pages = gr.Slider(1, 20, 10, step=1, label='Max convert pages') + with gr.Column(scale=1): + language = gr.Dropdown(all_lang, label='Language', value='ch') with gr.Row(): - formula_enable = gr.Checkbox(label='Enable formula recognition', value=True) is_ocr = gr.Checkbox(label='Force enable OCR', value=False) + formula_enable = gr.Checkbox(label='Enable formula recognition', value=True) table_enable = gr.Checkbox(label='Enable table recognition(test)', value=True) with gr.Row(): change_bu = gr.Button('Convert') @@ -227,7 +205,7 @@ if __name__ == '__main__': with gr.Tab('Markdown text'): md_text = gr.TextArea(lines=45, show_copy_button=True) file.change(fn=to_pdf, inputs=file, outputs=pdf_show) - change_bu.click(fn=to_markdown, inputs=[file, max_pages, is_ocr, layout_mode, formula_enable, table_enable, language], + change_bu.click(fn=to_markdown, inputs=[file, max_pages, is_ocr, formula_enable, table_enable, language], outputs=[md, md_text, output_file, pdf_show]) clear_bu.add([file, md, pdf_show, md_text, output_file, is_ocr]) diff --git a/projects/llama_index_rag/README.md b/projects/llama_index_rag/README.md deleted file mode 100644 index 57cd9aeb4ba7518370fa7d14e9ba85451c888c5f..0000000000000000000000000000000000000000 --- a/projects/llama_index_rag/README.md +++ /dev/null @@ -1,160 +0,0 @@ -## Installation - -MinerU - -```bash -git clone https://github.com/opendatalab/MinerU.git -cd MinerU - -conda create -n MinerU python=3.10 -conda activate MinerU -pip install .[full] --extra-index-url https://wheels.myhloli.com -``` - -Third-party software - -```bash -# install -pip install llama-index-vector-stores-elasticsearch==0.2.0 -pip install llama-index-embeddings-dashscope==0.2.0 -pip install llama-index-core==0.10.68 -pip install einops==0.7.0 -pip install transformers-stream-generator==0.0.5 -pip install accelerate==0.33.0 - -# uninstall -pip uninstall transformer-engine -``` - -## Environment Configuration - -``` -export DASHSCOPE_API_KEY={some_key} -export ES_USER={some_es_user} -export ES_PASSWORD={some_es_password} -export ES_URL=http://{es_url}:9200 -``` -For instructions on obtaining a DASHSCOPE_API_KEY, refer to [documentation](https://help.aliyun.com/zh/dashscope/opening-service) - -## Usage - -### Data Ingestion - -```bash -python data_ingestion.py -p some.pdf # load data from pdf - - or - -python data_ingestion.py -p /opt/data/some_pdf_directory/ # load data from multiples pdf which under the directory of {some_pdf_directory} -``` - -### Query - -```bash -python query.py --question '{the_question_you_want_to_ask}' -``` - -## Example - -````bash -# Start the es service -docker compose up -d - -or - -docker-compose up -d - - -# Set environment variables -export ES_USER=elastic -export ES_PASSWORD=llama_index -export ES_URL=http://127.0.0.1:9200 -export DASHSCOPE_API_KEY={some_key} - - -# Ingest data -python data_ingestion.py example/data/declaration_of_the_rights_of_man_1789.pdf - - -# Ask a question -python query.py -q 'how about the rights of men' - -## outputs -Please answer the question based on the content within ```: - ``` - I. Men are born, and always continue, free and equal in respect of their rights. Civil distinctions, therefore, can be founded only on public utility. - ``` - My question is:how about the rights of men。 - -question: how about the rights of men -answer: The statement implies that men are born free and equal in terms of their rights. Civil distinctions should only be based on public utility. However, it does not specify what those rights are. It is up to society and individual countries to determine and protect the specific rights of their citizens. - -```` - -## Development - -`MinerU` provides a `RAG` integration interface, allowing users to specify a single input `pdf` file or a directory. `MinerU` will automatically parse the input files and return an iterable interface for retrieving the data. - - -### API Interface - -```python -from magic_pdf.integrations.rag.type import Node - -class RagPageReader: - def get_rel_map(self) -> list[ElementRelation]: - # Retrieve the relationships between nodes - pass - ... - -class RagDocumentReader: - ... - -class DataReader: - def __init__(self, path_or_directory: str, method: str, output_dir: str): - pass - - def get_documents_count(self) -> int: - """Get the number of pdf documents""" - pass - - def get_document_result(self, idx: int) -> RagDocumentReader | None: - """Retrieve the parsed content of a specific pdf""" - pass - - - def get_document_filename(self, idx: int) -> Path: - """Retrieve the path of a specific pdf""" - pass - - -``` - -Type Definitions - -```python - - -class Node(BaseModel): - category_type: CategoryType = Field(description='Category') # Category - text: str | None = Field(description='Text content', default=None) - image_path: str | None = Field(description='Path to image or table (table may be stored as an image)', default=None) - anno_id: int = Field(description='Unique ID', default=-1) - latex: str | None = Field(description='LaTeX output for equations or tables', default=None) - html: str | None = Field(description='HTML output for tables', default=None) - - - -``` - -Tables can be stored in one of three formats: image, LaTeX, or HTML. -`anno_id` is a globally unique ID for each Node. It can be used later to match this Node with other Nodes. The relationships between nodes can be retrieved using the `get_rel_map` method. Users can use `anno_id` to link nodes and construct a RAG index that includes node relationships. - - -### Node Relationship Matrix - -| | image_body | table_body | -| -------------- | ---------- | ---------- | -| image_caption | sibling | | -| table_caption | | sibling | -| table_footnote | | sibling | diff --git a/projects/llama_index_rag/README_zh-CN.md b/projects/llama_index_rag/README_zh-CN.md deleted file mode 100644 index 4d3bf005b4aecbed206ae72ecaa55a012cc78447..0000000000000000000000000000000000000000 --- a/projects/llama_index_rag/README_zh-CN.md +++ /dev/null @@ -1,199 +0,0 @@ -
    -

    目录

    -
  • 介绍
  • -
  • 安装
  • -
  • 示例
  • -
  • 开发
  • - -
    - -## 介绍 - -`MinerU` 提供数据 `API接口` 以支持用户导入数据到 `RAG` 系统。本项目将基于`通义千问`展示如何构建一个轻量级的 `RAG` 系统。 - -

    - -

    - -## 安装 - -环境要求 - -```text -NVIDIA A100 80GB, -Centos 7 3.10.0-957.el7.x86_64 - -Client: Docker Engine - Community - Version: 24.0.5 - API version: 1.43 - Go version: go1.20.6 - Git commit: ced0996 - Built: Fri Jul 21 20:39:02 2023 - OS/Arch: linux/amd64 - Context: default - -Server: Docker Engine - Community - Engine: - Version: 24.0.5 - API version: 1.43 (minimum version 1.12) - Go version: go1.20.6 - Git commit: a61e2b4 - Built: Fri Jul 21 20:38:05 2023 - OS/Arch: linux/amd64 - Experimental: false - containerd: - Version: 1.6.25 - GitCommit: d8f198a4ed8892c764191ef7b3b06d8a2eeb5c7f - runc: - Version: 1.1.10 - GitCommit: v1.1.10-0-g18a0cb0 - docker-init: - Version: 0.19.0 - GitCommit: de40ad0 -``` - -请参考[文档](../../README_zh-CN.md) 安装 MinerU - -第三方软件 - -```bash -# install -pip install modelscope==1.14.0 -pip install llama-index-vector-stores-elasticsearch==0.2.0 -pip install llama-index-embeddings-dashscope==0.2.0 -pip install llama-index-core==0.10.68 -pip install einops==0.7.0 -pip install transformers-stream-generator==0.0.5 -pip install accelerate==0.33.0 - -# uninstall -pip uninstall transformer-engine -``` - - -## 示例 - -````bash -cd projects/llama_index_rag - -docker compose up -d - -or - -docker-compose up -d - - -# 配置环境变量 - -export ES_USER=elastic -export ES_PASSWORD=llama_index -export ES_URL=http://127.0.0.1:9200 -export DASHSCOPE_API_KEY={some_key} - - -DASHSCOPE_API_KEY 开通参考[文档](https://help.aliyun.com/zh/dashscope/opening-service) - -# 未导入数据,查询问题。返回通义千问默认答案 -python query.py -q 'how about the rights of men' - -## outputs -question: how about the rights of men -answer: The topic of men's rights often refers to discussions around legal, social, and political issues that affect men specifically or differently from women. Movements related to men's rights advocate for addressing areas where men face discrimination or unique challenges, such as: - - Child Custody: Ensuring that men have equal opportunities for custody of their children following divorce or separation. - Domestic Violence: Recognizing that men can also be victims of domestic abuse and ensuring they have access to support services. - Mental Health and Suicide Rates: Addressing the higher rates of suicide among men and providing mental health resources. - Military Conscription: In some countries, only men are required to register for military service, which is seen as a gender-based obligation. - Workplace Safety: Historically, more men than women have been employed in high-risk occupations, leading to higher workplace injury and death rates. - Parental Leave: Advocating for paternity leave policies that allow men to take time off work for family care. - Men's rights activism often intersects with broader discussions on gender equality and aims to promote fairness and equity across genders. It's important to note that while advocating for these issues, it should be done in a way that does not detract from or oppose the goals of gender equality and the rights of other groups. The focus should be on creating a fair society where everyone has equal opportunities and protections under the law. - - -# 导入数据 -python data_ingestion.py -p example/data/ - -or - -python data_ingestion.py -p example/data/declaration_of_the_rights_of_man_1789.pdf - - -# 导入数据后,查询问题。通义千问模型会根据 RAG 系统的检索结果,结合上下文,给出答案。 - -python query.py -q 'how about the rights of men' - -## outputs -请基于```内的内容回答问题。" - ``` - I. Men are born, and always continue, free and equal in respect of their rights. Civil distinctions, therefore, can be founded only on public utility. - ``` - 我的问题是:how about the rights of men。 - -question: how about the rights of men -answer: The statement implies that men are born free and equal in terms of their rights. Civil distinctions should only be based on public utility. However, it does not specify what those rights are. It is up to society and individual countries to determine and protect the specific rights of their citizens. - -```` - -## 开发 - -`MinerU` 提供了 `RAG` 集成接口,用户可以通过指定输入单个 `pdf` 文件或者某个目录。`MinerU` 会自动解析输入文件并返回可以迭代的接口用于获取数据 - -### API 接口 - -```python -from magic_pdf.integrations.rag.type import Node - -class RagPageReader: - def get_rel_map(self) -> list[ElementRelation]: - # 获取节点间的关系 - pass - ... - -class RagDocumentReader: - ... - -class DataReader: - def __init__(self, path_or_directory: str, method: str, output_dir: str): - pass - - def get_documents_count(self) -> int: - """获取 pdf 文档数量""" - pass - - def get_document_result(self, idx: int) -> RagDocumentReader | None: - """获取某个 pdf 的解析内容""" - pass - - - def get_document_filename(self, idx: int) -> Path: - """获取某个 pdf 的具体路径""" - pass - - -``` - -类型定义 - -```python - -class Node(BaseModel): - category_type: CategoryType = Field(description='类别') # 类别 - text: str | None = Field(description='文本内容', - default=None) - image_path: str | None = Field(description='图或者表格(表可能用图片形式存储)的存储路径', - default=None) - anno_id: int = Field(description='unique id', default=-1) - latex: str | None = Field(description='公式或表格 latex 解析结果', default=None) - html: str | None = Field(description='表格的 html 解析结果', default=None) - -``` - -表格存储形式可能会是 图片、latex、html 三种形式之一。 -anno_id 是该 Node 的在全局唯一ID。后续可以用于匹配该 Node 和其他 Node 的关系。节点的关系可以通过方法 `get_rel_map` 获取。用户可以用 `anno_id` 匹配节点之间的关系,并用于构建具备节点的关系的 rag index。 - -### 节点类型关系矩阵 - -| | image_body | table_body | -| -------------- | ---------- | ---------- | -| image_caption | sibling | | -| table_caption | | sibling | -| table_footnote | | sibling | diff --git a/projects/llama_index_rag/data_ingestion.py b/projects/llama_index_rag/data_ingestion.py deleted file mode 100644 index 821a10811b78f3f324a6455dc224862494c0606f..0000000000000000000000000000000000000000 --- a/projects/llama_index_rag/data_ingestion.py +++ /dev/null @@ -1,68 +0,0 @@ -import os - -import click -from llama_index.core.schema import TextNode -from llama_index.embeddings.dashscope import (DashScopeEmbedding, - DashScopeTextEmbeddingModels, - DashScopeTextEmbeddingType) -from llama_index.vector_stores.elasticsearch import ElasticsearchStore - -from magic_pdf.integrations.rag.api import DataReader - -es_vec_store = ElasticsearchStore( - index_name='rag_index', - es_url=os.getenv('ES_URL', 'http://127.0.0.1:9200'), - es_user=os.getenv('ES_USER', 'elastic'), - es_password=os.getenv('ES_PASSWORD', 'llama_index'), -) - - -# Create embeddings -# text_type=`document` to build index -def embed_node(node): - embedder = DashScopeEmbedding( - model_name=DashScopeTextEmbeddingModels.TEXT_EMBEDDING_V2, - text_type=DashScopeTextEmbeddingType.TEXT_TYPE_DOCUMENT, - ) - - result_embeddings = embedder.get_text_embedding(node.text) - node.embedding = result_embeddings - return node - - -@click.command() -@click.option( - '-p', - '--path', - 'path', - type=click.Path(exists=True), - required=True, - help='local pdf filepath or directory', -) -def cli(path): - output_dir = '/tmp/magic_pdf/integrations/rag/' - os.makedirs(output_dir, exist_ok=True) - documents = DataReader(path, 'ocr', output_dir) - - # build nodes - nodes = [] - - for idx in range(documents.get_documents_count()): - doc = documents.get_document_result(idx) - if doc is None: # something wrong happens when parse pdf ! - continue - - for page in iter( - doc): # iterate documents from initial page to last page ! - for element in iter(page): # iterate the element from all page ! - if element.text is None: - continue - nodes.append( - embed_node( - TextNode(text=element.text, - metadata={'purpose': 'demo'}))) - es_vec_store.add(nodes) - - -if __name__ == '__main__': - cli() diff --git a/projects/llama_index_rag/docker-compose.yml b/projects/llama_index_rag/docker-compose.yml deleted file mode 100644 index b6dc24d6fa6f4d09875ec3187682879390f6794f..0000000000000000000000000000000000000000 --- a/projects/llama_index_rag/docker-compose.yml +++ /dev/null @@ -1,24 +0,0 @@ -services: - es: - container_name: es - image: docker.elastic.co/elasticsearch/elasticsearch:8.11.3 - volumes: - - esdata01:/usr/share/elasticsearch/data - ports: - - 9200:9200 - environment: - - node.name=es - - ELASTIC_PASSWORD=llama_index - - bootstrap.memory_lock=false - - discovery.type=single-node - - xpack.security.enabled=true - - xpack.security.http.ssl.enabled=false - - xpack.security.transport.ssl.enabled=false - ulimits: - memlock: - soft: -1 - hard: -1 - restart: always -volumes: - esdata01: - driver: local diff --git a/projects/llama_index_rag/example/data/declaration_of_the_rights_of_man_1789.pdf b/projects/llama_index_rag/example/data/declaration_of_the_rights_of_man_1789.pdf deleted file mode 100644 index eff02687cafb674cef53422d8f7e0526175dc8a9..0000000000000000000000000000000000000000 Binary files a/projects/llama_index_rag/example/data/declaration_of_the_rights_of_man_1789.pdf and /dev/null differ diff --git a/projects/llama_index_rag/query.py b/projects/llama_index_rag/query.py deleted file mode 100644 index 64151dae1f6c7ae5c260af416fa2cd8ecca89673..0000000000000000000000000000000000000000 --- a/projects/llama_index_rag/query.py +++ /dev/null @@ -1,84 +0,0 @@ -import os - -import click -from llama_index.core.vector_stores.types import VectorStoreQuery -from llama_index.embeddings.dashscope import (DashScopeEmbedding, - DashScopeTextEmbeddingModels, - DashScopeTextEmbeddingType) -from llama_index.vector_stores.elasticsearch import (AsyncDenseVectorStrategy, - ElasticsearchStore) -# initialize qwen 7B model -from modelscope import AutoModelForCausalLM, AutoTokenizer, GenerationConfig - -es_vector_store = ElasticsearchStore( - index_name='rag_index', - es_url=os.getenv('ES_URL', 'http://127.0.0.1:9200'), - es_user=os.getenv('ES_USER', 'elastic'), - es_password=os.getenv('ES_PASSWORD', 'llama_index'), - retrieval_strategy=AsyncDenseVectorStrategy(), -) - - -def embed_text(text): - embedder = DashScopeEmbedding( - model_name=DashScopeTextEmbeddingModels.TEXT_EMBEDDING_V2, - text_type=DashScopeTextEmbeddingType.TEXT_TYPE_DOCUMENT, - ) - return embedder.get_text_embedding(text) - - -def search(vector_store: ElasticsearchStore, query: str): - query_vec = VectorStoreQuery(query_embedding=embed_text(query)) - result = vector_store.query(query_vec) - return '\n'.join([node.text for node in result.nodes]) - - -@click.command() -@click.option( - '-q', - '--question', - 'question', - required=True, - help='ask what you want to know!', -) -def cli(question): - tokenizer = AutoTokenizer.from_pretrained('qwen/Qwen-7B-Chat', - revision='v1.0.5', - trust_remote_code=True) - model = AutoModelForCausalLM.from_pretrained('qwen/Qwen-7B-Chat', - revision='v1.0.5', - device_map='auto', - trust_remote_code=True, - fp32=True).eval() - model.generation_config = GenerationConfig.from_pretrained( - 'Qwen/Qwen-7B-Chat', revision='v1.0.5', trust_remote_code=True) - - # define a prompt template for the vectorDB-enhanced LLM generation - def answer_question(question, context, model): - if context == '': - prompt = question - else: - prompt = f'''请基于```内的内容回答问题。" - ``` - {context} - ``` - 我的问题是:{question}。 - ''' - history = None - print(prompt) - response, history = model.chat(tokenizer, prompt, history=None) - return response - - answer = answer_question(question, search(es_vector_store, question), - model) - print(f'question: {question}\n' - f'answer: {answer}') - - -""" - -python query.py -q 'how about the rights of men' -""" - -if __name__ == '__main__': - cli() diff --git a/projects/llama_index_rag/rag_data_api.png b/projects/llama_index_rag/rag_data_api.png deleted file mode 100644 index 0aa4b2e56f821870a9edd061e163a0035a8a3f2b..0000000000000000000000000000000000000000 Binary files a/projects/llama_index_rag/rag_data_api.png and /dev/null differ diff --git a/projects/mcp/.env.example b/projects/mcp/.env.example new file mode 100644 index 0000000000000000000000000000000000000000..e282fb927f059de3f7cf475fa9782e65563107db --- /dev/null +++ b/projects/mcp/.env.example @@ -0,0 +1,5 @@ +MINERU_API_BASE = "https://mineru.net" +MINERU_API_KEY = "eyJ0eXB..." +OUTPUT_DIR=./downloads +USE_LOCAL_API=false +LOCAL_MINERU_API_BASE="http://localhost:8888" \ No newline at end of file diff --git a/projects/mcp/.gitignore b/projects/mcp/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..7410789349fc05b253098b3cb96aba7e2610df30 --- /dev/null +++ b/projects/mcp/.gitignore @@ -0,0 +1,12 @@ +downloads +.env +uv.lock +.venv +src/mineru/__pycache__ +dist +.DS_Store +.cursor +build +*.lock +src/mineru_mcp.egg-info +test \ No newline at end of file diff --git a/projects/mcp/DOCKER_README.md b/projects/mcp/DOCKER_README.md new file mode 100644 index 0000000000000000000000000000000000000000..36d16753044881f9d24811c6af45eadced5bd9d8 --- /dev/null +++ b/projects/mcp/DOCKER_README.md @@ -0,0 +1,164 @@ +# MinerU MCP-Server Docker 部署指南 + +## 1. 简介 + +本文档提供了使用 Docker 部署 MinerU MCP-Server 的详细指南。通过 Docker 部署,你可以在任何支持 Docker 的环境中快速启动 MinerU MCP 服务器,无需考虑复杂的环境配置和依赖管理。 + +Docker 部署的主要优势: + +- **一致的运行环境**:确保在任何平台上都有相同的运行环境 +- **简化部署流程**:一键启动,无需手动安装依赖 +- **易于扩展和迁移**:便于在不同环境间迁移和扩展服务 +- **资源隔离**:避免与宿主机其他服务产生冲突 + +## 2. 先决条件 + +在开始之前,请确保你的系统已安装以下软件: + +- [Docker](https://www.docker.com/get-started) (19.03 或更高版本) +- [Docker Compose](https://docs.docker.com/compose/install/) (1.27.0 或更高版本) + +你可以通过以下命令检查它们是否已正确安装: + +```bash +docker --version +docker-compose --version +``` + +同时,你需要: + +- 从 [MinerU 官网](https://mineru.net) 获取的 API 密钥(如果需要使用远程 API) +- 充足的硬盘空间,用于存储转换后的文件 + +## 3. 使用 Docker Compose 部署(推荐) + +Docker Compose 提供了最简单的部署方式,特别适合快速开始使用或开发环境。 + +### 3.1 准备配置文件 + +1. 克隆仓库(如果尚未克隆): + + ```bash + git clone + cd mineru-mcp + ``` + +2. 创建环境变量文件: + + ```bash + cp .env.example .env + ``` + +3. 编辑 `.env` 文件,设置必要的环境变量: + + ``` + MINERU_API_BASE=https://mineru.net + MINERU_API_KEY=你的API密钥 + OUTPUT_DIR=./downloads + USE_LOCAL_API=false + LOCAL_MINERU_API_BASE=http://localhost:8080 + ``` + + 如果你计划使用本地 API,请将 `USE_LOCAL_API` 设置为 `true`,并确保 `LOCAL_MINERU_API_BASE` 指向你的本地 API 服务地址。 + +### 3.2 启动服务 + +在项目根目录下运行: + +```bash +docker-compose up -d +``` + +这将会: +- 构建 Docker 镜像(如果尚未构建) +- 创建并启动容器 +- 在后台运行服务 (`-d` 参数) + +服务将在 `http://localhost:8001` 上启动。你可以通过 MCP 客户端连接此地址。 + +### 3.3 查看日志 + +要查看服务日志,运行: + +```bash +docker-compose logs -f +``` + +按 `Ctrl+C` 退出日志查看。 + +### 3.4 停止服务 + +要停止服务,运行: + +```bash +docker-compose down +``` + +如果你想同时删除构建的镜像,可以使用: + +```bash +docker-compose down --rmi local +``` + +## 4. 手动构建和运行 Docker 镜像 + +如果你需要更多的控制或自定义,你可以手动构建和运行 Docker 镜像。 + +### 4.1 构建镜像 + +在项目根目录下运行: + +```bash +docker build -t mineru-mcp:latest . +``` + +这将根据 Dockerfile 构建一个名为 `mineru-mcp` 的 Docker 镜像,标签为 `latest`。 + +### 4.2 运行容器 + +使用环境变量文件运行容器: + +```bash +docker run -p 8001:8001 --env-file .env mineru-mcp:latest +``` + +或者直接指定环境变量: + +```bash +docker run -p 8001:8001 \ + -e MINERU_API_BASE=https://mineru.net \ + -e MINERU_API_KEY=你的API密钥 \ + -e OUTPUT_DIR=/app/downloads \ + -v $(pwd)/downloads:/app/downloads \ + mineru-mcp:latest +``` + +### 4.3 挂载卷 + +为了持久化存储转换后的文件,你应该挂载宿主机目录到容器的输出目录: + +```bash +docker run -p 8001:8001 --env-file .env \ + -v $(pwd)/downloads:/app/downloads \ + mineru-mcp:latest +``` + +这将挂载当前工作目录下的 `downloads` 文件夹到容器内的 `/app/downloads` 目录。 + +## 5. 环境变量配置 + +Docker 环境中支持的环境变量与标准环境相同: + +| 环境变量 | 说明 | 默认值 | +| ------------------------- | -------------------------------------------------------------- | ------------------------- | +| `MINERU_API_BASE` | MinerU 远程 API 的基础 URL | `https://mineru.net` | +| `MINERU_API_KEY` | MinerU API 密钥,需要从官网申请 | - | +| `OUTPUT_DIR` | 转换后文件的保存路径 | `/app/downloads` | +| `USE_LOCAL_API` | 是否使用本地 API 进行解析(仅适用于 `local_parse_pdf` 工具) | `false` | +| `LOCAL_MINERU_API_BASE` | 本地 API 的基础 URL(当 `USE_LOCAL_API=true` 时有效) | `http://localhost:8080` | + +在 Docker 环境中,你可以: + +- 通过 `--env-file` 指定环境变量文件 +- 通过 `-e` 参数直接指定环境变量 +- 在 `docker-compose.yml` 文件中的 `environment` 部分配置环境变量 diff --git a/projects/mcp/Dockerfile b/projects/mcp/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..c33ea05b373458a6be83ace1347c421a0f3e7a1e --- /dev/null +++ b/projects/mcp/Dockerfile @@ -0,0 +1,35 @@ +FROM python:3.12-slim + +# Set working directory +WORKDIR /app + +# Configure pip to use Alibaba Cloud mirror +RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ + +# Install dependencies +RUN pip install --no-cache-dir poetry + +# Copy project files +COPY pyproject.toml . +COPY README.md . +COPY src/ ./src/ + +# Install the package +RUN poetry config virtualenvs.create false && \ + poetry install + +# Create downloads directory +RUN mkdir -p /app/downloads + +# Set environment variables +ENV OUTPUT_DIR=/app/downloads +# MINERU_API_KEY should be provided at runtime +ENV MINERU_API_BASE=https://mineru.net +ENV USE_LOCAL_API=false +ENV LOCAL_MINERU_API_BASE="" + +# Expose the port that SSE will run on +EXPOSE 8001 + +# Set command to start the service with SSE transport +CMD ["mineru-mcp", "--transport", "sse", "--output-dir", "/app/downloads"] \ No newline at end of file diff --git a/projects/mcp/README.md b/projects/mcp/README.md new file mode 100644 index 0000000000000000000000000000000000000000..bfa4eeaeb466589781c2ede7606b204958d2128f --- /dev/null +++ b/projects/mcp/README.md @@ -0,0 +1,346 @@ +# MinerU MCP-Server + +## 1. 概述 + +这个项目提供了一个 **MinerU MCP 服务器** (`mineru-mcp`),它基于 **FastMCP** 框架构建。其主要功能是作为 **MinerU API** 的接口,用于将文档转换为 Markdown格式。 + +该服务器通过 MCP 协议公开了以下主要工具: + +1. `parse_documents`:统一接口,支持处理本地文件和URL,自动根据配置选择最合适的处理方式,并自动读取转换后的内容 +2. `get_ocr_languages`:获取OCR支持的语言列表 + +这使得其他应用程序或 MCP 客户端能够轻松地集成 MinerU 的 文档 到 Markdown 转换功能。 + +## 2. 核心功能 + +* **文档提取**: 接收文档文件输入(单个或多个 URL、单个或多个本地路径,支持doc、ppt、pdf、图片多种格式),调用 MinerU API 进行内容提取和格式转换,最终生成 Markdown 文件。 +* **批量处理**: 支持同时处理多个文档文件(通过提供由空格、逗号或换行符分隔的 URL 列表或本地文件路径列表)。 +* **OCR 支持**: 可选启用 OCR 功能(默认不开启),以处理扫描版或图片型文档。 +* **多语言支持**: 支持多种语言的识别,可以自动检测文档语言或手动指定。 +* **自动化流程**: 自动处理与 MinerU API 的交互,包括任务提交、状态轮询、结果下载解压、结果文件读取。 +* **本地解析**: 支持调用本地部署的mineru模型直接解析文档,不依赖远程 API,适用于隐私敏感场景或离线环境。 +* **智能路径处理**: 自动识别URL和本地文件路径,根据USE_LOCAL_API配置选择最合适的处理方式。 + +## 3. 安装 + +在开始安装之前,请确保您的系统满足以下基本要求: +* Python >= 3.10 + +### 3.1 使用 pip 安装 (推荐) + +如果你的包已发布到 PyPI 或其他 Python 包索引,可以直接使用 pip 安装: + +```bash +pip install mineru-mcp==1.0.0 +``` + +目前版本:1.0.0 + +这种方式适用于不需要修改源代码的普通用户。 + +### 3.2 从源码安装 + +如果你需要修改源代码或进行开发,可以从源码安装。 + +克隆仓库并进入项目目录: + +```bash +git clone # 替换为你的仓库 URL +cd mineru-mcp +``` + +推荐使用 `uv` 或 `pip` 配合虚拟环境进行安装: + +**使用 uv (推荐):** + +```bash +# 安装 uv (如果尚未安装) +# pip install uv + +# 创建并激活虚拟环境 +uv venv + +# Linux/macOS +source .venv/bin/activate +# Windows +# .venv\\Scripts\\activate + +# 安装依赖和项目 +uv pip install -e . +``` + +**使用 pip:** + +```bash +# 创建并激活虚拟环境 +python -m venv .venv + +# Linux/macOS +source .venv/bin/activate +# Windows +# .venv\\Scripts\\activate + +# 安装依赖和项目 +pip install -e . +``` + +## 4. 环境变量配置 + +本项目支持通过环境变量进行配置。你可以选择直接设置系统环境变量,或者在项目根目录创建 `.env` 文件(参考 `.env.example` 模板)。 + +### 4.1 支持的环境变量 + +| 环境变量 | 说明 | 默认值 | +| ------------------------- | --------------------------------------------------------------- | ------------------------- | +| `MINERU_API_BASE` | MinerU 远程 API 的基础 URL | `https://mineru.net` | +| `MINERU_API_KEY` | MinerU API 密钥,需要从[官网](https://mineru.net)申请 | - | +| `OUTPUT_DIR` | 转换后文件的保存路径 | `./downloads` | +| `USE_LOCAL_API` | 是否使用本地 API 进行解析 | `false` | +| `LOCAL_MINERU_API_BASE` | 本地 API 的基础 URL(当 `USE_LOCAL_API=true` 时有效) | `http://localhost:8080` | + +### 4.2 远程 API 与本地 API + +本项目支持两种 API 模式: + +* **远程 API**:默认模式,通过 MinerU 官方提供的云服务进行文档解析。优点是无需本地部署复杂的模型和环境,但需要网络连接和 API 密钥。 +* **本地 API**:在本地部署 MinerU 引擎进行文档解析,适用于对数据隐私有高要求或需要离线使用的场景。设置 `USE_LOCAL_API=true` 时生效。 + +### 4.3 获取 API 密钥 + +要获取 `MINERU_API_KEY`,请访问 [MinerU 官网](https://mineru.net) 注册账号并申请 API 密钥。 + +## 5. 使用方法 + +### 5.1 工具概览 + +本项目通过 MCP 协议提供以下工具: + +1. **parse_documents**:统一接口,支持处理本地文件和URL,根据 `USE_LOCAL_API` 配置自动选择合适的处理方式,并自动读取转换后的文件内容 +2. **get_ocr_languages**:获取 OCR 支持的语言列表 + +### 5.2 参数说明 + +#### 5.2.1 parse_documents + +| 参数 | 类型 | 说明 | 默认值 | 适用模式 | +| ------------------- | ------- | ------------------------------------------------------------------- | -------- | -------- | +| `file_sources` | 字符串 | 文件路径或URL,多个可用逗号或换行符分隔 (支持pdf、ppt、pptx、doc、docx以及图片格式jpg、jpeg、png) | - | 全部 | +| `enable_ocr` | 布尔值 | 是否启用 OCR 功能 | `false` | 全部 | +| `language` | 字符串 | 文档语言,默认"ch"中文,可选"en"英文等 | `ch` | 全部 | +| `page_ranges` | 字符串 (可选) | 指定页码范围,格式为逗号分隔的字符串。例如:"2,4-6":表示选取第2页、第4页至第6页;"2--2":表示从第2页一直选取到倒数第二页。(远程API) | `None` | 远程API | + +> **注意**: +> - 当 `USE_LOCAL_API=true` 时,如果提供了URL,这些URL会被过滤掉,只处理本地文件路径 +> - 当 `USE_LOCAL_API=false` 时,会同时处理URL和本地文件路径 + +#### 5.2.2 get_ocr_languages + +无需参数 + +## 6. MCP 客户端集成 + +你可以在任何支持 MCP 协议的客户端中使用 MinerU MCP 服务器。 + +### 6.1 在 Claude 中使用 + +将 MinerU MCP 服务器配置为 Claude 的工具,即可在 Claude 中直接使用文档转 Markdown 功能。配置工具时详情请参考 MCP 工具配置文档。根据不同的安装和使用场景,你可以选择以下两种配置方式: + +#### 6.1.1 源码运行方式 + +如果你是从源码安装并运行 MinerU MCP,可以使用以下配置。这种方式适合你需要修改源码或者进行开发调试的场景: + +```json +{ + "mcpServers": { + "mineru-mcp": { + "command": "uv", + "args": ["--directory", "/Users/adrianwang/Documents/minerU-mcp", "run", "-m", "mineru.cli"], + "env": { + "MINERU_API_BASE": "https://mineru.net", + "MINERU_API_KEY": "ey...", + "OUTPUT_DIR": "./downloads", + "USE_LOCAL_API": "true", + "LOCAL_MINERU_API_BASE": "http://localhost:8080" + } + } + } +} +``` + +这种配置的特点: + +- 使用 `uv` 命令 +- 通过 `--directory` 参数指定源码所在目录 +- 使用 `-m mineru.cli` 运行模块 +- 适合开发调试和定制化需求 + +#### 6.1.2 安装包运行方式 + +如果你是通过 pip 或 uv 安装了 mineru-mcp 包,可以使用以下更简洁的配置。这种方式适合生产环境或日常使用: + +```json +{ + "mcpServers": { + "mineru-mcp": { + "command": "uvx", + "args": ["mineru-mcp"], + "env": { + "MINERU_API_BASE": "https://mineru.net", + "MINERU_API_KEY": "ey...", + "OUTPUT_DIR": "./downloads", + "USE_LOCAL_API": "true", + "LOCAL_MINERU_API_BASE": "http://localhost:8080" + } + } + } +} +``` + +这种配置的特点: + +- 使用 `uvx` 命令直接运行已安装的包 +- 配置更加简洁 +- 不需要指定源码目录 +- 适合稳定的生产环境使用 + +### 6.2 在 FastMCP 客户端中使用 + + +```python +from fastmcp import FastMCP + +# 初始化 FastMCP 客户端 +client = FastMCP(server_url="http://localhost:8001") + +# 使用 parse_documents 工具处理单个文档 +result = await client.tool_call( + tool_name="parse_documents", + params={"file_sources": "/path/to/document.pdf"} +) + +# 混合处理URLs和本地文件 +result = await client.tool_call( + tool_name="parse_documents", + params={"file_sources": "/path/to/file.pdf, https://example.com/document.pdf"} +) + +# 启用OCR +result = await client.tool_call( + tool_name="parse_documents", + params={"file_sources": "/path/to/file.pdf", "enable_ocr": True} +) +``` + +### 6.3 直接运行服务 + +你可以通过设置环境变量并直接运行命令的方式启动 MinerU MCP 服务器,这种方式特别适合快速测试和开发环境。 + +#### 6.3.1 设置环境变量 + +首先,确保设置了必要的环境变量。你可以通过创建 `.env` 文件(参考 `.env.example`)或直接在命令行中设置: + +```bash +# Linux/macOS +export MINERU_API_BASE="https://mineru.net" +export MINERU_API_KEY="your-api-key" +export OUTPUT_DIR="./downloads" +export USE_LOCAL_API="true" # 可选,如果需要本地解析 +export LOCAL_MINERU_API_BASE="http://localhost:8080" # 可选,如果启用本地 API + +# Windows +set MINERU_API_BASE=https://mineru.net +set MINERU_API_KEY=your-api-key +set OUTPUT_DIR=./downloads +set USE_LOCAL_API=true +set LOCAL_MINERU_API_BASE=http://localhost:8080 +``` + +#### 6.3.2 启动服务 + +使用以下命令启动 MinerU MCP 服务器,支持多种传输模式: + +**SSE 传输模式**: +```bash +uv run mineru-mcp --transport sse +``` + +**Streamable HTTP 传输模式**: +```bash +uv run mineru-mcp --transport streamable-http +``` + +或者,如果你使用全局安装: + +```bash +mineru-mcp --transport sse +# 或 +mineru-mcp --transport streamable-http +``` + +服务默认在 `http://localhost:8001` 启动,使用的传输协议取决于你指定的 `--transport` 参数。 + +> **注意**:不同传输模式使用不同的路由路径: +> - SSE 模式:`/sse`(例如:`http://localhost:8001/sse`) +> - Streamable HTTP 模式:`/mcp`(例如:`http://localhost:8001/mcp`) + + +## 7. Docker 部署 + +本项目支持使用 Docker 进行部署,使你能在任何支持 Docker 的环境中快速启动 MinerU MCP 服务器。 + +### 7.1 使用 Docker Compose + +1. 确保你已经安装了 Docker 和 Docker Compose +2. 复制项目根目录中的 `.env.example` 文件为 `.env`,并根据你的需求修改环境变量 +3. 运行以下命令启动服务: + +```bash +docker-compose up -d +``` + +服务默认会在 `http://localhost:8001` 启动。 + +### 7.2 手动构建 Docker 镜像 + +如果需要手动构建 Docker 镜像,可以使用以下命令: + +```bash +docker build -t mineru-mcp:latest . +``` + +然后启动容器: + +```bash +docker run -p 8001:8001 --env-file .env mineru-mcp:latest +``` + +更多 Docker 相关信息,请参考 `DOCKER_README.md` 文件。 + +## 8. 常见问题 + +### 8.1 API 密钥问题 + +**问题**:无法连接 MinerU API 或返回 401 错误。 +**解决方案**:检查你的 API 密钥是否正确设置。在 `.env` 文件中确保 `MINERU_API_KEY` 环境变量包含有效的密钥。 + +### 8.2 如何优雅退出服务 + +**问题**:如何正确地停止 MinerU MCP 服务? +**解决方案**:服务运行时,可以通过按 `Ctrl+C` 来优雅地退出。系统会自动处理正在进行的操作,并确保所有资源得到正确释放。如果一次 `Ctrl+C` 没有响应,可以再次按下 `Ctrl+C` 强制退出。 + +### 8.3 文件路径问题 + +**问题**:使用 `parse_documents` 工具处理本地文件时报找不到文件错误。 +**解决方案**:请确保使用绝对路径,或者相对于服务器运行目录的正确相对路径。 + +### 8.4 MCP 服务调用超时问题 + +**问题**:调用 `parse_documents` 工具时出现 `Error calling tool 'parse_documents': MCP error -32001: Request timed out` 错误。 +**解决方案**:这个问题常见于处理大型文档或网络不稳定的情况。在某些 MCP 客户端(如 Cursor)中,超时后可能导致无法再次调用 MCP 服务,需要重启客户端。最新版本的 Cursor 中可能会显示正在调用 MCP,但实际上没有真正调用成功。建议: +1. **等待官方修复**:这是Cursor客户端的已知问题,建议等待Cursor官方修复 +2. **处理小文件**:尽量只处理少量小文件,避免处理大型文档导致超时 +3. **分批处理**:将多个文件分成多次请求处理,每次只处理一两个文件 +4. 增加超时时间设置(如果客户端支持) +5. 对于超时后无法再次调用的问题,需要重启 MCP 客户端 +6. 如果反复出现超时,请检查网络连接或考虑使用本地 API 模式 + diff --git a/projects/mcp/docker-compose.yml b/projects/mcp/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..1bd9e533fa46337e47d810ea80efdc89d6695cdc --- /dev/null +++ b/projects/mcp/docker-compose.yml @@ -0,0 +1,14 @@ +version: '3' + +services: + mineru-mcp: + build: + context: . + dockerfile: Dockerfile + ports: + - "8001:8001" + environment: + - MINERU_API_KEY=${MINERU_API_KEY} + volumes: + - ./downloads:/app/downloads + restart: unless-stopped \ No newline at end of file diff --git a/projects/mcp/pyproject.toml b/projects/mcp/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..e15cf115ef2cda34c5a7363abd8f922694a6eb05 --- /dev/null +++ b/projects/mcp/pyproject.toml @@ -0,0 +1,39 @@ +[project] +name = "mineru-mcp" +version = "1.0.0" +description = "MinerU MCP Server for PDF to Markdown conversion" +authors = [ + {name = "minerU",email = "OpenDataLab@pjlab.org.cn"} +] +readme = "README.md" +license = {text = "MIT"} +requires-python = ">=3.10,<4.0" +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", +] +dependencies = [ + "fastmcp>=2.5.2", + "python-dotenv>=1.0.0", + "requests>=2.31.0", + "aiohttp>=3.9.0", + "httpx>=0.24.0", + "uvicorn>=0.20.0", + "starlette>=0.27.0", +] + +[project.scripts] +mineru-mcp = "mineru.cli:main" + +[tool.poetry] +packages = [{include = "mineru", from = "src"}] + +[[tool.poetry.source]] +name = "aliyun" +url = "https://mirrors.aliyun.com/pypi/simple/" +priority = "primary" + +[build-system] +requires = ["setuptools>=42.0", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/projects/mcp/src/mineru/api.py b/projects/mcp/src/mineru/api.py new file mode 100644 index 0000000000000000000000000000000000000000..43de2da44a0d8142ce71a00d96bb21a37939bea0 --- /dev/null +++ b/projects/mcp/src/mineru/api.py @@ -0,0 +1,729 @@ +"""MinerU File转Markdown转换的API客户端。""" + +import asyncio +import os +import zipfile +from pathlib import Path +from typing import Any, Dict, List, Optional, Union + +import aiohttp +import requests + +from . import config + + +def singleton_func(cls): + instance = {} + + def _singleton(*args, **kwargs): + if cls not in instance: + instance[cls] = cls(*args, **kwargs) + return instance[cls] + + return _singleton + + +@singleton_func +class MinerUClient: + """ + 用于与 MinerU API 交互以将 File 转换为 Markdown 的客户端。 + """ + + def __init__(self, api_base: Optional[str] = None, api_key: Optional[str] = None): + """ + 初始化 MinerU API 客户端。 + + Args: + api_base: MinerU API 的基础 URL (默认: 从环境变量获取) + api_key: 用于向 MinerU 进行身份验证的 API 密钥 (默认: 从环境变量获取) + """ + self.api_base = api_base or config.MINERU_API_BASE + self.api_key = api_key or config.MINERU_API_KEY + + if not self.api_key: + # 提供更友好的错误消息 + raise ValueError( + "错误: MinerU API 密钥 (MINERU_API_KEY) 未设置或为空。\n" + "请确保已设置 MINERU_API_KEY 环境变量,例如:\n" + " export MINERU_API_KEY='your_actual_api_key'\n" + "或者,在项目根目录的 `.env` 文件中定义该变量。" + ) + + async def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]: + """ + 向 MinerU API 发出请求。 + + Args: + method: HTTP 方法 (GET, POST 等) + endpoint: API 端点路径 (不含基础 URL) + **kwargs: 传递给 aiohttp 请求的其他参数 + + Returns: + dict: API 响应 (JSON 格式) + """ + url = f"{self.api_base}{endpoint}" + headers = { + "Authorization": f"Bearer {self.api_key}", + "Accept": "application/json", + } + + if "headers" in kwargs: + kwargs["headers"].update(headers) + else: + kwargs["headers"] = headers + + # 创建一个不包含授权信息的参数副本,用于日志记录 + log_kwargs = kwargs.copy() + if "headers" in log_kwargs and "Authorization" in log_kwargs["headers"]: + log_kwargs["headers"] = log_kwargs["headers"].copy() + log_kwargs["headers"]["Authorization"] = "Bearer ****" # 隐藏API密钥 + + config.logger.debug(f"API请求: {method} {url}") + config.logger.debug(f"请求参数: {log_kwargs}") + + async with aiohttp.ClientSession() as session: + async with session.request(method, url, **kwargs) as response: + response.raise_for_status() + response_json = await response.json() + + config.logger.debug(f"API响应: {response_json}") + + return response_json + + async def submit_file_url_task( + self, + urls: Union[str, List[Union[str, Dict[str, Any]]], Dict[str, Any]], + enable_ocr: bool = True, + language: str = "ch", + page_ranges: Optional[str] = None, + ) -> Dict[str, Any]: + """ + 提交 File URL 以转换为 Markdown。支持单个URL或多个URL批量处理。 + + Args: + urls: 可以是以下形式之一: + 1. 单个URL字符串 + 2. 多个URL的列表 + 3. 包含URL配置的字典列表,每个字典包含: + - url: File文件URL (必需) + - is_ocr: 是否启用OCR (可选) + - data_id: 文件数据ID (可选) + - page_ranges: 页码范围 (可选) + enable_ocr: 是否为转换启用 OCR(所有文件的默认值) + language: 指定文档语言,默认 ch,中文 + page_ranges: 指定页码范围,格式为逗号分隔的字符串。例如:"2,4-6"表示选取第2页、第4页至第6页;"2--2"表示从第2页到倒数第2页。 + + Returns: + dict: 任务信息,包括batch_id + """ + # 统计URL数量 + url_count = 1 + if isinstance(urls, list): + url_count = len(urls) + config.logger.debug( + f"调用submit_file_url_task: {url_count}个URL, " + + f"ocr={enable_ocr}, " + + f"language={language}" + ) + + # 处理输入,确保我们有一个URL配置列表 + urls_config = [] + + # 转换输入为标准格式 + if isinstance(urls, str): + urls_config.append( + {"url": urls, "is_ocr": enable_ocr, "page_ranges": page_ranges} + ) + + elif isinstance(urls, list): + # 处理URL列表或URL配置列表 + for i, url_item in enumerate(urls): + if isinstance(url_item, str): + # 简单的URL字符串 + urls_config.append( + { + "url": url_item, + "is_ocr": enable_ocr, + "page_ranges": page_ranges, + } + ) + + elif isinstance(url_item, dict): + # 含有详细配置的URL字典 + if "url" not in url_item: + raise ValueError(f"URL配置必须包含 'url' 字段: {url_item}") + + url_is_ocr = url_item.get("is_ocr", enable_ocr) + url_page_ranges = url_item.get("page_ranges", page_ranges) + + url_config = {"url": url_item["url"], "is_ocr": url_is_ocr} + if url_page_ranges is not None: + url_config["page_ranges"] = url_page_ranges + + urls_config.append(url_config) + else: + raise TypeError(f"不支持的URL配置类型: {type(url_item)}") + elif isinstance(urls, dict): + # 单个URL配置字典 + if "url" not in urls: + raise ValueError(f"URL配置必须包含 'url' 字段: {urls}") + + url_is_ocr = urls.get("is_ocr", enable_ocr) + url_page_ranges = urls.get("page_ranges", page_ranges) + + url_config = {"url": urls["url"], "is_ocr": url_is_ocr} + if url_page_ranges is not None: + url_config["page_ranges"] = url_page_ranges + + urls_config.append(url_config) + else: + raise TypeError(f"urls 必须是字符串、列表或字典,而不是 {type(urls)}") + + # 构建API请求payload + files_payload = urls_config # 与submit_file_task不同,这里直接使用URLs配置 + + payload = { + "language": language, + "files": files_payload, + } + + # 调用批量API + response = await self._request( + "POST", "/api/v4/extract/task/batch", json=payload + ) + + # 检查响应 + if "data" not in response or "batch_id" not in response["data"]: + raise ValueError(f"提交批量URL任务失败: {response}") + + batch_id = response["data"]["batch_id"] + + config.logger.info(f"开始处理 {len(urls_config)} 个文件URL") + config.logger.debug(f"批量URL任务提交成功,批次ID: {batch_id}") + + # 返回包含batch_id的响应和URLs信息 + result = { + "data": { + "batch_id": batch_id, + "uploaded_files": [url_config.get("url") for url_config in urls_config], + } + } + + # 对于单个URL的情况,设置file_name以保持与原来返回格式的兼容性 + if len(urls_config) == 1: + url = urls_config[0]["url"] + # 从URL中提取文件名 + file_name = url.split("/")[-1] + result["data"]["file_name"] = file_name + + return result + + async def submit_file_task( + self, + files: Union[str, List[Union[str, Dict[str, Any]]], Dict[str, Any]], + enable_ocr: bool = True, + language: str = "ch", + page_ranges: Optional[str] = None, + ) -> Dict[str, Any]: + """ + 提交本地 File 文件以转换为 Markdown。支持单个文件路径或多个文件配置。 + + Args: + files: 可以是以下形式之一: + 1. 单个文件路径字符串 + 2. 多个文件路径的列表 + 3. 包含文件配置的字典列表,每个字典包含: + - path/name: 文件路径或文件名 + - is_ocr: 是否启用OCR (可选) + - data_id: 文件数据ID (可选) + - page_ranges: 页码范围 (可选) + enable_ocr: 是否为转换启用 OCR(所有文件的默认值) + language: 指定文档语言,默认 ch,中文 + page_ranges: 指定页码范围,格式为逗号分隔的字符串。例如:"2,4-6"表示选取第2页、第4页至第6页;"2--2"表示从第2页到倒数第2页。 + + Returns: + dict: 任务信息,包括batch_id + """ + # 统计文件数量 + file_count = 1 + if isinstance(files, list): + file_count = len(files) + config.logger.debug( + f"调用submit_file_task: {file_count}个文件, " + + f"ocr={enable_ocr}, " + + f"language={language}" + ) + + # 处理输入,确保我们有一个文件配置列表 + files_config = [] + + # 转换输入为标准格式 + if isinstance(files, str): + # 单个文件路径 + file_path = Path(files) + if not file_path.exists(): + raise FileNotFoundError(f"未找到 File 文件: {file_path}") + + files_config.append( + { + "path": file_path, + "name": file_path.name, + "is_ocr": enable_ocr, + "page_ranges": page_ranges, + } + ) + + elif isinstance(files, list): + # 处理文件路径列表或文件配置列表 + for i, file_item in enumerate(files): + if isinstance(file_item, str): + # 简单的文件路径 + file_path = Path(file_item) + if not file_path.exists(): + raise FileNotFoundError(f"未找到 File 文件: {file_path}") + + files_config.append( + { + "path": file_path, + "name": file_path.name, + "is_ocr": enable_ocr, + "page_ranges": page_ranges, + } + ) + + elif isinstance(file_item, dict): + # 含有详细配置的文件字典 + if "path" not in file_item and "name" not in file_item: + raise ValueError( + f"文件配置必须包含 'path' 或 'name' 字段: {file_item}" + ) + + if "path" in file_item: + file_path = Path(file_item["path"]) + if not file_path.exists(): + raise FileNotFoundError(f"未找到 File 文件: {file_path}") + + file_name = file_path.name + else: + file_name = file_item["name"] + file_path = None + + file_is_ocr = file_item.get("is_ocr", enable_ocr) + file_page_ranges = file_item.get("page_ranges", page_ranges) + + file_config = { + "path": file_path, + "name": file_name, + "is_ocr": file_is_ocr, + } + if file_page_ranges is not None: + file_config["page_ranges"] = file_page_ranges + + files_config.append(file_config) + else: + raise TypeError(f"不支持的文件配置类型: {type(file_item)}") + elif isinstance(files, dict): + # 单个文件配置字典 + if "path" not in files and "name" not in files: + raise ValueError(f"文件配置必须包含 'path' 或 'name' 字段: {files}") + + if "path" in files: + file_path = Path(files["path"]) + if not file_path.exists(): + raise FileNotFoundError(f"未找到 File 文件: {file_path}") + + file_name = file_path.name + else: + file_name = files["name"] + file_path = None + + file_is_ocr = files.get("is_ocr", enable_ocr) + file_page_ranges = files.get("page_ranges", page_ranges) + + file_config = { + "path": file_path, + "name": file_name, + "is_ocr": file_is_ocr, + } + if file_page_ranges is not None: + file_config["page_ranges"] = file_page_ranges + + files_config.append(file_config) + else: + raise TypeError(f"files 必须是字符串、列表或字典,而不是 {type(files)}") + + # 步骤1: 构建API请求payload + files_payload = [] + for file_config in files_config: + file_payload = { + "name": file_config["name"], + "is_ocr": file_config["is_ocr"], + } + if "page_ranges" in file_config and file_config["page_ranges"] is not None: + file_payload["page_ranges"] = file_config["page_ranges"] + files_payload.append(file_payload) + + payload = { + "language": language, + "files": files_payload, + } + + # 步骤2: 获取文件上传URL + response = await self._request("POST", "/api/v4/file-urls/batch", json=payload) + + # 检查响应 + if ( + "data" not in response + or "batch_id" not in response["data"] + or "file_urls" not in response["data"] + ): + raise ValueError(f"获取上传URL失败: {response}") + + batch_id = response["data"]["batch_id"] + file_urls = response["data"]["file_urls"] + + if len(file_urls) != len(files_config): + raise ValueError( + f"上传URL数量 ({len(file_urls)}) 与文件数量 ({len(files_config)}) 不匹配" + ) + + config.logger.info(f"开始上传 {len(file_urls)} 个本地文件") + config.logger.debug(f"获取上传URL成功,批次ID: {batch_id}") + + # 步骤3: 上传所有文件 + uploaded_files = [] + + for i, (file_config, upload_url) in enumerate(zip(files_config, file_urls)): + file_path = file_config["path"] + if file_path is None: + raise ValueError(f"文件 {file_config['name']} 没有有效的路径") + + try: + with open(file_path, "rb") as f: + # 重要:不设置Content-Type,让OSS自动处理 + response = requests.put(upload_url, data=f) + + if response.status_code != 200: + raise ValueError( + f"文件上传失败,状态码: {response.status_code}, 响应: {response.text}" + ) + + config.logger.debug(f"文件 {file_path.name} 上传成功") + uploaded_files.append(file_path.name) + except Exception as e: + raise ValueError(f"文件 {file_path.name} 上传失败: {str(e)}") + + config.logger.info(f"文件上传完成,共 {len(uploaded_files)} 个文件") + + # 返回包含batch_id的响应和已上传的文件信息 + result = {"data": {"batch_id": batch_id, "uploaded_files": uploaded_files}} + + # 对于单个文件的情况,保持与原来返回格式的兼容性 + if len(uploaded_files) == 1: + result["data"]["file_name"] = uploaded_files[0] + + return result + + async def get_batch_task_status(self, batch_id: str) -> Dict[str, Any]: + """ + 获取批量转换任务的状态。 + + Args: + batch_id: 批量任务的ID + + Returns: + dict: 批量任务状态信息 + """ + response = await self._request( + "GET", f"/api/v4/extract-results/batch/{batch_id}" + ) + + return response + + async def process_file_to_markdown( + self, + task_fn, + task_arg: Union[str, List[Dict[str, Any]], Dict[str, Any]], + enable_ocr: bool = True, + output_dir: Optional[str] = None, + max_retries: int = 180, + retry_interval: int = 10, + ) -> Union[str, Dict[str, Any]]: + """ + 从开始到结束处理 File 到 Markdown 的转换。 + + Args: + task_fn: 提交任务的函数 (submit_file_url_task 或 submit_file_task) + task_arg: 任务函数的参数,可以是: + - URL字符串 + - 文件路径字符串 + - 包含文件配置的字典 + - 包含多个文件配置的字典列表 + enable_ocr: 是否启用 OCR + output_dir: 结果的输出目录 + max_retries: 最大状态检查重试次数 + retry_interval: 状态检查之间的时间间隔 (秒) + + Returns: + Union[str, Dict[str, Any]]: + - 单文件: 包含提取的 Markdown 文件的目录路径 + - 多文件: { + "results": [ + { + "filename": str, + "status": str, + "content": str, + "error_message": str, + } + ], + "extract_dir": str + } + """ + try: + # 提交任务 - 使用位置参数调用,而不是命名参数 + task_info = await task_fn(task_arg, enable_ocr) + + # 批量任务处理 + batch_id = task_info["data"]["batch_id"] + + # 获取所有上传文件的名称 + uploaded_files = task_info["data"].get("uploaded_files", []) + if not uploaded_files and "file_name" in task_info["data"]: + uploaded_files = [task_info["data"]["file_name"]] + + if not uploaded_files: + raise ValueError("无法获取上传文件的信息") + + config.logger.debug(f"批量任务提交成功。Batch ID: {batch_id}") + + # 跟踪所有文件的处理状态 + files_status = {} # 将使用file_name作为键 + files_download_urls = {} + failed_files = {} # 记录失败的文件和错误信息 + + # 准备输出路径 + output_path = config.ensure_output_dir(output_dir) + + # 轮询任务完成情况 + for i in range(max_retries): + status_info = await self.get_batch_task_status(batch_id) + + config.logger.debug(f"轮训结果:{status_info}") + + if ( + "data" not in status_info + or "extract_result" not in status_info["data"] + ): + config.logger.error(f"获取批量任务状态失败: {status_info}") + await asyncio.sleep(retry_interval) + continue + + # 检查所有文件的状态 + all_done = True + has_progress = False + + for result in status_info["data"]["extract_result"]: + file_name = result.get("file_name") + + if not file_name: + continue + + # 初始化状态,如果之前没有记录 + if file_name not in files_status: + files_status[file_name] = "pending" + + state = result.get("state") + files_status[file_name] = state + + if state == "done": + # 保存下载链接 + full_zip_url = result.get("full_zip_url") + if full_zip_url: + files_download_urls[file_name] = full_zip_url + config.logger.info(f"文件 {file_name} 处理完成") + else: + config.logger.debug( + f"文件 {file_name} 标记为完成但没有下载链接" + ) + all_done = False + elif state in ["failed", "error"]: + err_msg = result.get("err_msg", "未知错误") + failed_files[file_name] = err_msg + config.logger.warning(f"文件 {file_name} 处理失败: {err_msg}") + # 不抛出异常,继续处理其他文件 + else: + all_done = False + # 显示进度信息 + if state == "running" and "extract_progress" in result: + has_progress = True + progress = result["extract_progress"] + extracted = progress.get("extracted_pages", 0) + total = progress.get("total_pages", 0) + if total > 0: + percent = (extracted / total) * 100 + config.logger.info( + f"处理进度: {file_name} " + + f"{extracted}/{total} 页 " + + f"({percent:.1f}%)" + ) + + # 检查是否所有文件都已经处理完成 + expected_file_count = len(uploaded_files) + processed_file_count = len(files_status) + completed_file_count = len(files_download_urls) + len(failed_files) + + # 记录当前状态 + config.logger.debug( + f"文件处理状态: all_done={all_done}, " + + f"files_status数量={processed_file_count}, " + + f"上传文件数量={expected_file_count}, " + + f"下载链接数量={len(files_download_urls)}, " + + f"失败文件数量={len(failed_files)}" + ) + + # 判断是否所有文件都已完成(包括成功和失败的) + if ( + processed_file_count > 0 + and processed_file_count >= expected_file_count + and completed_file_count >= processed_file_count + ): + if files_download_urls or failed_files: + config.logger.info("文件处理完成") + if failed_files: + config.logger.warning( + f"有 {len(failed_files)} 个文件处理失败" + ) + break + else: + # 这种情况不应该发生,但保险起见 + all_done = False + + # 如果没有进度信息,只显示简单的等待消息 + if not has_progress: + config.logger.info(f"等待文件处理完成... ({i+1}/{max_retries})") + + await asyncio.sleep(retry_interval) + else: + # 如果超过最大重试次数,检查是否有部分文件完成 + if not files_download_urls and not failed_files: + raise TimeoutError(f"批量任务 {batch_id} 未在允许的时间内完成") + else: + config.logger.warning( + "警告: 部分文件未在允许的时间内完成," + "继续处理已完成的文件" + ) + + # 创建主提取目录 + extract_dir = output_path / batch_id + extract_dir.mkdir(exist_ok=True) + + # 准备结果列表 + results = [] + + # 下载并解压每个成功的文件的结果 + for file_name, download_url in files_download_urls.items(): + try: + config.logger.debug + (f"下载文件处理结果: {file_name}") + + # 从下载URL中提取zip文件名作为子目录名 + zip_file_name = download_url.split("/")[-1] + # 去掉.zip扩展名 + zip_dir_name = os.path.splitext(zip_file_name)[0] + + file_extract_dir = extract_dir / zip_dir_name + file_extract_dir.mkdir(exist_ok=True) + + # 下载ZIP文件 + zip_path = output_path / f"{batch_id}_{zip_file_name}" + + async with aiohttp.ClientSession() as session: + async with session.get( + download_url, + headers={"Authorization": f"Bearer {self.api_key}"}, + ) as response: + response.raise_for_status() + with open(zip_path, "wb") as f: + f.write(await response.read()) + + # 解压到子文件夹 + with zipfile.ZipFile(zip_path, "r") as zip_ref: + zip_ref.extractall(file_extract_dir) + + # 解压后删除ZIP文件 + zip_path.unlink() + + # 尝试读取Markdown内容 + markdown_content = "" + markdown_files = list(file_extract_dir.glob("*.md")) + if markdown_files: + with open(markdown_files[0], "r", encoding="utf-8") as f: + markdown_content = f.read() + + # 添加成功结果 + results.append( + { + "filename": file_name, + "status": "success", + "content": markdown_content, + "extract_path": str(file_extract_dir), + } + ) + + config.logger.debug( + f"文件 {file_name} 的结果已解压到: {file_extract_dir}" + ) + + except Exception as e: + # 下载失败,添加错误结果 + error_msg = f"下载结果失败: {str(e)}" + config.logger.error(f"文件 {file_name} {error_msg}") + results.append( + { + "filename": file_name, + "status": "error", + "error_message": error_msg, + } + ) + + # 添加处理失败的文件到结果 + for file_name, error_msg in failed_files.items(): + results.append( + { + "filename": file_name, + "status": "error", + "error_message": f"处理失败: {error_msg}", + } + ) + + # 输出处理结果统计 + success_count = len(files_download_urls) + fail_count = len(failed_files) + total_count = success_count + fail_count + + config.logger.info("\n=== 文件处理结果统计 ===") + config.logger.info(f"总文件数: {total_count}") + config.logger.info(f"成功处理: {success_count}") + config.logger.info(f"处理失败: {fail_count}") + + if failed_files: + config.logger.info("\n失败文件详情:") + for file_name, error_msg in failed_files.items(): + config.logger.info(f" - {file_name}: {error_msg}") + + if success_count > 0: + config.logger.info(f"\n结果保存目录: {extract_dir}") + else: + config.logger.info(f"\n输出目录: {extract_dir}") + + # 返回详细结果 + return { + "results": results, + "extract_dir": str(extract_dir), + "success_count": success_count, + "fail_count": fail_count, + "total_count": total_count, + } + + except Exception as e: + config.logger.error(f"处理 File 到 Markdown 失败: {str(e)}") + raise diff --git a/projects/mcp/src/mineru/cli.py b/projects/mcp/src/mineru/cli.py new file mode 100644 index 0000000000000000000000000000000000000000..417f5a966db0584020efe8c46f193808408e3074 --- /dev/null +++ b/projects/mcp/src/mineru/cli.py @@ -0,0 +1,73 @@ +"""MinerU File转Markdown服务的命令行界面。""" + +import sys +import argparse + +from . import config +from . import server + + +def main(): + """命令行界面的入口点。""" + parser = argparse.ArgumentParser(description="MinerU File转Markdown转换服务") + + parser.add_argument( + "--output-dir", "-o", type=str, help="保存转换后文件的目录 (默认: ./downloads)" + ) + + parser.add_argument( + "--transport", + "-t", + type=str, + default="stdio", + help="协议类型 (默认: stdio,可选: sse,streamable-http)", + ) + + parser.add_argument( + "--port", + "-p", + type=int, + default=8001, + help="服务器端口 (默认: 8001, 仅在使用HTTP协议时有效)", + ) + + parser.add_argument( + "--host", + type=str, + default="127.0.0.1", + help="服务器主机地址 (默认: 127.0.0.1, 仅在使用HTTP协议时有效)", + ) + + args = parser.parse_args() + + # 检查参数有效性 + if args.transport == "stdio" and (args.host != "127.0.0.1" or args.port != 8001): + print("警告: 在STDIO模式下,--host和--port参数将被忽略", file=sys.stderr) + + # 验证API密钥 - 移动到这里,以便 --help 等参数可以无密钥运行 + if not config.MINERU_API_KEY: + print( + "错误: 启动服务需要 MINERU_API_KEY 环境变量。" + "\\n请检查是否已设置该环境变量,例如:" + "\\n export MINERU_API_KEY='your_actual_api_key'" + "\\n或者,确保在项目根目录的 `.env` 文件中定义了该变量。" + "\\n\\n您可以使用 --help 查看可用的命令行选项。", + file=sys.stderr, # 将错误消息输出到 stderr + ) + sys.exit(1) + + # 如果提供了输出目录,则进行设置 + if args.output_dir: + server.set_output_dir(args.output_dir) + + # 打印配置信息 + print("MinerU File转Markdown转换服务启动...") + if args.transport in ["sse", "streamable-http"]: + print(f"服务器地址: {args.host}:{args.port}") + print("按 Ctrl+C 可以退出服务") + + server.run_server(mode=args.transport, port=args.port, host=args.host) + + +if __name__ == "__main__": + main() diff --git a/projects/mcp/src/mineru/config.py b/projects/mcp/src/mineru/config.py new file mode 100644 index 0000000000000000000000000000000000000000..ebfa0b7adc2554cc648a29ed106652d2868ce337 --- /dev/null +++ b/projects/mcp/src/mineru/config.py @@ -0,0 +1,91 @@ +"""MinerU File转Markdown转换服务的配置工具。""" + +import os +import logging +from pathlib import Path +from dotenv import load_dotenv + +# 从 .env 文件加载环境变量 +load_dotenv() + +# API 配置 +MINERU_API_BASE = os.getenv("MINERU_API_BASE", "https://mineru.net") +MINERU_API_KEY = os.getenv("MINERU_API_KEY", "") + +# 本地API配置 +USE_LOCAL_API = os.getenv("USE_LOCAL_API", "").lower() in ["true", "1", "yes"] +LOCAL_MINERU_API_BASE = os.getenv("LOCAL_MINERU_API_BASE", "http://localhost:8080") + +# 转换后文件的默认输出目录 +DEFAULT_OUTPUT_DIR = os.getenv("OUTPUT_DIR", "./downloads") + + +# 设置日志系统 +def setup_logging(): + """ + 设置日志系统,根据环境变量配置日志级别。 + + Returns: + logging.Logger: 配置好的日志记录器。 + """ + # 获取环境变量中的日志级别设置 + log_level = os.getenv("MINERU_LOG_LEVEL", "INFO").upper() + debug_mode = os.getenv("MINERU_DEBUG", "").lower() in ["true", "1", "yes"] + + # 如果设置了debug_mode,则覆盖log_level + if debug_mode: + log_level = "DEBUG" + + # 确保log_level是有效的 + valid_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] + if log_level not in valid_levels: + log_level = "INFO" + + # 设置日志格式 + log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + + # 配置日志 + logging.basicConfig(level=getattr(logging, log_level), format=log_format) + + logger = logging.getLogger("mineru") + logger.setLevel(getattr(logging, log_level)) + + # 输出日志级别信息 + logger.info(f"日志级别设置为: {log_level}") + + return logger + + +# 创建默认的日志记录器 +logger = setup_logging() + + +# 如果输出目录不存在,则创建它 +def ensure_output_dir(output_dir=None): + """ + 确保输出目录存在。 + + Args: + output_dir: 输出目录的可选路径。如果为 None,则使用 DEFAULT_OUTPUT_DIR。 + + Returns: + 表示输出目录的 Path 对象。 + """ + output_path = Path(output_dir or DEFAULT_OUTPUT_DIR) + output_path.mkdir(parents=True, exist_ok=True) + return output_path + + +# 验证 API 配置 +def validate_api_config(): + """ + 验证是否已设置所需的 API 配置。 + + Returns: + dict: 配置状态。 + """ + return { + "api_base": MINERU_API_BASE, + "api_key_set": bool(MINERU_API_KEY), + "output_dir": DEFAULT_OUTPUT_DIR, + } diff --git a/projects/mcp/src/mineru/examples.py b/projects/mcp/src/mineru/examples.py new file mode 100644 index 0000000000000000000000000000000000000000..8bda15822be693c464b305ccf7af7d578ce3680b --- /dev/null +++ b/projects/mcp/src/mineru/examples.py @@ -0,0 +1,76 @@ +"""演示如何使用 MinerU File转Markdown客户端的示例。""" + +import os +import asyncio +from mcp.client import MCPClient + + +async def convert_file_url_example(): + """从 URL 转换 File 的示例。""" + client = MCPClient("http://localhost:8000") + + # 转换单个 File URL + result = await client.call( + "convert_file_url", url="https://example.com/sample.pdf", enable_ocr=True + ) + print(f"转换结果: {result}") + + # 转换多个 File URL + urls = """ + https://example.com/doc1.pdf + https://example.com/doc2.pdf + """ + result = await client.call("convert_file_url", url=urls, enable_ocr=True) + print(f"多个转换结果: {result}") + + +async def convert_file_file_example(): + """转换本地 File 文件的示例。""" + client = MCPClient("http://localhost:8000") + + # 获取测试 File 的绝对路径 + script_dir = os.path.dirname(os.path.abspath(__file__)) + project_root = os.path.dirname(os.path.dirname(os.path.dirname(script_dir))) + test_file_path = os.path.join(project_root, "test_files", "test.pdf") + + # 转换单个 File 文件 + result = await client.call( + "convert_file_file", file_path=test_file_path, enable_ocr=True + ) + print(f"文件转换结果: {result}") + + +async def get_api_status_example(): + """获取 API 状态的示例。""" + client = MCPClient("http://localhost:8000") + + # 获取 API 状态 + status = await client.get_resource("status://api") + print(f"API 状态: {status}") + + # 获取使用帮助 + help_text = await client.get_resource("help://usage") + print(f"使用帮助: {help_text[:100]}...") # 显示前 100 个字符 + + +async def main(): + """运行所有示例。""" + print("运行 File 到 Markdown 转换示例...") + + # 检查是否设置了 API_KEY + if not os.environ.get("MINERU_API_KEY"): + print("警告: MINERU_API_KEY 环境变量未设置。") + print("使用以下命令设置: export MINERU_API_KEY=your_api_key") + print("跳过需要 API 访问的示例...") + + # 仅获取 API 状态 + await get_api_status_example() + else: + # 运行所有示例 + await convert_file_url_example() + await convert_file_file_example() + await get_api_status_example() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/projects/mcp/src/mineru/language.py b/projects/mcp/src/mineru/language.py new file mode 100644 index 0000000000000000000000000000000000000000..755ac1ec4b87571ba3b2ccdd8d7c2043c0f97899 --- /dev/null +++ b/projects/mcp/src/mineru/language.py @@ -0,0 +1,106 @@ +"""MinerU支持的语言列表。""" + +from typing import Dict, List + +# 支持的语言列表 +LANGUAGES: List[Dict[str, str]] = [ + {"name": "中文", "description": "Chinese & English", "code": "ch"}, + {"name": "英文", "description": "English", "code": "en"}, + {"name": "法文", "description": "French", "code": "fr"}, + {"name": "德文", "description": "German", "code": "german"}, + {"name": "日文", "description": "Japanese", "code": "japan"}, + {"name": "韩文", "description": "Korean", "code": "korean"}, + {"name": "中文繁体", "description": "Chinese Traditional", "code": "chinese_cht"}, + {"name": "意大利文", "description": "Italian", "code": "it"}, + {"name": "西班牙文", "description": "Spanish", "code": "es"}, + {"name": "葡萄牙文", "description": "Portuguese", "code": "pt"}, + {"name": "俄罗斯文", "description": "Russian", "code": "ru"}, + {"name": "阿拉伯文", "description": "Arabic", "code": "ar"}, + {"name": "印地文", "description": "Hindi", "code": "hi"}, + {"name": "维吾尔", "description": "Uyghur", "code": "ug"}, + {"name": "波斯文", "description": "Persian", "code": "fa"}, + {"name": "乌尔都文", "description": "Urdu", "code": "ur"}, + {"name": "塞尔维亚文(latin)", "description": "Serbian(latin)", "code": "rs_latin"}, + {"name": "欧西坦文", "description": "Occitan", "code": "oc"}, + {"name": "马拉地文", "description": "Marathi", "code": "mr"}, + {"name": "尼泊尔文", "description": "Nepali", "code": "ne"}, + { + "name": "塞尔维亚文(cyrillic)", + "description": "Serbian(cyrillic)", + "code": "rs_cyrillic", + }, + {"name": "毛利文", "description": "Maori", "code": "mi"}, + {"name": "马来文", "description": "Malay", "code": "ms"}, + {"name": "马耳他文", "description": "Maltese", "code": "mt"}, + {"name": "荷兰文", "description": "Dutch", "code": "nl"}, + {"name": "挪威文", "description": "Norwegian", "code": "no"}, + {"name": "波兰文", "description": "Polish", "code": "pl"}, + {"name": "罗马尼亚文", "description": "Romanian", "code": "ro"}, + {"name": "斯洛伐克文", "description": "Slovak", "code": "sk"}, + {"name": "斯洛文尼亚文", "description": "Slovenian", "code": "sl"}, + {"name": "阿尔巴尼亚文", "description": "Albanian", "code": "sq"}, + {"name": "瑞典文", "description": "Swedish", "code": "sv"}, + {"name": "西瓦希里文", "description": "Swahili", "code": "sw"}, + {"name": "塔加洛文", "description": "Tagalog", "code": "tl"}, + {"name": "土耳其文", "description": "Turkish", "code": "tr"}, + {"name": "乌兹别克文", "description": "Uzbek", "code": "uz"}, + {"name": "越南文", "description": "Vietnamese", "code": "vi"}, + {"name": "蒙古文", "description": "Mongolian", "code": "mn"}, + {"name": "车臣文", "description": "Chechen", "code": "che"}, + {"name": "哈里亚纳语", "description": "Haryanvi", "code": "bgc"}, + {"name": "保加利亚文", "description": "Bulgarian", "code": "bg"}, + {"name": "乌克兰文", "description": "Ukranian", "code": "uk"}, + {"name": "白俄罗斯文", "description": "Belarusian", "code": "be"}, + {"name": "泰卢固文", "description": "Telugu", "code": "te"}, + {"name": "阿巴扎文", "description": "Abaza", "code": "abq"}, + {"name": "泰米尔文", "description": "Tamil", "code": "ta"}, + {"name": "南非荷兰文", "description": "Afrikaans", "code": "af"}, + {"name": "阿塞拜疆文", "description": "Azerbaijani", "code": "az"}, + {"name": "波斯尼亚文", "description": "Bosnian", "code": "bs"}, + {"name": "捷克文", "description": "Czech", "code": "cs"}, + {"name": "威尔士文", "description": "Welsh", "code": "cy"}, + {"name": "丹麦文", "description": "Danish", "code": "da"}, + {"name": "爱沙尼亚文", "description": "Estonian", "code": "et"}, + {"name": "爱尔兰文", "description": "Irish", "code": "ga"}, + {"name": "克罗地亚文", "description": "Croatian", "code": "hr"}, + {"name": "匈牙利文", "description": "Hungarian", "code": "hu"}, + {"name": "印尼文", "description": "Indonesian", "code": "id"}, + {"name": "冰岛文", "description": "Icelandic", "code": "is"}, + {"name": "库尔德文", "description": "Kurdish", "code": "ku"}, + {"name": "立陶宛文", "description": "Lithuanian", "code": "lt"}, + {"name": "拉脱维亚文", "description": "Latvian", "code": "lv"}, + {"name": "达尔瓦文", "description": "Dargwa", "code": "dar"}, + {"name": "因古什文", "description": "Ingush", "code": "inh"}, + {"name": "拉克文", "description": "Lak", "code": "lbe"}, + {"name": "莱兹甘文", "description": "Lezghian", "code": "lez"}, + {"name": "塔巴萨兰文", "description": "Tabassaran", "code": "tab"}, + {"name": "比尔哈文", "description": "Bihari", "code": "bh"}, + {"name": "迈蒂利文", "description": "Maithili", "code": "mai"}, + {"name": "昂加文", "description": "Angika", "code": "ang"}, + {"name": "孟加拉文", "description": "Bhojpuri", "code": "bho"}, + {"name": "摩揭陀文", "description": "Magahi", "code": "mah"}, + {"name": "那格浦尔文", "description": "Nagpur", "code": "sck"}, + {"name": "尼瓦尔文", "description": "Newari", "code": "new"}, + {"name": "保加利亚文", "description": "Goan Konkani", "code": "gom"}, + {"name": "梵文", "description": "Sanskrit", "code": "sa"}, + {"name": "阿瓦尔文", "description": "Avar", "code": "ava"}, + {"name": "阿瓦尔文", "description": "Avar", "code": "ava"}, + {"name": "阿迪赫文", "description": "Adyghe", "code": "ady"}, + {"name": "巴利文", "description": "Pali", "code": "pi"}, + {"name": "拉丁文", "description": "Latin", "code": "la"}, +] + +# 构建语言代码到语言信息的映射字典,便于快速查找 +LANGUAGES_DICT: Dict[str, Dict[str, str]] = {lang["code"]: lang for lang in LANGUAGES} + + +def get_language_list() -> List[Dict[str, str]]: + """获取所有支持的语言列表。""" + return LANGUAGES + + +def get_language_by_code(code: str) -> Dict[str, str]: + """根据语言代码获取语言信息。""" + return LANGUAGES_DICT.get( + code, {"name": "未知", "description": "Unknown", "code": code} + ) diff --git a/projects/mcp/src/mineru/server.py b/projects/mcp/src/mineru/server.py new file mode 100644 index 0000000000000000000000000000000000000000..61f18119a249318546c507e31ae47b819e903056 --- /dev/null +++ b/projects/mcp/src/mineru/server.py @@ -0,0 +1,1060 @@ +"""MinerU File转Markdown转换的FastMCP服务器实现。""" + +import json +import re +import traceback +from pathlib import Path +from typing import Annotated, Any, Dict, List, Optional + +import aiohttp +import uvicorn +from fastmcp import FastMCP +from mcp.server.sse import SseServerTransport +from pydantic import Field +from starlette.applications import Starlette +from starlette.requests import Request +from starlette.routing import Mount, Route + +from . import config +from .api import MinerUClient +from .language import get_language_list + +# 初始化 FastMCP 服务器 +mcp = FastMCP( + name="MinerU File to Markdown Conversion", + instructions=""" + 一个将文档转化工具,可以将文档转化成Markdown、Json等格式,支持多种文件格式,包括 + PDF、Word、PPT以及图片格式(JPG、PNG、JPEG)。 + + 系统工具: + parse_documents: 解析文档(支持本地文件和URL,自动读取内容) + get_ocr_languages: 获取OCR支持的语言列表 + """, +) + +# 全局客户端实例 +_client_instance: Optional[MinerUClient] = None + + +def create_starlette_app(mcp_server, *, debug: bool = False) -> Starlette: + """创建用于SSE传输的Starlette应用。 + + Args: + mcp_server: MCP服务器实例 + debug: 是否启用调试模式 + + Returns: + Starlette: 配置好的Starlette应用实例 + """ + sse = SseServerTransport("/messages/") + + async def handle_sse(request: Request) -> None: + """处理SSE连接请求。""" + async with sse.connect_sse( + request.scope, + request.receive, + request._send, + ) as (read_stream, write_stream): + await mcp_server.run( + read_stream, + write_stream, + mcp_server.create_initialization_options(), + ) + + return Starlette( + debug=debug, + routes=[ + Route("/sse", endpoint=handle_sse), + Mount("/messages/", app=sse.handle_post_message), + ], + ) + + +def run_server(mode=None, port=8001, host="127.0.0.1"): + """运行 FastMCP 服务器。 + + Args: + mode: 运行模式,支持stdio、sse、streamable-http + port: 服务器端口,默认为8001,仅在HTTP模式下有效 + host: 服务器主机地址,默认为127.0.0.1,仅在HTTP模式下有效 + """ + # 确保输出目录存在 + config.ensure_output_dir(output_dir) + + # 检查是否设置了 API 密钥 + if not config.MINERU_API_KEY: + config.logger.warning("警告: MINERU_API_KEY 环境变量未设置。") + config.logger.warning("使用以下命令设置: export MINERU_API_KEY=your_api_key") + + # 获取MCP服务器实例 + mcp_server = mcp._mcp_server + + try: + # 运行服务器 + if mode == "sse": + config.logger.info(f"启动SSE服务器: {host}:{port}") + starlette_app = create_starlette_app(mcp_server, debug=True) + uvicorn.run(starlette_app, host=host, port=port) + elif mode == "streamable-http": + config.logger.info(f"启动Streamable HTTP服务器: {host}:{port}") + # 在HTTP模式下传递端口参数 + mcp.run(mode, port=port) + else: + # 默认stdio模式 + config.logger.info("启动STDIO服务器") + mcp.run(mode or "stdio") + except Exception as e: + config.logger.error(f"\n❌ 服务异常退出: {str(e)}") + traceback.print_exc() + finally: + # 清理资源 + cleanup_resources() + + +def cleanup_resources(): + """清理全局资源。""" + global _client_instance + if _client_instance is not None: + try: + # 如果客户端有close方法,调用它 + if hasattr(_client_instance, "close"): + _client_instance.close() + except Exception as e: + config.logger.error(f"清理客户端资源时出错: {str(e)}") + finally: + _client_instance = None + config.logger.info("资源清理完成") + + +def get_client() -> MinerUClient: + """获取 MinerUClient 的单例实例。如果尚未初始化,则进行初始化。""" + global _client_instance + if _client_instance is None: + _client_instance = MinerUClient() # Initialization happens here + return _client_instance + + +# Markdown 文件的输出目录 +output_dir = config.DEFAULT_OUTPUT_DIR + + +def set_output_dir(dir_path: str): + """设置转换后文件的输出目录。""" + global output_dir + output_dir = dir_path + config.ensure_output_dir(output_dir) + return output_dir + + +def parse_list_input(input_str: str) -> List[str]: + """ + 解析可能包含由逗号或换行符分隔的多个项目的字符串输入。 + + Args: + input_str: 可能包含多个项目的字符串 + + Returns: + 解析出的项目列表 + """ + if not input_str: + return [] + + # 按逗号、换行符或空格分割 + items = re.split(r"[,\n\s]+", input_str) + + # 移除空项目并处理带引号的项目 + result = [] + for item in items: + item = item.strip() + # 如果存在引号,则移除 + if (item.startswith('"') and item.endswith('"')) or ( + item.startswith("'") and item.endswith("'") + ): + item = item[1:-1] + + if item: + result.append(item) + + return result + + +async def convert_file_url( + url: str, + enable_ocr: bool = False, + language: str = "ch", + page_ranges: str | None = None, +) -> Dict[str, Any]: + """ + 从URL转换文件到Markdown格式。支持单个或多个URL处理。 + + 返回: + 成功: {"status": "success", "result_path": "输出目录路径"} + 失败: {"status": "error", "error": "错误信息"} + """ + urls_to_process = None + + # 检查是否为字典或字典列表格式的URL配置 + if isinstance(url, dict): + # 单个URL配置字典 + urls_to_process = url + elif isinstance(url, list) and len(url) > 0 and isinstance(url[0], dict): + # URL配置字典列表 + urls_to_process = url + elif isinstance(url, str): + # 检查是否为 JSON 字符串格式的多URL配置 + if url.strip().startswith("[") and url.strip().endswith("]"): + try: + # 尝试解析 JSON 字符串为URL配置列表 + url_configs = json.loads(url) + if not isinstance(url_configs, list): + raise ValueError("JSON URL配置必须是列表格式") + + urls_to_process = url_configs + except json.JSONDecodeError: + # 不是有效的 JSON,继续使用字符串解析方式 + pass + + if urls_to_process is None: + # 解析普通URL列表 + urls = parse_list_input(url) + + if not urls: + raise ValueError("未提供有效的 URL") + + if len(urls) == 1: + # 单个URL处理 + urls_to_process = {"url": urls[0], "is_ocr": enable_ocr} + else: + # 多个URL,转换为URL配置列表 + urls_to_process = [] + for url_item in urls: + urls_to_process.append( + { + "url": url_item, + "is_ocr": enable_ocr, + } + ) + + # 使用submit_file_url_task处理URLs + try: + result_path = await get_client().process_file_to_markdown( + lambda urls, o: get_client().submit_file_url_task( + urls, + o, + language=language, + page_ranges=page_ranges, + ), + urls_to_process, + enable_ocr, + output_dir, + ) + return {"status": "success", "result_path": result_path} + except Exception as e: + return {"status": "error", "error": str(e)} + + +async def convert_file_path( + file_path: str, + enable_ocr: bool = False, + language: str = "ch", + page_ranges: str | None = None, +) -> Dict[str, Any]: + """ + 将本地文件转换为Markdown格式。支持单个或多个文件批量处理。 + + 返回: + 成功: {"status": "success", "result_path": "输出目录路径"} + 失败: {"status": "error", "error": "错误信息"} + """ + + files_to_process = None + + # 检查是否为字典或字典列表格式的文件配置 + if isinstance(file_path, dict): + # 单个文件配置字典 + files_to_process = file_path + elif ( + isinstance(file_path, list) + and len(file_path) > 0 + and isinstance(file_path[0], dict) + ): + # 文件配置字典列表 + files_to_process = file_path + elif isinstance(file_path, str): + # 检查是否为 JSON 字符串格式的多文件配置 + if file_path.strip().startswith("[") and file_path.strip().endswith("]"): + try: + # 尝试解析 JSON 字符串为文件配置列表 + file_configs = json.loads(file_path) + if not isinstance(file_configs, list): + raise ValueError("JSON 文件配置必须是列表格式") + + files_to_process = file_configs + except json.JSONDecodeError: + # 不是有效的 JSON,继续使用字符串解析方式 + pass + + if files_to_process is None: + # 解析普通文件路径列表 + file_paths = parse_list_input(file_path) + + if not file_paths: + raise ValueError("未提供有效的文件路径") + + if len(file_paths) == 1: + # 单个文件处理 + files_to_process = { + "path": file_paths[0], + "is_ocr": enable_ocr, + } + else: + # 多个文件路径,转换为文件配置列表 + files_to_process = [] + for i, path in enumerate(file_paths): + files_to_process.append( + { + "path": path, + "is_ocr": enable_ocr, + } + ) + + # 使用submit_file_task处理文件 + try: + result_path = await get_client().process_file_to_markdown( + lambda files, o: get_client().submit_file_task( + files, + o, + language=language, + page_ranges=page_ranges, + ), + files_to_process, + enable_ocr, + output_dir, + ) + return {"status": "success", "result_path": result_path} + except Exception as e: + return { + "status": "error", + "error": str(e), + "params": { + "file_path": file_path, + "enable_ocr": enable_ocr, + "language": language, + }, + } + + +async def local_parse_file( + file_path: str, + parse_method: str = "auto", +) -> Dict[str, Any]: + """ + 根据环境变量设置使用本地或远程API解析文件。 + + 返回: + 成功: {"status": "success", "result": 处理结果} 或 {"status": "success", "result_path": "输出目录路径"} + 失败: {"status": "error", "error": "错误信息"} + """ + file_path = Path(file_path) + + # 检查文件是否存在 + if not file_path.exists(): + return {"status": "error", "error": f"文件不存在: {file_path}"} + + try: + # 根据环境变量决定使用本地API还是远程API + if config.USE_LOCAL_API: + config.logger.debug(f"使用本地API: {config.LOCAL_MINERU_API_BASE}") + return await _parse_file_local( + file_path=str(file_path), + parse_method=parse_method, + ) + else: + return {"status": "error", "error": "远程API未配置"} + except Exception as e: + config.logger.error(f"解析文件时出错: {str(e)}") + return {"status": "error", "error": str(e)} + + +async def read_converted_file( + file_path: str, +) -> Dict[str, Any]: + """ + 读取解析后的文件内容。主要支持Markdown和其他文本文件格式。 + + 返回: + 成功: {"status": "success", "content": "文件内容"} + 失败: {"status": "error", "error": "错误信息"} + """ + try: + target_file = Path(file_path) + parent_dir = target_file.parent + suffix = target_file.suffix.lower() + + # 支持的文本文件格式 + text_extensions = [".md", ".txt", ".json", ".html", ".tex", ".latex"] + + if suffix not in text_extensions: + return { + "status": "error", + "error": f"不支持的文件格式: {suffix}。目前仅支持以下格式: {', '.join(text_extensions)}", + } + + if not target_file.exists(): + if not parent_dir.exists(): + return {"status": "error", "error": f"目录 {parent_dir} 不存在"} + + # 递归搜索所有子目录下的同后缀文件 + similar_files_paths = [ + str(f) for f in parent_dir.rglob(f"*{suffix}") if f.is_file() + ] + + if similar_files_paths: + if len(similar_files_paths) == 1: + # 如果只找到一个文件,直接读取并返回内容 + alternative_file = similar_files_paths[0] + try: + with open(alternative_file, "r", encoding="utf-8") as f: + content = f.read() + return { + "status": "success", + "content": content, + "message": f"未找到文件 {target_file.name},但找到了 {Path(alternative_file).name},已返回其内容", + } + except Exception as e: + return { + "status": "error", + "error": f"尝试读取替代文件时出错: {str(e)}", + } + else: + # 如果找到多个文件,提供建议列表 + suggestion = f"你是否在找: {', '.join(similar_files_paths)}?" + return { + "status": "error", + "error": f"文件 {target_file.name} 不存在。在 {parent_dir} 及其子目录下找到以下同类型文件。{suggestion}", + } + else: + return { + "status": "error", + "error": f"文件 {target_file.name} 不存在,且在目录 {parent_dir} 及其子目录下未找到其他 {suffix} 文件。", + } + + # 以文本模式读取 + with open(target_file, "r", encoding="utf-8") as f: + content = f.read() + return {"status": "success", "content": content} + + except Exception as e: + config.logger.error(f"读取文件时出错: {str(e)}") + return {"status": "error", "error": str(e)} + + +async def find_and_read_markdown_content(result_path: str) -> Dict[str, Any]: + """ + 在给定的路径中寻找并读取Markdown文件内容。 + 查找所有可能的文件位置,返回所有找到的有效内容。 + + Args: + result_path: 结果目录路径 + + Returns: + Dict[str, Any]: 包含所有文件内容或错误信息的字典 + """ + if not result_path: + return {"status": "warning", "message": "未提供有效的结果路径"} + + base_path = Path(result_path) + if not base_path.exists(): + return {"status": "warning", "message": f"结果路径不存在: {result_path}"} + + # 使用集合来存储文件路径,确保唯一性 + unique_files = set() + + # 添加常见文件名 + common_files = [ + base_path / "full.md", + base_path / "full.txt", + base_path / "output.md", + base_path / "result.md", + ] + for f in common_files: + if f.exists(): + unique_files.add(str(f)) + + # 添加子目录中的常见文件名 + for subdir in base_path.iterdir(): + if subdir.is_dir(): + subdir_files = [ + subdir / "full.md", + subdir / "full.txt", + subdir / "output.md", + subdir / "result.md", + ] + for f in subdir_files: + if f.exists(): + unique_files.add(str(f)) + + # 查找所有的.md和.txt文件 + for md_file in base_path.glob("**/*.md"): + unique_files.add(str(md_file)) + for txt_file in base_path.glob("**/*.txt"): + unique_files.add(str(txt_file)) + + # 将集合转换回Path对象列表 + possible_files = [Path(f) for f in unique_files] + + config.logger.debug(f"找到 {len(possible_files)} 个可能的文件") + + # 收集所有找到的有效文件内容 + found_contents = [] + + # 尝试读取每个可能的文件 + for file_path in possible_files: + if file_path.exists(): + result = await read_converted_file(str(file_path)) + if result["status"] == "success": + config.logger.debug(f"成功读取文件内容: {file_path}") + found_contents.append( + {"file_path": str(file_path), "content": result["content"]} + ) + + # 如果找到了文件内容 + if found_contents: + config.logger.debug(f"在结果目录中找到了 {len(found_contents)} 个可读取的文件") + # 如果只找到一个文件,保持向后兼容的返回格式 + if len(found_contents) == 1: + return { + "status": "success", + "content": found_contents[0]["content"], + "file_path": found_contents[0]["file_path"], + } + # 如果找到多个文件,返回内容列表 + else: + return {"status": "success", "contents": found_contents} + + # 如果没有找到任何有效的文件 + return { + "status": "warning", + "message": f"无法在结果目录中找到可读取的Markdown文件: {result_path}", + } + + +async def _process_conversion_result( + result: Dict[str, Any], source: str, is_url: bool = False +) -> Dict[str, Any]: + """ + 处理转换结果,统一格式化输出。 + + Args: + result: 转换函数返回的结果 + source: 源文件路径或URL + is_url: 是否为URL + + Returns: + 格式化后的结果字典 + """ + filename = source.split("/")[-1] + if is_url and "?" in filename: + filename = filename.split("?")[0] + elif not is_url: + filename = Path(source).name + + base_result = { + "filename": filename, + "source_url" if is_url else "source_path": source, + } + + if result["status"] == "success": + # 获取result_path,可能是字符串或字典 + result_path = result.get("result_path") + + # 记录调试信息 + config.logger.debug(f"处理结果 result_path 类型: {type(result_path)}") + + if result_path: + # 情况1: result_path是字典且包含results字段(批量处理结果) + if isinstance(result_path, dict) and "results" in result_path: + config.logger.debug("检测到批量处理结果格式") + + # 查找与当前源文件匹配的结果 + for item in result_path.get("results", []): + if item.get("filename") == filename or ( + not is_url and Path(source).name == item.get("filename") + ): + # 直接返回匹配项的状态,无论是success还是error + if item.get("status") == "success" and "content" in item: + base_result.update( + { + "status": "success", + "content": item.get("content", ""), + } + ) + # 如果有extract_path,也添加进去 + if "extract_path" in item: + base_result["extract_path"] = item["extract_path"] + return base_result + elif item.get("status") == "error": + # 处理失败的文件,直接返回error状态 + base_result.update( + { + "status": "error", + "error_message": item.get( + "error_message", "文件处理失败" + ), + } + ) + return base_result + + # 如果没有找到匹配的结果,但有extract_dir,尝试从那里读取 + if "extract_dir" in result_path: + config.logger.debug( + f"尝试从extract_dir读取: {result_path['extract_dir']}" + ) + try: + content_result = await find_and_read_markdown_content( + result_path["extract_dir"] + ) + if content_result.get("status") == "success": + base_result.update( + { + "status": "success", + "content": content_result.get("content", ""), + "extract_path": result_path["extract_dir"], + } + ) + return base_result + except Exception as e: + config.logger.error(f"从extract_dir读取内容时出错: {str(e)}") + + # 如果上述方法都失败,返回错误 + base_result.update( + { + "status": "error", + "error_message": "未能在批量处理结果中找到匹配的内容", + } + ) + + # 情况2: result_path是字符串(传统格式) + elif isinstance(result_path, str): + config.logger.debug(f"处理传统格式结果路径: {result_path}") + content_result = await find_and_read_markdown_content(result_path) + if content_result.get("status") == "success": + base_result.update( + { + "status": "success", + "content": content_result.get("content", ""), + "extract_path": result_path, + } + ) + else: + base_result.update( + { + "status": "error", + "error_message": f"无法读取转换结果: {content_result.get('message', '')}", + } + ) + + # 情况3: result_path是其他类型的字典(尝试处理) + elif isinstance(result_path, dict): + config.logger.debug(f"处理其他字典格式: {result_path}") + # 尝试从字典中提取可能的路径 + extract_path = ( + result_path.get("extract_dir") + or result_path.get("path") + or result_path.get("dir") + ) + if extract_path and isinstance(extract_path, str): + try: + content_result = await find_and_read_markdown_content( + extract_path + ) + if content_result.get("status") == "success": + base_result.update( + { + "status": "success", + "content": content_result.get("content", ""), + "extract_path": extract_path, + } + ) + return base_result + except Exception as e: + config.logger.error(f"从extract_path读取内容时出错: {str(e)}") + + # 如果没有找到有效路径,返回错误 + base_result.update( + {"status": "error", "error_message": "转换结果格式无法识别"} + ) + else: + # 情况4: result_path是其他类型(错误) + base_result.update( + { + "status": "error", + "error_message": f"无法识别的result_path类型: {type(result_path)}", + } + ) + else: + base_result.update( + {"status": "error", "error_message": "转换成功但未返回结果路径"} + ) + else: + base_result.update( + {"status": "error", "error_message": result.get("error", "未知错误")} + ) + + return base_result + + +@mcp.tool() +async def parse_documents( + file_sources: Annotated[ + str, + Field( + description="""文件路径或URL,支持以下格式: + - 单个路径或URL: "/path/to/file.pdf" 或 "https://example.com/document.pdf" + - 多个路径或URL(逗号分隔): "/path/to/file1.pdf, /path/to/file2.pdf" 或 + "https://example.com/doc1.pdf, https://example.com/doc2.pdf" + - 混合路径和URL: "/path/to/file.pdf, https://example.com/document.pdf" + (支持pdf、ppt、pptx、doc、docx以及图片格式jpg、jpeg、png)""" + ), + ], + # 通用参数 + enable_ocr: Annotated[bool, Field(description="启用OCR识别,默认False")] = False, + language: Annotated[ + str, Field(description='文档语言,默认"ch"中文,可选"en"英文等') + ] = "ch", + # 远程API参数 + page_ranges: Annotated[ + str | None, + Field( + description='指定页码范围,格式为逗号分隔的字符串。例如:"2,4-6":表示选取第2页、第4页至第6页;"2--2":表示从第2页一直选取到倒数第二页。(远程API),默认None' + ), + ] = None, +) -> Dict[str, Any]: + """ + 统一接口,将文件转换为Markdown格式。支持本地文件和URL,会根据USE_LOCAL_API配置自动选择合适的处理方式。 + + 当USE_LOCAL_API=true时: + - 会过滤掉http/https开头的URL路径 + - 对本地文件使用本地API进行解析 + + 当USE_LOCAL_API=false时: + - 将http/https开头的路径使用convert_file_url处理 + - 将其他路径使用convert_file_path处理 + + 处理完成后,会自动尝试读取转换后的文件内容并返回。 + + 返回: + 成功: {"status": "success", "content": "文件内容"} 或 {"status": "success", "results": [处理结果列表]} + 失败: {"status": "error", "error": "错误信息"} + """ + # 解析路径列表 + sources = parse_list_input(file_sources) + if not sources: + return {"status": "error", "error": "未提供有效的文件路径或URL"} + + # 去重处理,使用字典来保持原始顺序 + sources = list(dict.fromkeys(sources)) + + config.logger.debug(f"去重后的文件路径: {sources}") + + # 记录去重信息 + original_count = len(parse_list_input(file_sources)) + unique_count = len(sources) + if original_count > unique_count: + config.logger.debug( + f"检测到重复路径,已自动去重: {original_count} -> {unique_count}" + ) + + # 将路径分类 + url_paths = [] + file_paths = [] + + for source in sources: + if source.lower().startswith(("http://", "https://")): + url_paths.append(source) + else: + file_paths.append(source) + + results = [] + + # 根据USE_LOCAL_API决定处理方式 + if config.USE_LOCAL_API: + # 在本地API模式下,只处理本地文件路径 + if not file_paths: + return { + "status": "warning", + "message": "在本地API模式下,无法处理URL,且未提供有效的本地文件路径", + } + + config.logger.info(f"使用本地API处理 {len(file_paths)} 个文件") + + # 逐个处理本地文件 + for path in file_paths: + try: + # 跳过不存在的文件 + if not Path(path).exists(): + results.append( + { + "filename": Path(path).name, + "source_path": path, + "status": "error", + "error_message": f"文件不存在: {path}", + } + ) + continue + + result = await local_parse_file( + file_path=path, + parse_method=( + "ocr" if enable_ocr else "txt" + ), # 如果启用OCR,使用ocr,否则使用txt + ) + + # 添加文件名信息 + result_with_filename = { + "filename": Path(path).name, + "source_path": path, + **result, + } + results.append(result_with_filename) + + except Exception as e: + # 处理文件时出现异常,记录错误但继续处理下一个文件 + config.logger.error(f"处理文件 {path} 时出现错误: {str(e)}") + results.append( + { + "filename": Path(path).name, + "source_path": path, + "status": "error", + "error_message": f"处理文件时出现异常: {str(e)}", + } + ) + + else: + # 在远程API模式下,分别处理URL和本地文件路径 + if url_paths: + config.logger.info(f"使用远程API处理 {len(url_paths)} 个文件URL") + + try: + # 调用convert_file_url处理URLs + url_result = await convert_file_url( + url=",".join(url_paths), + enable_ocr=enable_ocr, + language=language, + page_ranges=page_ranges, + ) + + if url_result["status"] == "success": + # 为每个URL生成对应的结果 + for url in url_paths: + result_item = await _process_conversion_result( + url_result, url, is_url=True + ) + results.append(result_item) + else: + # 转换失败,为所有URL添加错误结果 + for url in url_paths: + results.append( + { + "filename": url.split("/")[-1].split("?")[0], + "source_url": url, + "status": "error", + "error_message": url_result.get("error", "URL处理失败"), + } + ) + + except Exception as e: + config.logger.error(f"处理URL时出现错误: {str(e)}") + for url in url_paths: + results.append( + { + "filename": url.split("/")[-1].split("?")[0], + "source_url": url, + "status": "error", + "error_message": f"处理URL时出现异常: {str(e)}", + } + ) + + if file_paths: + config.logger.info(f"使用远程API处理 {len(file_paths)} 个本地文件") + + # 过滤出存在的文件 + existing_files = [] + for file_path in file_paths: + if not Path(file_path).exists(): + results.append( + { + "filename": Path(file_path).name, + "source_path": file_path, + "status": "error", + "error_message": f"文件不存在: {file_path}", + } + ) + else: + existing_files.append(file_path) + + if existing_files: + try: + # 调用convert_file_path处理本地文件 + file_result = await convert_file_path( + file_path=",".join(existing_files), + enable_ocr=enable_ocr, + language=language, + page_ranges=page_ranges, + ) + + config.logger.debug(f"file_result: {file_result}") + + if file_result["status"] == "success": + # 为每个文件生成对应的结果 + for file_path in existing_files: + result_item = await _process_conversion_result( + file_result, file_path, is_url=False + ) + results.append(result_item) + else: + # 转换失败,为所有文件添加错误结果 + for file_path in existing_files: + results.append( + { + "filename": Path(file_path).name, + "source_path": file_path, + "status": "error", + "error_message": file_result.get( + "error", "文件处理失败" + ), + } + ) + + except Exception as e: + config.logger.error(f"处理本地文件时出现错误: {str(e)}") + for file_path in existing_files: + results.append( + { + "filename": Path(file_path).name, + "source_path": file_path, + "status": "error", + "error_message": f"处理文件时出现异常: {str(e)}", + } + ) + + # 处理结果为空的情况 + if not results: + return {"status": "error", "error": "未处理任何文件"} + + # 计算成功和失败的统计信息 + success_count = len([r for r in results if r.get("status") == "success"]) + error_count = len([r for r in results if r.get("status") == "error"]) + total_count = len(results) + + # 只有一个结果时,直接返回该结果(保持向后兼容) + if len(results) == 1: + result = results[0].copy() + # 为了向后兼容,移除新增的字段 + if "filename" in result: + del result["filename"] + if "source_path" in result: + del result["source_path"] + if "source_url" in result: + del result["source_url"] + return result + + # 多个结果时,返回详细的结果列表 + # 根据成功/失败情况决定整体状态 + overall_status = "success" + if success_count == 0: + # 所有文件都失败 + overall_status = "error" + elif error_count > 0: + # 有部分文件失败,但不是全部 + overall_status = "partial_success" + + return { + "status": overall_status, + "results": results, + "summary": { + "total_files": total_count, + "success_count": success_count, + "error_count": error_count, + }, + } + + +@mcp.tool() +async def get_ocr_languages() -> Dict[str, Any]: + """ + 获取 OCR 支持的语言列表。 + + Returns: + Dict[str, Any]: 包含所有支持的OCR语言列表的字典 + """ + try: + # 从language模块获取语言列表 + languages = get_language_list() + return {"status": "success", "languages": languages} + except Exception as e: + return {"status": "error", "error": str(e)} + + +async def _parse_file_local( + file_path: str, + parse_method: str = "auto", +) -> Dict[str, Any]: + """ + 使用本地API解析文件。 + + Args: + file_path: 要解析的文件路径 + parse_method: 解析方法 + output_dir: 输出目录 + + Returns: + Dict[str, Any]: 包含解析结果的字典 + """ + # API URL路径 + api_url = f"{config.LOCAL_MINERU_API_BASE}/file_parse" + + # 使用Path对象确保文件路径正确 + file_path_obj = Path(file_path) + if not file_path_obj.exists(): + raise FileNotFoundError(f"文件不存在: {file_path}") + + # 读取文件二进制数据 + with open(file_path_obj, "rb") as f: + file_data = f.read() + + # 准备用于上传文件的表单数据 + file_type = file_path_obj.suffix.lower() + form_data = aiohttp.FormData() + form_data.add_field( + "file", file_data, filename=file_path_obj.name, content_type=file_type + ) + form_data.add_field("parse_method", parse_method) + + config.logger.debug(f"发送本地API请求到: {api_url}") + config.logger.debug(f"上传文件: {file_path_obj.name} (大小: {len(file_data)} 字节)") + + # 发送请求 + try: + async with aiohttp.ClientSession() as session: + async with session.post(api_url, data=form_data) as response: + if response.status != 200: + error_text = await response.text() + config.logger.error( + f"API返回错误状态码: {response.status}, 错误信息: {error_text}" + ) + raise RuntimeError(f"API返回错误: {response.status}, {error_text}") + + result = await response.json() + + config.logger.debug(f"本地API响应: {result}") + + # 处理响应 + if "error" in result: + return {"status": "error", "error": result["error"]} + + return {"status": "success", "result": result} + except aiohttp.ClientError as e: + error_msg = f"与本地API通信时出错: {str(e)}" + config.logger.error(error_msg) + raise RuntimeError(error_msg) diff --git a/projects/web/.gitignore b/projects/web/.gitignore deleted file mode 100644 index a547bf36d8d11a4f89c59c144f24795749086dd1..0000000000000000000000000000000000000000 --- a/projects/web/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/projects/web/README.md b/projects/web/README.md deleted file mode 100644 index 68a4ec70b38da1f0b3869b89b6e23c29ca007395..0000000000000000000000000000000000000000 --- a/projects/web/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# MinerU web - -## Table of Contents -- [Local Frontend Development](#local-frontend-development) -- [Technology Stack](#technology-stack) - -## Local Frontend Development - -### Prerequisites -- Node.js 18.x -- pnpm - -### Installation Steps - -1. Install Node.js 18 - - Visit the [Node.js official website](https://nodejs.org/) to download and install Node.js version 18.x - -2. Install pnpm - ```bash - npm install -g pnpm -3. Clone the repository - ```git clone https://github.com/opendatalab/MinerU - cd ./projects/web - ``` -4. Install dependencies - ``` - pnpm install - ``` -5. Run the development server - ``` - pnpm run dev - ``` -6. ⚠️ Note: This command is for local development only, do not use for deployment! -Open your browser and visit http://localhost:5173 (or another address output in the console) - -7. Ensure that the backend service in ./projects/web_demo is running - -8. If you encounter an error when executing `pnpm install`, you can switch to an alternative package manager. - ``` - npm install -g yarn - yarn - yarn start - ``` - - -## Building the Project -``` -pnpm run build -``` -## Technology Stack -- React -- Tailwind CSS -- typeScript -- zustand -- ahooks diff --git a/projects/web/README_zh-CN.md b/projects/web/README_zh-CN.md deleted file mode 100644 index 64724bb27b7ec44a534e4282a20ebb2124c5fb13..0000000000000000000000000000000000000000 --- a/projects/web/README_zh-CN.md +++ /dev/null @@ -1,61 +0,0 @@ -# MinerU web - - -## 目录 -- [前端本地开发](#前端本地开发) -- [技术栈](#技术栈) -## 前端本地开发 - -### 前置条件 -- Node.js 18.x -- pnpm - -### 安装步骤 - -1. 安装 Node.js 18 - - 访问 [Node.js 官网](https://nodejs.org/) 下载并安装 Node.js 18.x 版本 - -2. 安装 pnpm - ```bash - npm install -g pnpm - ``` -3. 克隆仓库 - ``` - 1. git clone https://github.com/opendatalab/MinerU - 2. cd ./projects/web - ``` - -4. 安装依赖 - ``` - pnpm install - ``` - -5. 运行开发服务器 - ``` - pnpm run dev - ``` - -6. ⚠️ 注意:此命令仅用于本地开发,不要用于部署! -打开浏览器访问 http://localhost:5173(或控制台输出的其他地址) -构建项目 -要构建生产版本,请执行以下命令: - - ``` - pnpm run build - ``` -7. 请确保./projects/web_demo后端服务启动 - -8. 如果pnpm install执行error,可更换包管理器 - ``` - npm install -g yarn - yarn - yarn start - ``` - -## 技术栈 - -- React -- Tailwind CSS -- typeScript -- zustand -- ahooks diff --git a/projects/web/eslint.config.js b/projects/web/eslint.config.js deleted file mode 100644 index 092408a9f09eae19150818b4f0db5d1b70744828..0000000000000000000000000000000000000000 --- a/projects/web/eslint.config.js +++ /dev/null @@ -1,28 +0,0 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' - -export default tseslint.config( - { ignores: ['dist'] }, - { - extends: [js.configs.recommended, ...tseslint.configs.recommended], - files: ['**/*.{ts,tsx}'], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - plugins: { - 'react-hooks': reactHooks, - 'react-refresh': reactRefresh, - }, - rules: { - ...reactHooks.configs.recommended.rules, - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - }, - }, -) diff --git a/projects/web/index.html b/projects/web/index.html deleted file mode 100644 index dfb16ecdfb0540e043ce7cd68502586c61255a79..0000000000000000000000000000000000000000 --- a/projects/web/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - MinerU - - -
    - - - diff --git a/projects/web/package-lock.json b/projects/web/package-lock.json deleted file mode 100644 index 88dec5cbbf6a44501fd198bc821c156289c929c4..0000000000000000000000000000000000000000 --- a/projects/web/package-lock.json +++ /dev/null @@ -1,15512 +0,0 @@ -{ - "name": "my-react-app", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "my-react-app", - "version": "0.0.0", - "dependencies": { - "@codemirror/view": "^6.33.0", - "@types/lodash": "^4.17.7", - "@types/qs": "^6.9.15", - "@types/react-copy-to-clipboard": "^5.0.7", - "@types/react-syntax-highlighter": "^15.5.13", - "@uiw/codemirror-extensions-langs": "^4.23.0", - "@uiw/react-codemirror": "^4.23.0", - "ahooks": "^3.8.1", - "antd": "^5.20.3", - "axios": "^1.7.5", - "classnames": "^2.5.1", - "js-cookie": "^3.0.5", - "lodash": "^4.17.21", - "qs": "^6.13.0", - "react": "^18.3.1", - "react-copy-to-clipboard": "^5.1.0", - "react-dom": "^18.3.1", - "react-intl": "^6.6.8", - "react-markdown": "^9.0.1", - "react-router-dom": "^6.26.1", - "react-syntax-highlighter": "^15.5.0", - "rehype-katex": "^7.0.1", - "rehype-raw": "^7.0.0", - "remark-gfm": "^4.0.0", - "remark-math": "^6.0.0", - "zustand": "^4.5.5" - }, - "devDependencies": { - "@eslint/js": "^9.9.0", - "@types/js-cookie": "^3.0.6", - "@types/node": "^22.5.1", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.1", - "autoprefixer": "^10.4.20", - "eslint": "^9.9.0", - "eslint-plugin-react-hooks": "^5.1.0-rc.0", - "eslint-plugin-react-refresh": "^0.4.9", - "globals": "^15.9.0", - "postcss": "^8.4.41", - "sass-embedded": "^1.77.8", - "tailwindcss": "^3.4.10", - "ts-prune": "^0.10.3", - "typescript": "^5.5.3", - "typescript-eslint": "^8.0.1", - "vite": "^5.4.1" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@ant-design/colors": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.1.0.tgz", - "integrity": "sha512-MMoDGWn1y9LdQJQSHiCC20x3uZ3CwQnv9QMz6pCmJOrqdgM9YxsoVVY0wtrdXbmfSgnV0KNk6zi09NAhMR2jvg==", - "dependencies": { - "@ctrl/tinycolor": "^3.6.1" - } - }, - "node_modules/@ant-design/cssinjs": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.21.1.tgz", - "integrity": "sha512-tyWnlK+XH7Bumd0byfbCiZNK43HEubMoCcu9VxwsAwiHdHTgWa+tMN0/yvxa+e8EzuFP1WdUNNPclRpVtD33lg==", - "dependencies": { - "@babel/runtime": "^7.11.1", - "@emotion/hash": "^0.8.0", - "@emotion/unitless": "^0.7.5", - "classnames": "^2.3.1", - "csstype": "^3.1.3", - "rc-util": "^5.35.0", - "stylis": "^4.3.3" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/@ant-design/cssinjs-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.0.3.tgz", - "integrity": "sha512-BrztZZKuoYcJK8uEH40ylBemf/Mu/QPiDos56g2bv6eUoniQkgQHOCOvA3+pncoFO1TaS8xcUCIqGzDA0I+ZVQ==", - "dependencies": { - "@ant-design/cssinjs": "^1.21.0", - "@babel/runtime": "^7.23.2", - "rc-util": "^5.38.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@ant-design/fast-color": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", - "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", - "dependencies": { - "@babel/runtime": "^7.24.7" - }, - "engines": { - "node": ">=8.x" - } - }, - "node_modules/@ant-design/icons": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.4.0.tgz", - "integrity": "sha512-QZbWC5xQYexCI5q4/fehSEkchJr5UGtvAJweT743qKUQQGs9IH2DehNLP49DJ3Ii9m9CijD2HN6fNy3WKhIFdA==", - "dependencies": { - "@ant-design/colors": "^7.0.0", - "@ant-design/icons-svg": "^4.4.0", - "@babel/runtime": "^7.24.8", - "classnames": "^2.2.6", - "rc-util": "^5.31.1" - }, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/@ant-design/icons-svg": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", - "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==" - }, - "node_modules/@ant-design/react-slick": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", - "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", - "dependencies": { - "@babel/runtime": "^7.10.4", - "classnames": "^2.2.5", - "json2mq": "^0.2.0", - "resize-observer-polyfill": "^1.5.1", - "throttle-debounce": "^5.0.0" - }, - "peerDependencies": { - "react": ">=16.9.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.25.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.5.tgz", - "integrity": "sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.25.4", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", - "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.4.tgz", - "integrity": "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.25.4" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", - "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", - "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.4.tgz", - "integrity": "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.4", - "@babel/parser": "^7.25.4", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.4", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.4.tgz", - "integrity": "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bufbuild/protobuf": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.10.0.tgz", - "integrity": "sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==", - "dev": true - }, - "node_modules/@codemirror/autocomplete": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.0.tgz", - "integrity": "sha512-5DbOvBbY4qW5l57cjDsmmpDh3/TeK1vXfTHa+BUMrRzdWdcxKZ4U4V7vQaTtOpApNU4kLS4FQ6cINtLg245LXA==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0" - }, - "peerDependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@codemirror/commands": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.0.tgz", - "integrity": "sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.27.0", - "@lezer/common": "^1.1.0" - } - }, - "node_modules/@codemirror/lang-angular": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@codemirror/lang-angular/-/lang-angular-0.1.3.tgz", - "integrity": "sha512-xgeWGJQQl1LyStvndWtruUvb4SnBZDAu/gvFH/ZU+c0W25tQR8e5hq7WTwiIY2dNxnf+49mRiGI/9yxIwB6f5w==", - "dependencies": { - "@codemirror/lang-html": "^6.0.0", - "@codemirror/lang-javascript": "^6.1.2", - "@codemirror/language": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.3.3" - } - }, - "node_modules/@codemirror/lang-cpp": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-cpp/-/lang-cpp-6.0.2.tgz", - "integrity": "sha512-6oYEYUKHvrnacXxWxYa6t4puTlbN3dgV662BDfSH8+MfjQjVmP697/KYTDOqpxgerkvoNm7q5wlFMBeX8ZMocg==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@lezer/cpp": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-css": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz", - "integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.2", - "@lezer/css": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-go": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-go/-/lang-go-6.0.1.tgz", - "integrity": "sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.6.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/go": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-html": { - "version": "6.4.9", - "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz", - "integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/lang-css": "^6.0.0", - "@codemirror/lang-javascript": "^6.0.0", - "@codemirror/language": "^6.4.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0", - "@lezer/css": "^1.1.0", - "@lezer/html": "^1.3.0" - } - }, - "node_modules/@codemirror/lang-java": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-java/-/lang-java-6.0.1.tgz", - "integrity": "sha512-OOnmhH67h97jHzCuFaIEspbmsT98fNdhVhmA3zCxW0cn7l8rChDhZtwiwJ/JOKXgfm4J+ELxQihxaI7bj7mJRg==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@lezer/java": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-javascript": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz", - "integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.6.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0", - "@lezer/javascript": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-json": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz", - "integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@lezer/json": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-less": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-less/-/lang-less-6.0.2.tgz", - "integrity": "sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==", - "dependencies": { - "@codemirror/lang-css": "^6.2.0", - "@codemirror/language": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-lezer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-lezer/-/lang-lezer-6.0.1.tgz", - "integrity": "sha512-WHwjI7OqKFBEfkunohweqA5B/jIlxaZso6Nl3weVckz8EafYbPZldQEKSDb4QQ9H9BUkle4PVELP4sftKoA0uQ==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/lezer": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-liquid": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-liquid/-/lang-liquid-6.2.1.tgz", - "integrity": "sha512-J1Mratcm6JLNEiX+U2OlCDTysGuwbHD76XwuL5o5bo9soJtSbz2g6RU3vGHFyS5DC8rgVmFSzi7i6oBftm7tnA==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/lang-html": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.3.1" - } - }, - "node_modules/@codemirror/lang-markdown": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.2.5.tgz", - "integrity": "sha512-Hgke565YcO4fd9pe2uLYxnMufHO5rQwRr+AAhFq8ABuhkrjyX8R5p5s+hZUTdV60O0dMRjxKhBLxz8pu/MkUVA==", - "dependencies": { - "@codemirror/autocomplete": "^6.7.1", - "@codemirror/lang-html": "^6.0.0", - "@codemirror/language": "^6.3.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.2.1", - "@lezer/markdown": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-php": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-php/-/lang-php-6.0.1.tgz", - "integrity": "sha512-ublojMdw/PNWa7qdN5TMsjmqkNuTBD3k6ndZ4Z0S25SBAiweFGyY68AS3xNcIOlb6DDFDvKlinLQ40vSLqf8xA==", - "dependencies": { - "@codemirror/lang-html": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/php": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-python": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.6.tgz", - "integrity": "sha512-ai+01WfZhWqM92UqjnvorkxosZ2aq2u28kHvr+N3gu012XqY2CThD67JPMHnGceRfXPDBmn1HnyqowdpF57bNg==", - "dependencies": { - "@codemirror/autocomplete": "^6.3.2", - "@codemirror/language": "^6.8.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.2.1", - "@lezer/python": "^1.1.4" - } - }, - "node_modules/@codemirror/lang-rust": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-6.0.1.tgz", - "integrity": "sha512-344EMWFBzWArHWdZn/NcgkwMvZIWUR1GEBdwG8FEp++6o6vT6KL9V7vGs2ONsKxxFUPXKI0SPcWhyYyl2zPYxQ==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@lezer/rust": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-sass": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-sass/-/lang-sass-6.0.2.tgz", - "integrity": "sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==", - "dependencies": { - "@codemirror/lang-css": "^6.2.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.2", - "@lezer/sass": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-sql": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.7.1.tgz", - "integrity": "sha512-flQa7zemrLKk0TIrOJnpeyH/b29BcVybtsTeZMgAo40O6kGbrnUSCgwI3TF5iJY3O9VXJKKCA+i0CBVvDfr88w==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-vue": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@codemirror/lang-vue/-/lang-vue-0.1.3.tgz", - "integrity": "sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==", - "dependencies": { - "@codemirror/lang-html": "^6.0.0", - "@codemirror/lang-javascript": "^6.1.2", - "@codemirror/language": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.3.1" - } - }, - "node_modules/@codemirror/lang-wast": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-wast/-/lang-wast-6.0.2.tgz", - "integrity": "sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-xml": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", - "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.4.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/xml": "^1.0.0" - } - }, - "node_modules/@codemirror/lang-yaml": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.1.tgz", - "integrity": "sha512-HV2NzbK9bbVnjWxwObuZh5FuPCowx51mEfoFT9y3y+M37fA3+pbxx4I7uePuygFzDsAmCTwQSc/kXh/flab4uw==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.2.0", - "@lezer/yaml": "^1.0.0" - } - }, - "node_modules/@codemirror/language": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.2.tgz", - "integrity": "sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.23.0", - "@lezer/common": "^1.1.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0", - "style-mod": "^4.0.0" - } - }, - "node_modules/@codemirror/language-data": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@codemirror/language-data/-/language-data-6.5.1.tgz", - "integrity": "sha512-0sWxeUSNlBr6OmkqybUTImADFUP0M3P0IiSde4nc24bz/6jIYzqYSgkOSLS+CBIoW1vU8Q9KUWXscBXeoMVC9w==", - "dependencies": { - "@codemirror/lang-angular": "^0.1.0", - "@codemirror/lang-cpp": "^6.0.0", - "@codemirror/lang-css": "^6.0.0", - "@codemirror/lang-go": "^6.0.0", - "@codemirror/lang-html": "^6.0.0", - "@codemirror/lang-java": "^6.0.0", - "@codemirror/lang-javascript": "^6.0.0", - "@codemirror/lang-json": "^6.0.0", - "@codemirror/lang-less": "^6.0.0", - "@codemirror/lang-liquid": "^6.0.0", - "@codemirror/lang-markdown": "^6.0.0", - "@codemirror/lang-php": "^6.0.0", - "@codemirror/lang-python": "^6.0.0", - "@codemirror/lang-rust": "^6.0.0", - "@codemirror/lang-sass": "^6.0.0", - "@codemirror/lang-sql": "^6.0.0", - "@codemirror/lang-vue": "^0.1.1", - "@codemirror/lang-wast": "^6.0.0", - "@codemirror/lang-xml": "^6.0.0", - "@codemirror/lang-yaml": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/legacy-modes": "^6.4.0" - } - }, - "node_modules/@codemirror/legacy-modes": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.4.1.tgz", - "integrity": "sha512-vdg3XY7OAs5uLDx2Iw+cGfnwtd7kM+Et/eMsqAGTfT/JKiVBQZXosTzjEbWAi/FrY6DcQIz8mQjBozFHZEUWQA==", - "dependencies": { - "@codemirror/language": "^6.0.0" - } - }, - "node_modules/@codemirror/lint": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.1.tgz", - "integrity": "sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, - "node_modules/@codemirror/search": { - "version": "6.5.6", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", - "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, - "node_modules/@codemirror/state": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", - "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==" - }, - "node_modules/@codemirror/theme-one-dark": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz", - "integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/highlight": "^1.0.0" - } - }, - "node_modules/@codemirror/view": { - "version": "6.33.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.33.0.tgz", - "integrity": "sha512-AroaR3BvnjRW8fiZBalAaK+ZzB5usGgI014YKElYZvQdNH5ZIidHlO+cyf/2rWzyBFRkvG6VhiXeAEbC53P2YQ==", - "dependencies": { - "@codemirror/state": "^6.4.0", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, - "node_modules/@ctrl/tinycolor": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", - "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" - }, - "node_modules/@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", - "dev": true, - "dependencies": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", - "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@formatjs/ecma402-abstract": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.0.0.tgz", - "integrity": "sha512-rRqXOqdFmk7RYvj4khklyqzcfQl9vEL/usogncBHRZfZBDOwMGuSRNFl02fu5KGHXdbinju+YXyuR+Nk8xlr/g==", - "dependencies": { - "@formatjs/intl-localematcher": "0.5.4", - "tslib": "^2.4.0" - } - }, - "node_modules/@formatjs/fast-memoize": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.0.tgz", - "integrity": "sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@formatjs/icu-messageformat-parser": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.8.tgz", - "integrity": "sha512-nBZJYmhpcSX0WeJ5SDYUkZ42AgR3xiyhNCsQweFx3cz/ULJjym8bHAzWKvG5e2+1XO98dBYC0fWeeAECAVSwLA==", - "dependencies": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/icu-skeleton-parser": "1.8.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@formatjs/icu-skeleton-parser": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.2.tgz", - "integrity": "sha512-k4ERKgw7aKGWJZgTarIcNEmvyTVD9FYh0mTrrBMHZ1b8hUu6iOJ4SzsZlo3UNAvHYa+PnvntIwRPt1/vy4nA9Q==", - "dependencies": { - "@formatjs/ecma402-abstract": "2.0.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@formatjs/intl": { - "version": "2.10.4", - "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.4.tgz", - "integrity": "sha512-56483O+HVcL0c7VucAS2tyH020mt9XTozZO67cwtGg0a7KWDukS/FzW3OnvaHmTHDuYsoPIzO+ZHVfU6fT/bJw==", - "dependencies": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/fast-memoize": "2.2.0", - "@formatjs/icu-messageformat-parser": "2.7.8", - "@formatjs/intl-displaynames": "6.6.8", - "@formatjs/intl-listformat": "7.5.7", - "intl-messageformat": "10.5.14", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "typescript": "^4.7 || 5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@formatjs/intl-displaynames": { - "version": "6.6.8", - "resolved": "https://registry.npmjs.org/@formatjs/intl-displaynames/-/intl-displaynames-6.6.8.tgz", - "integrity": "sha512-Lgx6n5KxN16B3Pb05z3NLEBQkGoXnGjkTBNCZI+Cn17YjHJ3fhCeEJJUqRlIZmJdmaXQhjcQVDp6WIiNeRYT5g==", - "dependencies": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/intl-localematcher": "0.5.4", - "tslib": "^2.4.0" - } - }, - "node_modules/@formatjs/intl-listformat": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-7.5.7.tgz", - "integrity": "sha512-MG2TSChQJQT9f7Rlv+eXwUFiG24mKSzmF144PLb8m8OixyXqn4+YWU+5wZracZGCgVTVmx8viCf7IH3QXoiB2g==", - "dependencies": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/intl-localematcher": "0.5.4", - "tslib": "^2.4.0" - } - }, - "node_modules/@formatjs/intl-localematcher": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.4.tgz", - "integrity": "sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", - "dev": true, - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@lezer/common": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", - "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==" - }, - "node_modules/@lezer/cpp": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.2.tgz", - "integrity": "sha512-macwKtyeUO0EW86r3xWQCzOV9/CF8imJLpJlPv3sDY57cPGeUZ8gXWOWNlJr52TVByMV3PayFQCA5SHEERDmVQ==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/css": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.8.tgz", - "integrity": "sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/go": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@lezer/go/-/go-1.0.0.tgz", - "integrity": "sha512-co9JfT3QqX1YkrMmourYw2Z8meGC50Ko4d54QEcQbEYpvdUvN4yb0NBZdn/9ertgvjsySxHsKzH3lbm3vqJ4Jw==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/highlight": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", - "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lezer/html": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz", - "integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/java": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.2.tgz", - "integrity": "sha512-3j8X70JvYf0BZt8iSRLXLkt0Ry1hVUgH6wT32yBxH/Xi55nW2VMhc1Az4SKwu4YGSmxCm1fsqDDcHTuFjC8pmg==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/javascript": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.17.tgz", - "integrity": "sha512-bYW4ctpyGK+JMumDApeUzuIezX01H76R1foD6LcRX224FWfyYit/HYxiPGDjXXe/wQWASjCvVGoukTH68+0HIA==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.1.3", - "@lezer/lr": "^1.3.0" - } - }, - "node_modules/@lezer/json": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.2.tgz", - "integrity": "sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/lezer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lezer/lezer/-/lezer-1.1.2.tgz", - "integrity": "sha512-O8yw3CxPhzYHB1hvwbdozjnAslhhR8A5BH7vfEMof0xk3p+/DFDfZkA9Tde6J+88WgtwaHy4Sy6ThZSkaI0Evw==", - "dependencies": { - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/lr": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", - "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lezer/markdown": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.3.0.tgz", - "integrity": "sha512-ErbEQ15eowmJUyT095e9NJc3BI9yZ894fjSDtHftD0InkfUBGgnKSU6dvan9jqsZuNHg2+ag/1oyDRxNsENupQ==", - "dependencies": { - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0" - } - }, - "node_modules/@lezer/php": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.2.tgz", - "integrity": "sha512-GN7BnqtGRpFyeoKSEqxvGvhJQiI4zkgmYnDk/JIyc7H7Ifc1tkPnUn/R2R8meH3h/aBf5rzjvU8ZQoyiNDtDrA==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.1.0" - } - }, - "node_modules/@lezer/python": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.14.tgz", - "integrity": "sha512-ykDOb2Ti24n76PJsSa4ZoDF0zH12BSw1LGfQXCYJhJyOGiFTfGaX0Du66Ze72R+u/P35U+O6I9m8TFXov1JzsA==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/rust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz", - "integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/sass": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@lezer/sass/-/sass-1.0.6.tgz", - "integrity": "sha512-w/RCO2dIzZH1To8p+xjs8cE+yfgGus8NZ/dXeWl/QzHyr+TeBs71qiE70KPImEwvTsmEjoWh0A5SxMzKd5BWBQ==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/xml": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.5.tgz", - "integrity": "sha512-VFouqOzmUWfIg+tfmpcdV33ewtK+NSwd4ngSe1aG7HFb4BN0ExyY1b8msp+ndFrnlG4V4iC8yXacjFtrwERnaw==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/yaml": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz", - "integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.4.0" - } - }, - "node_modules/@nextjournal/lang-clojure": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@nextjournal/lang-clojure/-/lang-clojure-1.0.0.tgz", - "integrity": "sha512-gOCV71XrYD0DhwGoPMWZmZ0r92/lIHsqQu9QWdpZYYBwiChNwMO4sbVMP7eTuAqffFB2BTtCSC+1skSH9d3bNg==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@nextjournal/lezer-clojure": "1.0.0" - } - }, - "node_modules/@nextjournal/lezer-clojure": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@nextjournal/lezer-clojure/-/lezer-clojure-1.0.0.tgz", - "integrity": "sha512-VZyuGu4zw5mkTOwQBTaGVNWmsOZAPw5ZRxu1/Knk/Xfs7EDBIogwIs5UXTYkuECX5ZQB8eOB+wKA2pc7VyqaZQ==", - "dependencies": { - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@rc-component/async-validator": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz", - "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", - "dependencies": { - "@babel/runtime": "^7.24.4" - }, - "engines": { - "node": ">=14.x" - } - }, - "node_modules/@rc-component/color-picker": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz", - "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", - "dependencies": { - "@ant-design/fast-color": "^2.0.6", - "@babel/runtime": "^7.23.6", - "classnames": "^2.2.6", - "rc-util": "^5.38.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/context": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", - "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "rc-util": "^5.27.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/mini-decimal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", - "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", - "dependencies": { - "@babel/runtime": "^7.18.0" - }, - "engines": { - "node": ">=8.x" - } - }, - "node_modules/@rc-component/mutate-observer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", - "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", - "dependencies": { - "@babel/runtime": "^7.18.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/portal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", - "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", - "dependencies": { - "@babel/runtime": "^7.18.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/qrcode": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.0.tgz", - "integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==", - "dependencies": { - "@babel/runtime": "^7.24.7", - "classnames": "^2.3.2", - "rc-util": "^5.38.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/tour": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.0.tgz", - "integrity": "sha512-h6hyILDwL+In9GAgRobwRWihLqqsD7Uft3fZGrJ7L4EiyCoxbnNYwzPXDfz7vNDhWeVyvAWQJj9fJCzpI4+b4g==", - "dependencies": { - "@babel/runtime": "^7.18.0", - "@rc-component/portal": "^1.0.0-9", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/trigger": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.1.tgz", - "integrity": "sha512-fuU11J8pOt6+U/tU6/CAv8wjCwGaNeRk9f5k8HQth7JBbJ6MMH62WhGycVW75VnXfBZgL/7kO+wbiO2Xc9U9sQ==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@rc-component/portal": "^1.1.0", - "classnames": "^2.3.2", - "rc-motion": "^2.0.0", - "rc-resize-observer": "^1.3.1", - "rc-util": "^5.38.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@remix-run/router": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.1.tgz", - "integrity": "sha512-S45oynt/WH19bHbIXjtli6QmwNYvaz+vtnubvNpNDvUOoA/OWh6j1OikIP3G+v5GHdxyC6EXoChG3HgYGEUfcg==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@replit/codemirror-lang-csharp": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-csharp/-/codemirror-lang-csharp-6.2.0.tgz", - "integrity": "sha512-6utbaWkoymhoAXj051mkRp+VIJlpwUgCX9Toevz3YatiZsz512fw3OVCedXQx+WcR0wb6zVHjChnuxqfCLtFVQ==", - "peerDependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@replit/codemirror-lang-nix": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-nix/-/codemirror-lang-nix-6.0.1.tgz", - "integrity": "sha512-lvzjoYn9nfJzBD5qdm3Ut6G3+Or2wEacYIDJ49h9+19WSChVnxv4ojf+rNmQ78ncuxIt/bfbMvDLMeMP0xze6g==", - "peerDependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@replit/codemirror-lang-solidity": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-solidity/-/codemirror-lang-solidity-6.0.2.tgz", - "integrity": "sha512-/dpTVH338KFV6SaDYYSadkB4bI/0B0QRF/bkt1XS3t3QtyR49mn6+2k0OUQhvt2ZSO7kt10J+OPilRAtgbmX0w==", - "dependencies": { - "@lezer/highlight": "^1.2.0" - }, - "peerDependencies": { - "@codemirror/language": "^6.0.0" - } - }, - "node_modules/@replit/codemirror-lang-svelte": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-svelte/-/codemirror-lang-svelte-6.0.0.tgz", - "integrity": "sha512-U2OqqgMM6jKelL0GNWbAmqlu1S078zZNoBqlJBW+retTc5M4Mha6/Y2cf4SVg6ddgloJvmcSpt4hHrVoM4ePRA==", - "peerDependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/lang-css": "^6.0.1", - "@codemirror/lang-html": "^6.2.0", - "@codemirror/lang-javascript": "^6.1.1", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0", - "@lezer/javascript": "^1.2.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.1.tgz", - "integrity": "sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.1.tgz", - "integrity": "sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.1.tgz", - "integrity": "sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.1.tgz", - "integrity": "sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.1.tgz", - "integrity": "sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.1.tgz", - "integrity": "sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.1.tgz", - "integrity": "sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.1.tgz", - "integrity": "sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.1.tgz", - "integrity": "sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.1.tgz", - "integrity": "sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.1.tgz", - "integrity": "sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.1.tgz", - "integrity": "sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.1.tgz", - "integrity": "sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.1.tgz", - "integrity": "sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.1.tgz", - "integrity": "sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.1.tgz", - "integrity": "sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@ts-morph/common": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.12.3.tgz", - "integrity": "sha512-4tUmeLyXJnJWvTFOKtcNJ1yh0a3SsTLi2MUoyj8iUNznFRN1ZquaNe7Oukqrnki2FzZkm0J9adCNLDZxUzvj+w==", - "dev": true, - "dependencies": { - "fast-glob": "^3.2.7", - "minimatch": "^3.0.4", - "mkdirp": "^1.0.4", - "path-browserify": "^1.0.1" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", - "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/hast": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", - "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/@types/hast/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", - "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, - "node_modules/@types/js-cookie": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", - "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", - "dev": true - }, - "node_modules/@types/katex": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", - "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==" - }, - "node_modules/@types/lodash": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==" - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/ms": { - "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" - }, - "node_modules/@types/node": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", - "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", - "dev": true, - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "dev": true - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" - }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" - }, - "node_modules/@types/react": { - "version": "18.3.4", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz", - "integrity": "sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-copy-to-clipboard": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.7.tgz", - "integrity": "sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-syntax-highlighter": { - "version": "15.5.13", - "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz", - "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz", - "integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/type-utils": "8.3.0", - "@typescript-eslint/utils": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz", - "integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", - "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz", - "integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/utils": "8.3.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", - "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", - "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", - "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", - "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.3.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@uiw/codemirror-extensions-basic-setup": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.23.0.tgz", - "integrity": "sha512-+k5nkRpUWGaHr1JWT8jcKsVewlXw5qBgSopm9LW8fZ6KnSNZBycz8kHxh0+WSvckmXEESGptkIsb7dlkmJT/hQ==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/commands": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/search": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0" - }, - "funding": { - "url": "https://jaywcjlove.github.io/#/sponsor" - }, - "peerDependencies": { - "@codemirror/autocomplete": ">=6.0.0", - "@codemirror/commands": ">=6.0.0", - "@codemirror/language": ">=6.0.0", - "@codemirror/lint": ">=6.0.0", - "@codemirror/search": ">=6.0.0", - "@codemirror/state": ">=6.0.0", - "@codemirror/view": ">=6.0.0" - } - }, - "node_modules/@uiw/codemirror-extensions-langs": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-langs/-/codemirror-extensions-langs-4.23.0.tgz", - "integrity": "sha512-WUJnTgS3CIV5TZPjwYO+mvRqxfvSSSKC2a+Wm5Uk3uFoZZ7O/GKi4bKKLsIHQkCwNnd9CHJzwN2dpIVrK1AmLA==", - "dependencies": { - "@codemirror/lang-angular": "^0.1.0", - "@codemirror/lang-cpp": "^6.0.0", - "@codemirror/lang-css": "^6.2.0", - "@codemirror/lang-html": "^6.4.0", - "@codemirror/lang-java": "^6.0.0", - "@codemirror/lang-javascript": "^6.1.0", - "@codemirror/lang-json": "^6.0.0", - "@codemirror/lang-less": "^6.0.1", - "@codemirror/lang-lezer": "^6.0.0", - "@codemirror/lang-liquid": "^6.0.1", - "@codemirror/lang-markdown": "^6.1.0", - "@codemirror/lang-php": "^6.0.0", - "@codemirror/lang-python": "^6.1.0", - "@codemirror/lang-rust": "^6.0.0", - "@codemirror/lang-sass": "^6.0.1", - "@codemirror/lang-sql": "^6.4.0", - "@codemirror/lang-vue": "^0.1.1", - "@codemirror/lang-wast": "^6.0.0", - "@codemirror/lang-xml": "^6.0.0", - "@codemirror/language-data": ">=6.0.0", - "@codemirror/legacy-modes": ">=6.0.0", - "@nextjournal/lang-clojure": "^1.0.0", - "@replit/codemirror-lang-csharp": "^6.1.0", - "@replit/codemirror-lang-nix": "^6.0.1", - "@replit/codemirror-lang-solidity": "^6.0.1", - "@replit/codemirror-lang-svelte": "^6.0.0", - "codemirror-lang-mermaid": "^0.5.0" - }, - "funding": { - "url": "https://jaywcjlove.github.io/#/sponsor" - }, - "peerDependencies": { - "@codemirror/language-data": ">=6.0.0", - "@codemirror/legacy-modes": ">=6.0.0" - } - }, - "node_modules/@uiw/react-codemirror": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.23.0.tgz", - "integrity": "sha512-MnqTXfgeLA3fsUUQjqjJgemEuNyoGALgsExVm0NQAllAAi1wfj+IoKFeK+h3XXMlTFRCFYOUh4AHDv0YXJLsOg==", - "dependencies": { - "@babel/runtime": "^7.18.6", - "@codemirror/commands": "^6.1.0", - "@codemirror/state": "^6.1.1", - "@codemirror/theme-one-dark": "^6.0.0", - "@uiw/codemirror-extensions-basic-setup": "4.23.0", - "codemirror": "^6.0.0" - }, - "funding": { - "url": "https://jaywcjlove.github.io/#/sponsor" - }, - "peerDependencies": { - "@babel/runtime": ">=7.11.0", - "@codemirror/state": ">=6.0.0", - "@codemirror/theme-one-dark": ">=6.0.0", - "@codemirror/view": ">=6.0.0", - "codemirror": ">=6.0.0", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", - "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.5", - "@babel/plugin-transform-react-jsx-self": "^7.24.5", - "@babel/plugin-transform-react-jsx-source": "^7.24.1", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0" - } - }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ahooks": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/ahooks/-/ahooks-3.8.1.tgz", - "integrity": "sha512-JoP9+/RWO7MnI/uSKdvQ8WB10Y3oo1PjLv+4Sv4Vpm19Z86VUMdXh+RhWvMGxZZs06sq2p0xVtFk8Oh5ZObsoA==", - "dependencies": { - "@babel/runtime": "^7.21.0", - "dayjs": "^1.9.1", - "intersection-observer": "^0.12.0", - "js-cookie": "^3.0.5", - "lodash": "^4.17.21", - "react-fast-compare": "^3.2.2", - "resize-observer-polyfill": "^1.5.1", - "screenfull": "^5.0.0", - "tslib": "^2.4.1" - }, - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/antd": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/antd/-/antd-5.20.3.tgz", - "integrity": "sha512-v2s5LJlhuccIKLT17ESXQDkiQJdPK4jXg4x2pmSSRlrKXAxfftn8Zhd/7pdF3qR3OkwheQpSRjynrNZKp9Tgkg==", - "dependencies": { - "@ant-design/colors": "^7.1.0", - "@ant-design/cssinjs": "^1.21.0", - "@ant-design/cssinjs-utils": "^1.0.3", - "@ant-design/icons": "^5.4.0", - "@ant-design/react-slick": "~1.1.2", - "@babel/runtime": "^7.24.8", - "@ctrl/tinycolor": "^3.6.1", - "@rc-component/color-picker": "~2.0.1", - "@rc-component/mutate-observer": "^1.1.0", - "@rc-component/qrcode": "~1.0.0", - "@rc-component/tour": "~1.15.0", - "@rc-component/trigger": "^2.2.1", - "classnames": "^2.5.1", - "copy-to-clipboard": "^3.3.3", - "dayjs": "^1.11.11", - "rc-cascader": "~3.27.0", - "rc-checkbox": "~3.3.0", - "rc-collapse": "~3.7.3", - "rc-dialog": "~9.5.2", - "rc-drawer": "~7.2.0", - "rc-dropdown": "~4.2.0", - "rc-field-form": "~2.4.0", - "rc-image": "~7.9.0", - "rc-input": "~1.6.3", - "rc-input-number": "~9.2.0", - "rc-mentions": "~2.15.0", - "rc-menu": "~9.14.1", - "rc-motion": "^2.9.2", - "rc-notification": "~5.6.0", - "rc-pagination": "~4.2.0", - "rc-picker": "~4.6.13", - "rc-progress": "~4.0.0", - "rc-rate": "~2.13.0", - "rc-resize-observer": "^1.4.0", - "rc-segmented": "~2.3.0", - "rc-select": "~14.15.1", - "rc-slider": "~11.1.5", - "rc-steps": "~6.0.1", - "rc-switch": "~4.1.0", - "rc-table": "~7.45.7", - "rc-tabs": "~15.1.1", - "rc-textarea": "~1.8.1", - "rc-tooltip": "~6.2.0", - "rc-tree": "~5.8.8", - "rc-tree-select": "~5.22.1", - "rc-upload": "~4.7.0", - "rc-util": "^5.43.0", - "scroll-into-view-if-needed": "^3.1.0", - "throttle-debounce": "^5.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ant-design" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-tree-filter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", - "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/axios": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", - "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-builder": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", - "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", - "dev": true - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001653", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz", - "integrity": "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/classnames": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" - }, - "node_modules/code-block-writer": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.3.tgz", - "integrity": "sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==", - "dev": true - }, - "node_modules/codemirror": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", - "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/commands": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/search": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0" - } - }, - "node_modules/codemirror-lang-mermaid": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/codemirror-lang-mermaid/-/codemirror-lang-mermaid-0.5.0.tgz", - "integrity": "sha512-Taw/2gPCyNArQJCxIP/HSUif+3zrvD+6Ugt7KJZ2dUKou/8r3ZhcfG8krNTZfV2iu8AuGnymKuo7bLPFyqsh/A==", - "dependencies": { - "@codemirror/language": "^6.9.0", - "@lezer/highlight": "^1.1.6", - "@lezer/lr": "^1.3.10" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/compute-scroll-into-view": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz", - "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/copy-to-clipboard": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", - "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", - "dependencies": { - "toggle-selection": "^1.0.6" - } - }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cosmiconfig/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/crelt": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", - "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" - }, - "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decode-named-character-reference": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", - "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", - "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.9.1", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.1.0-rc-fb9a90fa48-20240614", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0-rc-fb9a90fa48-20240614.tgz", - "integrity": "sha512-xsiRwaDNF5wWNC4ZHLut+x/YcAxksUd9Rizt7LaEn3bV8VyYRpXnRJQlLOfYaVy9esk4DFP4zPPnoNVjq5Gc0w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.11.tgz", - "integrity": "sha512-wrAKxMbVr8qhXTtIKfXqAn5SAtRZt0aXxe5P23Fh4pUAdC6XEsybGLB8P0PI4j1yYqOgUEUlzKAGDfo7rJOjcw==", - "dev": true, - "peerDependencies": { - "eslint": ">=7" - } - }, - "node_modules/eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", - "dev": true, - "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fault": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", - "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", - "dependencies": { - "format": "^0.2.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/format": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", - "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/globals": { - "version": "15.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", - "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hast-util-from-dom": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.0.tgz", - "integrity": "sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==", - "dependencies": { - "@types/hast": "^3.0.0", - "hastscript": "^8.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-dom/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/hast-util-from-dom/node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-from-dom/node_modules/hast-util-parse-selector": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-dom/node_modules/hastscript": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", - "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-dom/node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-from-dom/node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-from-html": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.2.tgz", - "integrity": "sha512-HwOHwxdt2zC5KQ/CNoybBntRook2zJvfZE/u5/Ap7aLPe22bDqen7KwGkOqOyzL5zIqKwiYX/OTtE0FWgr6XXA==", - "dependencies": { - "@types/hast": "^3.0.0", - "devlop": "^1.1.0", - "hast-util-from-parse5": "^8.0.0", - "parse5": "^7.0.0", - "vfile": "^6.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-html-isomorphic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", - "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-from-dom": "^5.0.0", - "hast-util-from-html": "^2.0.0", - "unist-util-remove-position": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-html-isomorphic/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/hast-util-from-html/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/hast-util-from-parse5": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", - "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "hastscript": "^8.0.0", - "property-information": "^6.0.0", - "vfile": "^6.0.0", - "vfile-location": "^5.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/hast-util-from-parse5/node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-from-parse5/node_modules/hast-util-parse-selector": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5/node_modules/hastscript": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", - "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5/node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-from-parse5/node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-is-element": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", - "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-is-element/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.4.tgz", - "integrity": "sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-from-parse5": "^8.0.0", - "hast-util-to-parse5": "^8.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "parse5": "^7.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", - "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-object": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-jsx-runtime/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/hast-util-to-jsx-runtime/node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-to-jsx-runtime/node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-to-jsx-runtime/node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-to-parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", - "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-parse5/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/hast-util-to-parse5/node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-to-parse5/node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-to-parse5/node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-to-text": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", - "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "hast-util-is-element": "^3.0.0", - "unist-util-find-after": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-text/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/hastscript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", - "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "engines": { - "node": "*" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/html-url-attributes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.0.tgz", - "integrity": "sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/immutable": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inline-style-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", - "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" - }, - "node_modules/intersection-observer": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.2.tgz", - "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==" - }, - "node_modules/intl-messageformat": { - "version": "10.5.14", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz", - "integrity": "sha512-IjC6sI0X7YRjjyVH9aUgdftcmZK7WXdHeil4KwbjDnRWjnVitKpAx3rr6t6di1joFp5188VqKcobOPA6mCLG/w==", - "dependencies": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/fast-memoize": "2.2.0", - "@formatjs/icu-messageformat-parser": "2.7.8", - "tslib": "^2.4.0" - } - }, - "node_modules/is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dev": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "dev": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", - "engines": { - "node": ">=14" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json2mq": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", - "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", - "dependencies": { - "string-convert": "^0.2.0" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/katex": { - "version": "0.16.11", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz", - "integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==", - "funding": [ - "https://opencollective.com/katex", - "https://github.com/sponsors/katex" - ], - "dependencies": { - "commander": "^8.3.0" - }, - "bin": { - "katex": "cli.js" - } - }, - "node_modules/katex/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lowlight": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", - "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", - "dependencies": { - "fault": "^1.0.0", - "highlight.js": "~10.7.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/markdown-table": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", - "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-find-and-replace": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", - "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", - "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", - "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", - "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-math": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", - "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "longest-streak": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.1.0", - "unist-util-remove-position": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-math/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", - "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", - "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", - "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", - "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", - "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", - "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-math": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", - "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", - "dependencies": { - "@types/katex": "^0.16.0", - "devlop": "^1.0.0", - "katex": "^0.16.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", - "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", - "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", - "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", - "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", - "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", - "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", - "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", - "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", - "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", - "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", - "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", - "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", - "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", - "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-entities/node_modules/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/property-information": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", - "dependencies": { - "xtend": "^4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/rc-cascader": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.27.0.tgz", - "integrity": "sha512-z5uq8VvQadFUBiuZJ7YF5UAUGNkZtdEtcEYiIA94N/Kc2MIKr6lEbN5HyVddvYSgwWlKqnL6pH5bFXFuIK3MNg==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "array-tree-filter": "^2.1.0", - "classnames": "^2.3.1", - "rc-select": "~14.15.0", - "rc-tree": "~5.8.1", - "rc-util": "^5.37.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-checkbox": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.3.0.tgz", - "integrity": "sha512-Ih3ZaAcoAiFKJjifzwsGiT/f/quIkxJoklW4yKGho14Olulwn8gN7hOBve0/WGDg5o/l/5mL0w7ff7/YGvefVw==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.3.2", - "rc-util": "^5.25.2" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-collapse": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.7.3.tgz", - "integrity": "sha512-60FJcdTRn0X5sELF18TANwtVi7FtModq649H11mYF1jh83DniMoM4MqY627sEKRCTm4+WXfGDcB7hY5oW6xhyw==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^2.3.4", - "rc-util": "^5.27.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-dialog": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.5.2.tgz", - "integrity": "sha512-qVUjc8JukG+j/pNaHVSRa2GO2/KbV2thm7yO4hepQ902eGdYK913sGkwg/fh9yhKYV1ql3BKIN2xnud3rEXAPw==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/portal": "^1.0.0-8", - "classnames": "^2.2.6", - "rc-motion": "^2.3.0", - "rc-util": "^5.21.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-drawer": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.2.0.tgz", - "integrity": "sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@rc-component/portal": "^1.1.1", - "classnames": "^2.2.6", - "rc-motion": "^2.6.1", - "rc-util": "^5.38.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-dropdown": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.0.tgz", - "integrity": "sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.2.6", - "rc-util": "^5.17.0" - }, - "peerDependencies": { - "react": ">=16.11.0", - "react-dom": ">=16.11.0" - } - }, - "node_modules/rc-field-form": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.4.0.tgz", - "integrity": "sha512-XZ/lF9iqf9HXApIHQHqzJK5v2w4mkUMsVqAzOyWVzoiwwXEavY6Tpuw7HavgzIoD+huVff4JghSGcgEfX6eycg==", - "dependencies": { - "@babel/runtime": "^7.18.0", - "@rc-component/async-validator": "^5.0.3", - "rc-util": "^5.32.2" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-image": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.9.0.tgz", - "integrity": "sha512-l4zqO5E0quuLMCtdKfBgj4Suv8tIS011F5k1zBBlK25iMjjiNHxA0VeTzGFtUZERSA45gvpXDg8/P6qNLjR25g==", - "dependencies": { - "@babel/runtime": "^7.11.2", - "@rc-component/portal": "^1.0.2", - "classnames": "^2.2.6", - "rc-dialog": "~9.5.2", - "rc-motion": "^2.6.2", - "rc-util": "^5.34.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-input": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.6.3.tgz", - "integrity": "sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==", - "dependencies": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-util": "^5.18.1" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/rc-input-number": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.2.0.tgz", - "integrity": "sha512-5XZFhBCV5f9UQ62AZ2hFbEY8iZT/dm23Q1kAg0H8EvOgD3UDbYYJAayoVIkM3lQaCqYAW5gV0yV3vjw1XtzWHg==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/mini-decimal": "^1.0.1", - "classnames": "^2.2.5", - "rc-input": "~1.6.0", - "rc-util": "^5.40.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-mentions": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.15.0.tgz", - "integrity": "sha512-f5v5i7VdqvBDXbphoqcQWmXDif2Msd2arritVoWybrVDuHE6nQ7XCYsybHbV//WylooK52BFDouFvyaRDtXZEw==", - "dependencies": { - "@babel/runtime": "^7.22.5", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.2.6", - "rc-input": "~1.6.0", - "rc-menu": "~9.14.0", - "rc-textarea": "~1.8.0", - "rc-util": "^5.34.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-menu": { - "version": "9.14.1", - "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.14.1.tgz", - "integrity": "sha512-5wlRb3M8S4yGlWhSoEYJ7ZVRElyScdcpUHxgiLxkeig1tEdyKrnED3B2fhpN0Rrpdp9jyhnmZR/Lwq2fH5VvDQ==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/trigger": "^2.0.0", - "classnames": "2.x", - "rc-motion": "^2.4.3", - "rc-overflow": "^1.3.1", - "rc-util": "^5.27.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-motion": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.2.tgz", - "integrity": "sha512-fUAhHKLDdkAXIDLH0GYwof3raS58dtNUmzLF2MeiR8o6n4thNpSDQhOqQzWE4WfFZDCi9VEN8n7tiB7czREcyw==", - "dependencies": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-util": "^5.43.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-notification": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.0.tgz", - "integrity": "sha512-TGQW5T7waOxLwgJG7fXcw8l7AQiFOjaZ7ISF5PrU526nunHRNcTMuzKihQHaF4E/h/KfOCDk3Mv8eqzbu2e28w==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^2.9.0", - "rc-util": "^5.20.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-overflow": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.2.tgz", - "integrity": "sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==", - "dependencies": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.37.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-pagination": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-4.2.0.tgz", - "integrity": "sha512-V6qeANJsT6tmOcZ4XiUmj8JXjRLbkusuufpuoBw2GiAn94fIixYjFLmbruD1Sbhn8fPLDnWawPp4CN37zQorvw==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.3.2", - "rc-util": "^5.38.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-picker": { - "version": "4.6.14", - "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.6.14.tgz", - "integrity": "sha512-7DuTfUFdkxmsNpWQ0TWv6FPGna5e6KKC4nxtx3x9xhumLz7jb3fhlDdWQvqEL6tpt9DOb1+N5j+wB+lDOSS9kg==", - "dependencies": { - "@babel/runtime": "^7.24.7", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.2.1", - "rc-overflow": "^1.3.2", - "rc-resize-observer": "^1.4.0", - "rc-util": "^5.43.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "date-fns": ">= 2.x", - "dayjs": ">= 1.x", - "luxon": ">= 3.x", - "moment": ">= 2.x", - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - }, - "peerDependenciesMeta": { - "date-fns": { - "optional": true - }, - "dayjs": { - "optional": true - }, - "luxon": { - "optional": true - }, - "moment": { - "optional": true - } - } - }, - "node_modules/rc-progress": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", - "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.6", - "rc-util": "^5.16.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-rate": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.0.tgz", - "integrity": "sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.5", - "rc-util": "^5.0.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-resize-observer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz", - "integrity": "sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==", - "dependencies": { - "@babel/runtime": "^7.20.7", - "classnames": "^2.2.1", - "rc-util": "^5.38.0", - "resize-observer-polyfill": "^1.5.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-segmented": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.3.0.tgz", - "integrity": "sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg==", - "dependencies": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-motion": "^2.4.4", - "rc-util": "^5.17.0" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/rc-select": { - "version": "14.15.1", - "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.15.1.tgz", - "integrity": "sha512-mGvuwW1RMm1NCSI8ZUoRoLRK51R2Nb+QJnmiAvbDRcjh2//ulCkxeV6ZRFTECPpE1t2DPfyqZMPw90SVJzQ7wQ==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/trigger": "^2.1.1", - "classnames": "2.x", - "rc-motion": "^2.0.1", - "rc-overflow": "^1.3.1", - "rc-util": "^5.16.1", - "rc-virtual-list": "^3.5.2" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/rc-slider": { - "version": "11.1.5", - "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.5.tgz", - "integrity": "sha512-b77H5PbjMKsvkYXAYIkn50QuFX6ICQmCTibDinI9q+BHx65/TV4TeU25+oadhSRzykxs0/vBWeKBwRyySOeWlg==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.5", - "rc-util": "^5.36.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-steps": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", - "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", - "dependencies": { - "@babel/runtime": "^7.16.7", - "classnames": "^2.2.3", - "rc-util": "^5.16.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-switch": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", - "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", - "dependencies": { - "@babel/runtime": "^7.21.0", - "classnames": "^2.2.1", - "rc-util": "^5.30.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-table": { - "version": "7.45.7", - "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.45.7.tgz", - "integrity": "sha512-wi9LetBL1t1csxyGkMB2p3mCiMt+NDexMlPbXHvQFmBBAsMxrgNSAPwUci2zDLUq9m8QdWc1Nh8suvrpy9mXrg==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/context": "^1.4.0", - "classnames": "^2.2.5", - "rc-resize-observer": "^1.1.0", - "rc-util": "^5.37.0", - "rc-virtual-list": "^3.14.2" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-tabs": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.1.1.tgz", - "integrity": "sha512-Tc7bJvpEdkWIVCUL7yQrMNBJY3j44NcyWS48jF/UKMXuUlzaXK+Z/pEL5LjGcTadtPvVmNqA40yv7hmr+tCOAw==", - "dependencies": { - "@babel/runtime": "^7.11.2", - "classnames": "2.x", - "rc-dropdown": "~4.2.0", - "rc-menu": "~9.14.0", - "rc-motion": "^2.6.2", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.34.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-textarea": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.8.1.tgz", - "integrity": "sha512-bm36N2ZqwZAP60ZQg2OY9mPdqWC+m6UTjHc+CqEZOxb3Ia29BGHazY/s5bI8M4113CkqTzhtFUDNA078ZiOx3Q==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.1", - "rc-input": "~1.6.0", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.27.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-tooltip": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.2.0.tgz", - "integrity": "sha512-iS/3iOAvtDh9GIx1ulY7EFUXUtktFccNLsARo3NPgLf0QW9oT0w3dA9cYWlhqAKmD+uriEwdWz1kH0Qs4zk2Aw==", - "dependencies": { - "@babel/runtime": "^7.11.2", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.3.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-tree": { - "version": "5.8.8", - "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.8.8.tgz", - "integrity": "sha512-S+mCMWo91m5AJqjz3PdzKilGgbFm7fFJRFiTDOcoRbD7UfMOPnerXwMworiga0O2XIo383UoWuEfeHs1WOltag==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^2.0.1", - "rc-util": "^5.16.1", - "rc-virtual-list": "^3.5.1" - }, - "engines": { - "node": ">=10.x" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/rc-tree-select": { - "version": "5.22.2", - "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.22.2.tgz", - "integrity": "sha512-WHmWCck4+8mf4/KFTjw70AlnoNPkX4C1TOIzzwxfZ7w8hcNO4bzggoeO2Q3fAedjZteN5I3t2dT0BCZAnHedlQ==", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-select": "~14.15.0", - "rc-tree": "~5.8.1", - "rc-util": "^5.16.1" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/rc-upload": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.7.0.tgz", - "integrity": "sha512-eUwxYNHlsYe5vYhKFAUGrQG95JrnPzY+BmPi1Daq39fWNl/eOc7v4UODuWrVp2LFkQBuV3cMCG/I68iub6oBrg==", - "dependencies": { - "@babel/runtime": "^7.18.3", - "classnames": "^2.2.5", - "rc-util": "^5.2.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-util": { - "version": "5.43.0", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.43.0.tgz", - "integrity": "sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==", - "dependencies": { - "@babel/runtime": "^7.18.3", - "react-is": "^18.2.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-virtual-list": { - "version": "3.14.5", - "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.14.5.tgz", - "integrity": "sha512-ZMOnkCLv2wUN8Jz7yI4XiSLa9THlYvf00LuMhb1JlsQCewuU7ydPuHw1rGVPhe9VZYl/5UqODtNd7QKJ2DMGfg==", - "dependencies": { - "@babel/runtime": "^7.20.0", - "classnames": "^2.2.6", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.36.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-copy-to-clipboard": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", - "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", - "dependencies": { - "copy-to-clipboard": "^3.3.1", - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "react": "^15.3.0 || 16 || 17 || 18" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-fast-compare": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" - }, - "node_modules/react-intl": { - "version": "6.6.8", - "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.8.tgz", - "integrity": "sha512-M0pkhzcgV31h++2901BiRXWl69hp2zPyLxRrSwRjd1ErXbNoubz/f4M6DrRTd4OiSUrT4ajRQzrmtS5plG4FtA==", - "dependencies": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/icu-messageformat-parser": "2.7.8", - "@formatjs/intl": "2.10.4", - "@formatjs/intl-displaynames": "6.6.8", - "@formatjs/intl-listformat": "7.5.7", - "@types/hoist-non-react-statics": "^3.3.1", - "@types/react": "16 || 17 || 18", - "hoist-non-react-statics": "^3.3.2", - "intl-messageformat": "10.5.14", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "react": "^16.6.0 || 17 || 18", - "typescript": "^4.7 || 5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, - "node_modules/react-markdown": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz", - "integrity": "sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==", - "dependencies": { - "@types/hast": "^3.0.0", - "devlop": "^1.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "html-url-attributes": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "unified": "^11.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=18", - "react": ">=18" - } - }, - "node_modules/react-markdown/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-router": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.1.tgz", - "integrity": "sha512-kIwJveZNwp7teQRI5QmwWo39A5bXRyqpH0COKKmPnyD2vBvDwgFXSqDUYtt1h+FEyfnE8eXr7oe0MxRzVwCcvQ==", - "dependencies": { - "@remix-run/router": "1.19.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.1.tgz", - "integrity": "sha512-veut7m41S1fLql4pLhxeSW3jlqs+4MtjRLj0xvuCEXsxusJCbs6I8yn9BxzzDX2XDgafrccY6hwjmd/bL54tFw==", - "dependencies": { - "@remix-run/router": "1.19.1", - "react-router": "6.26.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "node_modules/react-syntax-highlighter": { - "version": "15.5.0", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz", - "integrity": "sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "highlight.js": "^10.4.1", - "lowlight": "^1.17.0", - "prismjs": "^1.27.0", - "refractor": "^3.6.0" - }, - "peerDependencies": { - "react": ">= 0.14.0" - } - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/refractor": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", - "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", - "dependencies": { - "hastscript": "^6.0.0", - "parse-entities": "^2.0.0", - "prismjs": "~1.27.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/prismjs": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", - "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "node_modules/rehype-katex": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz", - "integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/katex": "^0.16.0", - "hast-util-from-html-isomorphic": "^2.0.0", - "hast-util-to-text": "^4.0.0", - "katex": "^0.16.0", - "unist-util-visit-parents": "^6.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-katex/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/rehype-raw": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", - "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-raw": "^9.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-raw/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/remark-gfm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", - "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-gfm": "^3.0.0", - "micromark-extension-gfm": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-math": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", - "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-math": "^3.0.0", - "micromark-extension-math": "^3.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-rehype": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", - "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-rehype/node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/resize-observer-polyfill": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", - "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.1.tgz", - "integrity": "sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.1", - "@rollup/rollup-android-arm64": "4.21.1", - "@rollup/rollup-darwin-arm64": "4.21.1", - "@rollup/rollup-darwin-x64": "4.21.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.1", - "@rollup/rollup-linux-arm-musleabihf": "4.21.1", - "@rollup/rollup-linux-arm64-gnu": "4.21.1", - "@rollup/rollup-linux-arm64-musl": "4.21.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.1", - "@rollup/rollup-linux-riscv64-gnu": "4.21.1", - "@rollup/rollup-linux-s390x-gnu": "4.21.1", - "@rollup/rollup-linux-x64-gnu": "4.21.1", - "@rollup/rollup-linux-x64-musl": "4.21.1", - "@rollup/rollup-win32-arm64-msvc": "4.21.1", - "@rollup/rollup-win32-ia32-msvc": "4.21.1", - "@rollup/rollup-win32-x64-msvc": "4.21.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/sass-embedded": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.77.8.tgz", - "integrity": "sha512-WGXA6jcaoBo5Uhw0HX/s6z/sl3zyYQ7ZOnLOJzqwpctFcFmU4L07zn51e2VSkXXFpQZFAdMZNqOGz/7h/fvcRA==", - "dev": true, - "dependencies": { - "@bufbuild/protobuf": "^1.0.0", - "buffer-builder": "^0.2.0", - "immutable": "^4.0.0", - "rxjs": "^7.4.0", - "supports-color": "^8.1.1", - "varint": "^6.0.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "optionalDependencies": { - "sass-embedded-android-arm": "1.77.8", - "sass-embedded-android-arm64": "1.77.8", - "sass-embedded-android-ia32": "1.77.8", - "sass-embedded-android-x64": "1.77.8", - "sass-embedded-darwin-arm64": "1.77.8", - "sass-embedded-darwin-x64": "1.77.8", - "sass-embedded-linux-arm": "1.77.8", - "sass-embedded-linux-arm64": "1.77.8", - "sass-embedded-linux-ia32": "1.77.8", - "sass-embedded-linux-musl-arm": "1.77.8", - "sass-embedded-linux-musl-arm64": "1.77.8", - "sass-embedded-linux-musl-ia32": "1.77.8", - "sass-embedded-linux-musl-x64": "1.77.8", - "sass-embedded-linux-x64": "1.77.8", - "sass-embedded-win32-arm64": "1.77.8", - "sass-embedded-win32-ia32": "1.77.8", - "sass-embedded-win32-x64": "1.77.8" - } - }, - "node_modules/sass-embedded-android-arm": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.77.8.tgz", - "integrity": "sha512-GpGL7xZ7V1XpFbnflib/NWbM0euRzineK0iwoo31/ntWKAXGj03iHhGzkSiOwWSFcXgsJJi3eRA5BTmBvK5Q+w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "bin": { - "sass": "dart-sass/sass" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-android-arm64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.77.8.tgz", - "integrity": "sha512-EmWHLbEx0Zo/f/lTFzMeH2Du+/I4RmSRlEnERSUKQWVp3aBSO04QDvdxfFezgQ+2Yt/ub9WMqBpma9P/8MPsLg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "bin": { - "sass": "dart-sass/sass" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-android-ia32": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.77.8.tgz", - "integrity": "sha512-+GjfJ3lDezPi4dUUyjQBxlNKXNa+XVWsExtGvVNkv1uKyaOxULJhubVo2G6QTJJU0esJdfeXf5Ca5/J0ph7+7w==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "bin": { - "sass": "dart-sass/sass" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-android-x64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.77.8.tgz", - "integrity": "sha512-YZbFDzGe5NhaMCygShqkeCWtzjhkWxGVunc7ULR97wmxYPQLPeVyx7XFQZc84Aj0lKAJBJS4qRZeqphMqZEJsQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "bin": { - "sass": "dart-sass/sass" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-darwin-arm64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.77.8.tgz", - "integrity": "sha512-aifgeVRNE+i43toIkDFFJc/aPLMo0PJ5s5hKb52U+oNdiJE36n65n2L8F/8z3zZRvCa6eYtFY2b7f1QXR3B0LA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "bin": { - "sass": "dart-sass/sass" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-darwin-x64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.77.8.tgz", - "integrity": "sha512-/VWZQtcWIOek60Zj6Sxk6HebXA1Qyyt3sD8o5qwbTgZnKitB1iEBuNunyGoAgMNeUz2PRd6rVki6hvbas9hQ6w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "bin": { - "sass": "dart-sass/sass" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-arm": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.77.8.tgz", - "integrity": "sha512-2edZMB6jf0whx3T0zlgH+p131kOEmWp+I4wnKj7ZMUeokiY4Up05d10hSvb0Q63lOrSjFAWu6P5/pcYUUx8arQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "bin": { - "sass": "dart-sass/sass" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-arm64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.77.8.tgz", - "integrity": "sha512-6iIOIZtBFa2YfMsHqOb3qake3C9d/zlKxjooKKnTSo+6g6z+CLTzMXe1bOfayb7yxeenElmFoK1k54kWD/40+g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "bin": { - "sass": "dart-sass/sass" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-ia32": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.77.8.tgz", - "integrity": "sha512-63GsFFHWN5yRLTWiSef32TM/XmjhCBx1DFhoqxmj+Yc6L9Z1h0lDHjjwdG6Sp5XTz5EmsaFKjpDgnQTP9hJX3Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "bin": { - "sass": "dart-sass/sass" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-arm": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.77.8.tgz", - "integrity": "sha512-nFkhSl3uu9btubm+JBW7uRglNVJ8W8dGfzVqh3fyQJKS1oyBC3vT3VOtfbT9YivXk28wXscSHpqXZwY7bUuopA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-arm64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.77.8.tgz", - "integrity": "sha512-j8cgQxNWecYK+aH8ESFsyam/Q6G+9gg8eJegiRVpA9x8yk3ykfHC7UdQWwUcF22ZcuY4zegrjJx8k+thsgsOVA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-ia32": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.77.8.tgz", - "integrity": "sha512-oWveMe+8TFlP8WBWPna/+Ec5TV0CE+PxEutyi0ltSruBds2zxRq9dPVOqrpPcDN9QUx50vNZC0Afgch0aQEd0g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-x64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.77.8.tgz", - "integrity": "sha512-2NtRpMXHeFo9kaYxuZ+Ewwo39CE7BTS2JDfXkTjZTZqd8H+8KC53eBh516YQnn2oiqxSiKxm7a6pxbxGZGwXOQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-x64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.77.8.tgz", - "integrity": "sha512-ND5qZLWUCpOn7LJfOf0gLSZUWhNIysY+7NZK1Ctq+pM6tpJky3JM5I1jSMplNxv5H3o8p80n0gSm+fcjsEFfjQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "bin": { - "sass": "dart-sass/sass" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-win32-arm64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.77.8.tgz", - "integrity": "sha512-7L8zT6xzEvTYj86MvUWnbkWYCNQP+74HvruLILmiPPE+TCgOjgdi750709BtppVJGGZSs40ZuN6mi/YQyGtwXg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "bin": { - "sass": "dart-sass/sass.bat" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-win32-ia32": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.77.8.tgz", - "integrity": "sha512-7Buh+4bP0WyYn6XPbthkIa3M2vtcR8QIsFVg3JElVlr+8Ng19jqe0t0SwggDgbMX6AdQZC+Wj4F1BprZSok42A==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "bin": { - "sass": "dart-sass/sass.bat" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-win32-x64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.77.8.tgz", - "integrity": "sha512-rZmLIx4/LLQm+4GW39sRJW0MIlDqmyV0fkRzTmhFP5i/wVC7cuj8TUubPHw18rv2rkHFfBZKZJTCkPjCS5Z+SA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "bin": { - "sass": "dart-sass/sass.bat" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sass-embedded/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/screenfull": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", - "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==", - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/scroll-into-view-if-needed": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", - "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", - "dependencies": { - "compute-scroll-into-view": "^3.0.2" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/string-convert": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", - "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/stringify-entities/node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-mod": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", - "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" - }, - "node_modules/style-to-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.7.tgz", - "integrity": "sha512-uSjr59G5u6fbxUfKbb8GcqMGT3Xs9v5IbPkjb0S16GyOeBLAzSRK0CixBv5YrYvzO6TDLzIS6QCn78tkqWngPw==", - "dependencies": { - "inline-style-parser": "0.2.3" - } - }, - "node_modules/stylis": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz", - "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==" - }, - "node_modules/sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tailwindcss": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz", - "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==", - "dev": true, - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/throttle-debounce": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", - "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", - "engines": { - "node": ">=12.22" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/true-myth": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/true-myth/-/true-myth-4.1.1.tgz", - "integrity": "sha512-rqy30BSpxPznbbTcAcci90oZ1YR4DqvKcNXNerG5gQBU2v4jk0cygheiul5J6ExIMrgDVuanv/MkGfqZbKrNNg==", - "dev": true, - "engines": { - "node": "10.* || >= 12.*" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true - }, - "node_modules/ts-morph": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-13.0.3.tgz", - "integrity": "sha512-pSOfUMx8Ld/WUreoSzvMFQG5i9uEiWIsBYjpU9+TTASOeUa89j5HykomeqVULm1oqWtBdleI3KEFRLrlA3zGIw==", - "dev": true, - "dependencies": { - "@ts-morph/common": "~0.12.3", - "code-block-writer": "^11.0.0" - } - }, - "node_modules/ts-prune": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/ts-prune/-/ts-prune-0.10.3.tgz", - "integrity": "sha512-iS47YTbdIcvN8Nh/1BFyziyUqmjXz7GVzWu02RaZXqb+e/3Qe1B7IQ4860krOeCGUeJmterAlaM2FRH0Ue0hjw==", - "dev": true, - "dependencies": { - "commander": "^6.2.1", - "cosmiconfig": "^7.0.1", - "json5": "^2.1.3", - "lodash": "^4.17.21", - "true-myth": "^4.1.0", - "ts-morph": "^13.0.1" - }, - "bin": { - "ts-prune": "lib/index.js" - } - }, - "node_modules/ts-prune/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "devOptional": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz", - "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==", - "dev": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.3.0", - "@typescript-eslint/parser": "8.3.0", - "@typescript-eslint/utils": "8.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true - }, - "node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", - "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-find-after": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", - "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-remove-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", - "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/use-sync-external-store": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", - "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true - }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-location": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", - "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vite": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz", - "integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==", - "dev": true, - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.41", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/w3c-keyname": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" - }, - "node_modules/web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", - "dev": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zustand": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz", - "integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==", - "dependencies": { - "use-sync-external-store": "1.2.2" - }, - "engines": { - "node": ">=12.7.0" - }, - "peerDependencies": { - "@types/react": ">=16.8", - "immer": ">=9.0.6", - "react": ">=16.8" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "immer": { - "optional": true - }, - "react": { - "optional": true - } - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - }, - "dependencies": { - "@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@ant-design/colors": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.1.0.tgz", - "integrity": "sha512-MMoDGWn1y9LdQJQSHiCC20x3uZ3CwQnv9QMz6pCmJOrqdgM9YxsoVVY0wtrdXbmfSgnV0KNk6zi09NAhMR2jvg==", - "requires": { - "@ctrl/tinycolor": "^3.6.1" - } - }, - "@ant-design/cssinjs": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.21.1.tgz", - "integrity": "sha512-tyWnlK+XH7Bumd0byfbCiZNK43HEubMoCcu9VxwsAwiHdHTgWa+tMN0/yvxa+e8EzuFP1WdUNNPclRpVtD33lg==", - "requires": { - "@babel/runtime": "^7.11.1", - "@emotion/hash": "^0.8.0", - "@emotion/unitless": "^0.7.5", - "classnames": "^2.3.1", - "csstype": "^3.1.3", - "rc-util": "^5.35.0", - "stylis": "^4.3.3" - } - }, - "@ant-design/cssinjs-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.0.3.tgz", - "integrity": "sha512-BrztZZKuoYcJK8uEH40ylBemf/Mu/QPiDos56g2bv6eUoniQkgQHOCOvA3+pncoFO1TaS8xcUCIqGzDA0I+ZVQ==", - "requires": { - "@ant-design/cssinjs": "^1.21.0", - "@babel/runtime": "^7.23.2", - "rc-util": "^5.38.0" - } - }, - "@ant-design/fast-color": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", - "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", - "requires": { - "@babel/runtime": "^7.24.7" - } - }, - "@ant-design/icons": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.4.0.tgz", - "integrity": "sha512-QZbWC5xQYexCI5q4/fehSEkchJr5UGtvAJweT743qKUQQGs9IH2DehNLP49DJ3Ii9m9CijD2HN6fNy3WKhIFdA==", - "requires": { - "@ant-design/colors": "^7.0.0", - "@ant-design/icons-svg": "^4.4.0", - "@babel/runtime": "^7.24.8", - "classnames": "^2.2.6", - "rc-util": "^5.31.1" - } - }, - "@ant-design/icons-svg": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", - "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==" - }, - "@ant-design/react-slick": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", - "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", - "requires": { - "@babel/runtime": "^7.10.4", - "classnames": "^2.2.5", - "json2mq": "^0.2.0", - "resize-observer-polyfill": "^1.5.1", - "throttle-debounce": "^5.0.0" - } - }, - "@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - } - }, - "@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", - "dev": true - }, - "@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - } - }, - "@babel/generator": { - "version": "7.25.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.5.tgz", - "integrity": "sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w==", - "dev": true, - "requires": { - "@babel/types": "^7.25.4", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - } - }, - "@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - } - }, - "@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, - "requires": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - } - }, - "@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "dev": true - }, - "@babel/helpers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", - "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", - "dev": true, - "requires": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.0" - } - }, - "@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - } - }, - "@babel/parser": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.4.tgz", - "integrity": "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==", - "dev": true, - "requires": { - "@babel/types": "^7.25.4" - } - }, - "@babel/plugin-transform-react-jsx-self": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", - "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.7" - } - }, - "@babel/plugin-transform-react-jsx-source": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", - "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.7" - } - }, - "@babel/runtime": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", - "requires": { - "regenerator-runtime": "^0.14.0" - } - }, - "@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" - } - }, - "@babel/traverse": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.4.tgz", - "integrity": "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.4", - "@babel/parser": "^7.25.4", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.4", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.4.tgz", - "integrity": "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - } - }, - "@bufbuild/protobuf": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.10.0.tgz", - "integrity": "sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==", - "dev": true - }, - "@codemirror/autocomplete": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.0.tgz", - "integrity": "sha512-5DbOvBbY4qW5l57cjDsmmpDh3/TeK1vXfTHa+BUMrRzdWdcxKZ4U4V7vQaTtOpApNU4kLS4FQ6cINtLg245LXA==", - "requires": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0" - } - }, - "@codemirror/commands": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.0.tgz", - "integrity": "sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==", - "requires": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.27.0", - "@lezer/common": "^1.1.0" - } - }, - "@codemirror/lang-angular": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@codemirror/lang-angular/-/lang-angular-0.1.3.tgz", - "integrity": "sha512-xgeWGJQQl1LyStvndWtruUvb4SnBZDAu/gvFH/ZU+c0W25tQR8e5hq7WTwiIY2dNxnf+49mRiGI/9yxIwB6f5w==", - "requires": { - "@codemirror/lang-html": "^6.0.0", - "@codemirror/lang-javascript": "^6.1.2", - "@codemirror/language": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.3.3" - } - }, - "@codemirror/lang-cpp": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-cpp/-/lang-cpp-6.0.2.tgz", - "integrity": "sha512-6oYEYUKHvrnacXxWxYa6t4puTlbN3dgV662BDfSH8+MfjQjVmP697/KYTDOqpxgerkvoNm7q5wlFMBeX8ZMocg==", - "requires": { - "@codemirror/language": "^6.0.0", - "@lezer/cpp": "^1.0.0" - } - }, - "@codemirror/lang-css": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz", - "integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==", - "requires": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.2", - "@lezer/css": "^1.0.0" - } - }, - "@codemirror/lang-go": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-go/-/lang-go-6.0.1.tgz", - "integrity": "sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==", - "requires": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.6.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/go": "^1.0.0" - } - }, - "@codemirror/lang-html": { - "version": "6.4.9", - "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz", - "integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==", - "requires": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/lang-css": "^6.0.0", - "@codemirror/lang-javascript": "^6.0.0", - "@codemirror/language": "^6.4.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0", - "@lezer/css": "^1.1.0", - "@lezer/html": "^1.3.0" - } - }, - "@codemirror/lang-java": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-java/-/lang-java-6.0.1.tgz", - "integrity": "sha512-OOnmhH67h97jHzCuFaIEspbmsT98fNdhVhmA3zCxW0cn7l8rChDhZtwiwJ/JOKXgfm4J+ELxQihxaI7bj7mJRg==", - "requires": { - "@codemirror/language": "^6.0.0", - "@lezer/java": "^1.0.0" - } - }, - "@codemirror/lang-javascript": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz", - "integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==", - "requires": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.6.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0", - "@lezer/javascript": "^1.0.0" - } - }, - "@codemirror/lang-json": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz", - "integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==", - "requires": { - "@codemirror/language": "^6.0.0", - "@lezer/json": "^1.0.0" - } - }, - "@codemirror/lang-less": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-less/-/lang-less-6.0.2.tgz", - "integrity": "sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==", - "requires": { - "@codemirror/lang-css": "^6.2.0", - "@codemirror/language": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@codemirror/lang-lezer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-lezer/-/lang-lezer-6.0.1.tgz", - "integrity": "sha512-WHwjI7OqKFBEfkunohweqA5B/jIlxaZso6Nl3weVckz8EafYbPZldQEKSDb4QQ9H9BUkle4PVELP4sftKoA0uQ==", - "requires": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/lezer": "^1.0.0" - } - }, - "@codemirror/lang-liquid": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-liquid/-/lang-liquid-6.2.1.tgz", - "integrity": "sha512-J1Mratcm6JLNEiX+U2OlCDTysGuwbHD76XwuL5o5bo9soJtSbz2g6RU3vGHFyS5DC8rgVmFSzi7i6oBftm7tnA==", - "requires": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/lang-html": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.3.1" - } - }, - "@codemirror/lang-markdown": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.2.5.tgz", - "integrity": "sha512-Hgke565YcO4fd9pe2uLYxnMufHO5rQwRr+AAhFq8ABuhkrjyX8R5p5s+hZUTdV60O0dMRjxKhBLxz8pu/MkUVA==", - "requires": { - "@codemirror/autocomplete": "^6.7.1", - "@codemirror/lang-html": "^6.0.0", - "@codemirror/language": "^6.3.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.2.1", - "@lezer/markdown": "^1.0.0" - } - }, - "@codemirror/lang-php": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-php/-/lang-php-6.0.1.tgz", - "integrity": "sha512-ublojMdw/PNWa7qdN5TMsjmqkNuTBD3k6ndZ4Z0S25SBAiweFGyY68AS3xNcIOlb6DDFDvKlinLQ40vSLqf8xA==", - "requires": { - "@codemirror/lang-html": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/php": "^1.0.0" - } - }, - "@codemirror/lang-python": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.6.tgz", - "integrity": "sha512-ai+01WfZhWqM92UqjnvorkxosZ2aq2u28kHvr+N3gu012XqY2CThD67JPMHnGceRfXPDBmn1HnyqowdpF57bNg==", - "requires": { - "@codemirror/autocomplete": "^6.3.2", - "@codemirror/language": "^6.8.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.2.1", - "@lezer/python": "^1.1.4" - } - }, - "@codemirror/lang-rust": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-6.0.1.tgz", - "integrity": "sha512-344EMWFBzWArHWdZn/NcgkwMvZIWUR1GEBdwG8FEp++6o6vT6KL9V7vGs2ONsKxxFUPXKI0SPcWhyYyl2zPYxQ==", - "requires": { - "@codemirror/language": "^6.0.0", - "@lezer/rust": "^1.0.0" - } - }, - "@codemirror/lang-sass": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-sass/-/lang-sass-6.0.2.tgz", - "integrity": "sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==", - "requires": { - "@codemirror/lang-css": "^6.2.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.2", - "@lezer/sass": "^1.0.0" - } - }, - "@codemirror/lang-sql": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.7.1.tgz", - "integrity": "sha512-flQa7zemrLKk0TIrOJnpeyH/b29BcVybtsTeZMgAo40O6kGbrnUSCgwI3TF5iJY3O9VXJKKCA+i0CBVvDfr88w==", - "requires": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@codemirror/lang-vue": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@codemirror/lang-vue/-/lang-vue-0.1.3.tgz", - "integrity": "sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==", - "requires": { - "@codemirror/lang-html": "^6.0.0", - "@codemirror/lang-javascript": "^6.1.2", - "@codemirror/language": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.3.1" - } - }, - "@codemirror/lang-wast": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-wast/-/lang-wast-6.0.2.tgz", - "integrity": "sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==", - "requires": { - "@codemirror/language": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@codemirror/lang-xml": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", - "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", - "requires": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.4.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/xml": "^1.0.0" - } - }, - "@codemirror/lang-yaml": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.1.tgz", - "integrity": "sha512-HV2NzbK9bbVnjWxwObuZh5FuPCowx51mEfoFT9y3y+M37fA3+pbxx4I7uePuygFzDsAmCTwQSc/kXh/flab4uw==", - "requires": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.2.0", - "@lezer/yaml": "^1.0.0" - } - }, - "@codemirror/language": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.2.tgz", - "integrity": "sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==", - "requires": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.23.0", - "@lezer/common": "^1.1.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0", - "style-mod": "^4.0.0" - } - }, - "@codemirror/language-data": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@codemirror/language-data/-/language-data-6.5.1.tgz", - "integrity": "sha512-0sWxeUSNlBr6OmkqybUTImADFUP0M3P0IiSde4nc24bz/6jIYzqYSgkOSLS+CBIoW1vU8Q9KUWXscBXeoMVC9w==", - "requires": { - "@codemirror/lang-angular": "^0.1.0", - "@codemirror/lang-cpp": "^6.0.0", - "@codemirror/lang-css": "^6.0.0", - "@codemirror/lang-go": "^6.0.0", - "@codemirror/lang-html": "^6.0.0", - "@codemirror/lang-java": "^6.0.0", - "@codemirror/lang-javascript": "^6.0.0", - "@codemirror/lang-json": "^6.0.0", - "@codemirror/lang-less": "^6.0.0", - "@codemirror/lang-liquid": "^6.0.0", - "@codemirror/lang-markdown": "^6.0.0", - "@codemirror/lang-php": "^6.0.0", - "@codemirror/lang-python": "^6.0.0", - "@codemirror/lang-rust": "^6.0.0", - "@codemirror/lang-sass": "^6.0.0", - "@codemirror/lang-sql": "^6.0.0", - "@codemirror/lang-vue": "^0.1.1", - "@codemirror/lang-wast": "^6.0.0", - "@codemirror/lang-xml": "^6.0.0", - "@codemirror/lang-yaml": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/legacy-modes": "^6.4.0" - } - }, - "@codemirror/legacy-modes": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.4.1.tgz", - "integrity": "sha512-vdg3XY7OAs5uLDx2Iw+cGfnwtd7kM+Et/eMsqAGTfT/JKiVBQZXosTzjEbWAi/FrY6DcQIz8mQjBozFHZEUWQA==", - "requires": { - "@codemirror/language": "^6.0.0" - } - }, - "@codemirror/lint": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.1.tgz", - "integrity": "sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==", - "requires": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, - "@codemirror/search": { - "version": "6.5.6", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", - "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", - "requires": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, - "@codemirror/state": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", - "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==" - }, - "@codemirror/theme-one-dark": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz", - "integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==", - "requires": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/highlight": "^1.0.0" - } - }, - "@codemirror/view": { - "version": "6.33.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.33.0.tgz", - "integrity": "sha512-AroaR3BvnjRW8fiZBalAaK+ZzB5usGgI014YKElYZvQdNH5ZIidHlO+cyf/2rWzyBFRkvG6VhiXeAEbC53P2YQ==", - "requires": { - "@codemirror/state": "^6.4.0", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, - "@ctrl/tinycolor": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", - "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==" - }, - "@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" - }, - "@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" - }, - "@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "dev": true, - "optional": true - }, - "@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "dev": true, - "optional": true - }, - "@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "dev": true, - "optional": true - }, - "@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "dev": true, - "optional": true - }, - "@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "dev": true, - "optional": true - }, - "@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "dev": true, - "optional": true - }, - "@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "dev": true, - "optional": true - }, - "@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "dev": true, - "optional": true - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } - } - }, - "@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "dev": true - }, - "@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", - "dev": true, - "requires": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - } - }, - "@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true - } - } - }, - "@eslint/js": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", - "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", - "dev": true - }, - "@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", - "dev": true - }, - "@formatjs/ecma402-abstract": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.0.0.tgz", - "integrity": "sha512-rRqXOqdFmk7RYvj4khklyqzcfQl9vEL/usogncBHRZfZBDOwMGuSRNFl02fu5KGHXdbinju+YXyuR+Nk8xlr/g==", - "requires": { - "@formatjs/intl-localematcher": "0.5.4", - "tslib": "^2.4.0" - } - }, - "@formatjs/fast-memoize": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.0.tgz", - "integrity": "sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==", - "requires": { - "tslib": "^2.4.0" - } - }, - "@formatjs/icu-messageformat-parser": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.8.tgz", - "integrity": "sha512-nBZJYmhpcSX0WeJ5SDYUkZ42AgR3xiyhNCsQweFx3cz/ULJjym8bHAzWKvG5e2+1XO98dBYC0fWeeAECAVSwLA==", - "requires": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/icu-skeleton-parser": "1.8.2", - "tslib": "^2.4.0" - } - }, - "@formatjs/icu-skeleton-parser": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.2.tgz", - "integrity": "sha512-k4ERKgw7aKGWJZgTarIcNEmvyTVD9FYh0mTrrBMHZ1b8hUu6iOJ4SzsZlo3UNAvHYa+PnvntIwRPt1/vy4nA9Q==", - "requires": { - "@formatjs/ecma402-abstract": "2.0.0", - "tslib": "^2.4.0" - } - }, - "@formatjs/intl": { - "version": "2.10.4", - "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.4.tgz", - "integrity": "sha512-56483O+HVcL0c7VucAS2tyH020mt9XTozZO67cwtGg0a7KWDukS/FzW3OnvaHmTHDuYsoPIzO+ZHVfU6fT/bJw==", - "requires": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/fast-memoize": "2.2.0", - "@formatjs/icu-messageformat-parser": "2.7.8", - "@formatjs/intl-displaynames": "6.6.8", - "@formatjs/intl-listformat": "7.5.7", - "intl-messageformat": "10.5.14", - "tslib": "^2.4.0" - } - }, - "@formatjs/intl-displaynames": { - "version": "6.6.8", - "resolved": "https://registry.npmjs.org/@formatjs/intl-displaynames/-/intl-displaynames-6.6.8.tgz", - "integrity": "sha512-Lgx6n5KxN16B3Pb05z3NLEBQkGoXnGjkTBNCZI+Cn17YjHJ3fhCeEJJUqRlIZmJdmaXQhjcQVDp6WIiNeRYT5g==", - "requires": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/intl-localematcher": "0.5.4", - "tslib": "^2.4.0" - } - }, - "@formatjs/intl-listformat": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-7.5.7.tgz", - "integrity": "sha512-MG2TSChQJQT9f7Rlv+eXwUFiG24mKSzmF144PLb8m8OixyXqn4+YWU+5wZracZGCgVTVmx8viCf7IH3QXoiB2g==", - "requires": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/intl-localematcher": "0.5.4", - "tslib": "^2.4.0" - } - }, - "@formatjs/intl-localematcher": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.4.tgz", - "integrity": "sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==", - "requires": { - "tslib": "^2.4.0" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", - "dev": true - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@lezer/common": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", - "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==" - }, - "@lezer/cpp": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.2.tgz", - "integrity": "sha512-macwKtyeUO0EW86r3xWQCzOV9/CF8imJLpJlPv3sDY57cPGeUZ8gXWOWNlJr52TVByMV3PayFQCA5SHEERDmVQ==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/css": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.8.tgz", - "integrity": "sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/go": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@lezer/go/-/go-1.0.0.tgz", - "integrity": "sha512-co9JfT3QqX1YkrMmourYw2Z8meGC50Ko4d54QEcQbEYpvdUvN4yb0NBZdn/9ertgvjsySxHsKzH3lbm3vqJ4Jw==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/highlight": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", - "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", - "requires": { - "@lezer/common": "^1.0.0" - } - }, - "@lezer/html": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz", - "integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/java": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.2.tgz", - "integrity": "sha512-3j8X70JvYf0BZt8iSRLXLkt0Ry1hVUgH6wT32yBxH/Xi55nW2VMhc1Az4SKwu4YGSmxCm1fsqDDcHTuFjC8pmg==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/javascript": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.17.tgz", - "integrity": "sha512-bYW4ctpyGK+JMumDApeUzuIezX01H76R1foD6LcRX224FWfyYit/HYxiPGDjXXe/wQWASjCvVGoukTH68+0HIA==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.1.3", - "@lezer/lr": "^1.3.0" - } - }, - "@lezer/json": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.2.tgz", - "integrity": "sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/lezer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lezer/lezer/-/lezer-1.1.2.tgz", - "integrity": "sha512-O8yw3CxPhzYHB1hvwbdozjnAslhhR8A5BH7vfEMof0xk3p+/DFDfZkA9Tde6J+88WgtwaHy4Sy6ThZSkaI0Evw==", - "requires": { - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/lr": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", - "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", - "requires": { - "@lezer/common": "^1.0.0" - } - }, - "@lezer/markdown": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.3.0.tgz", - "integrity": "sha512-ErbEQ15eowmJUyT095e9NJc3BI9yZ894fjSDtHftD0InkfUBGgnKSU6dvan9jqsZuNHg2+ag/1oyDRxNsENupQ==", - "requires": { - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0" - } - }, - "@lezer/php": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.2.tgz", - "integrity": "sha512-GN7BnqtGRpFyeoKSEqxvGvhJQiI4zkgmYnDk/JIyc7H7Ifc1tkPnUn/R2R8meH3h/aBf5rzjvU8ZQoyiNDtDrA==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.1.0" - } - }, - "@lezer/python": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.14.tgz", - "integrity": "sha512-ykDOb2Ti24n76PJsSa4ZoDF0zH12BSw1LGfQXCYJhJyOGiFTfGaX0Du66Ze72R+u/P35U+O6I9m8TFXov1JzsA==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/rust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz", - "integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/sass": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@lezer/sass/-/sass-1.0.6.tgz", - "integrity": "sha512-w/RCO2dIzZH1To8p+xjs8cE+yfgGus8NZ/dXeWl/QzHyr+TeBs71qiE70KPImEwvTsmEjoWh0A5SxMzKd5BWBQ==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/xml": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.5.tgz", - "integrity": "sha512-VFouqOzmUWfIg+tfmpcdV33ewtK+NSwd4ngSe1aG7HFb4BN0ExyY1b8msp+ndFrnlG4V4iC8yXacjFtrwERnaw==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "@lezer/yaml": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz", - "integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==", - "requires": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.4.0" - } - }, - "@nextjournal/lang-clojure": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@nextjournal/lang-clojure/-/lang-clojure-1.0.0.tgz", - "integrity": "sha512-gOCV71XrYD0DhwGoPMWZmZ0r92/lIHsqQu9QWdpZYYBwiChNwMO4sbVMP7eTuAqffFB2BTtCSC+1skSH9d3bNg==", - "requires": { - "@codemirror/language": "^6.0.0", - "@nextjournal/lezer-clojure": "1.0.0" - } - }, - "@nextjournal/lezer-clojure": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@nextjournal/lezer-clojure/-/lezer-clojure-1.0.0.tgz", - "integrity": "sha512-VZyuGu4zw5mkTOwQBTaGVNWmsOZAPw5ZRxu1/Knk/Xfs7EDBIogwIs5UXTYkuECX5ZQB8eOB+wKA2pc7VyqaZQ==", - "requires": { - "@lezer/lr": "^1.0.0" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true - }, - "@rc-component/async-validator": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz", - "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", - "requires": { - "@babel/runtime": "^7.24.4" - } - }, - "@rc-component/color-picker": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz", - "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", - "requires": { - "@ant-design/fast-color": "^2.0.6", - "@babel/runtime": "^7.23.6", - "classnames": "^2.2.6", - "rc-util": "^5.38.1" - } - }, - "@rc-component/context": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", - "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", - "requires": { - "@babel/runtime": "^7.10.1", - "rc-util": "^5.27.0" - } - }, - "@rc-component/mini-decimal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", - "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", - "requires": { - "@babel/runtime": "^7.18.0" - } - }, - "@rc-component/mutate-observer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", - "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", - "requires": { - "@babel/runtime": "^7.18.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - } - }, - "@rc-component/portal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", - "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", - "requires": { - "@babel/runtime": "^7.18.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - } - }, - "@rc-component/qrcode": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.0.tgz", - "integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==", - "requires": { - "@babel/runtime": "^7.24.7", - "classnames": "^2.3.2", - "rc-util": "^5.38.0" - } - }, - "@rc-component/tour": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.0.tgz", - "integrity": "sha512-h6hyILDwL+In9GAgRobwRWihLqqsD7Uft3fZGrJ7L4EiyCoxbnNYwzPXDfz7vNDhWeVyvAWQJj9fJCzpI4+b4g==", - "requires": { - "@babel/runtime": "^7.18.0", - "@rc-component/portal": "^1.0.0-9", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - } - }, - "@rc-component/trigger": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.1.tgz", - "integrity": "sha512-fuU11J8pOt6+U/tU6/CAv8wjCwGaNeRk9f5k8HQth7JBbJ6MMH62WhGycVW75VnXfBZgL/7kO+wbiO2Xc9U9sQ==", - "requires": { - "@babel/runtime": "^7.23.2", - "@rc-component/portal": "^1.1.0", - "classnames": "^2.3.2", - "rc-motion": "^2.0.0", - "rc-resize-observer": "^1.3.1", - "rc-util": "^5.38.0" - } - }, - "@remix-run/router": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.1.tgz", - "integrity": "sha512-S45oynt/WH19bHbIXjtli6QmwNYvaz+vtnubvNpNDvUOoA/OWh6j1OikIP3G+v5GHdxyC6EXoChG3HgYGEUfcg==" - }, - "@replit/codemirror-lang-csharp": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-csharp/-/codemirror-lang-csharp-6.2.0.tgz", - "integrity": "sha512-6utbaWkoymhoAXj051mkRp+VIJlpwUgCX9Toevz3YatiZsz512fw3OVCedXQx+WcR0wb6zVHjChnuxqfCLtFVQ==", - "requires": {} - }, - "@replit/codemirror-lang-nix": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-nix/-/codemirror-lang-nix-6.0.1.tgz", - "integrity": "sha512-lvzjoYn9nfJzBD5qdm3Ut6G3+Or2wEacYIDJ49h9+19WSChVnxv4ojf+rNmQ78ncuxIt/bfbMvDLMeMP0xze6g==", - "requires": {} - }, - "@replit/codemirror-lang-solidity": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-solidity/-/codemirror-lang-solidity-6.0.2.tgz", - "integrity": "sha512-/dpTVH338KFV6SaDYYSadkB4bI/0B0QRF/bkt1XS3t3QtyR49mn6+2k0OUQhvt2ZSO7kt10J+OPilRAtgbmX0w==", - "requires": { - "@lezer/highlight": "^1.2.0" - } - }, - "@replit/codemirror-lang-svelte": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-svelte/-/codemirror-lang-svelte-6.0.0.tgz", - "integrity": "sha512-U2OqqgMM6jKelL0GNWbAmqlu1S078zZNoBqlJBW+retTc5M4Mha6/Y2cf4SVg6ddgloJvmcSpt4hHrVoM4ePRA==", - "requires": {} - }, - "@rollup/rollup-android-arm-eabi": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.1.tgz", - "integrity": "sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==", - "dev": true, - "optional": true - }, - "@rollup/rollup-android-arm64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.1.tgz", - "integrity": "sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==", - "dev": true, - "optional": true - }, - "@rollup/rollup-darwin-arm64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.1.tgz", - "integrity": "sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==", - "dev": true, - "optional": true - }, - "@rollup/rollup-darwin-x64": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.1.tgz", - "integrity": "sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.1.tgz", - "integrity": "sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.1.tgz", - "integrity": "sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.1.tgz", - "integrity": "sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-arm64-musl": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.1.tgz", - "integrity": "sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.1.tgz", - "integrity": "sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.1.tgz", - "integrity": "sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.1.tgz", - "integrity": "sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-x64-gnu": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.1.tgz", - "integrity": "sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==", - "dev": true, - "optional": true - }, - "@rollup/rollup-linux-x64-musl": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.1.tgz", - "integrity": "sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==", - "dev": true, - "optional": true - }, - "@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.1.tgz", - "integrity": "sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==", - "dev": true, - "optional": true - }, - "@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.1.tgz", - "integrity": "sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==", - "dev": true, - "optional": true - }, - "@rollup/rollup-win32-x64-msvc": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.1.tgz", - "integrity": "sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==", - "dev": true, - "optional": true - }, - "@ts-morph/common": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.12.3.tgz", - "integrity": "sha512-4tUmeLyXJnJWvTFOKtcNJ1yh0a3SsTLi2MUoyj8iUNznFRN1ZquaNe7Oukqrnki2FzZkm0J9adCNLDZxUzvj+w==", - "dev": true, - "requires": { - "fast-glob": "^3.2.7", - "minimatch": "^3.0.4", - "mkdirp": "^1.0.4", - "path-browserify": "^1.0.1" - } - }, - "@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "requires": { - "@babel/types": "^7.20.7" - } - }, - "@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "requires": { - "@types/ms": "*" - } - }, - "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" - }, - "@types/estree-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", - "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", - "requires": { - "@types/estree": "*" - } - }, - "@types/hast": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", - "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", - "requires": { - "@types/unist": "^2" - }, - "dependencies": { - "@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - } - } - }, - "@types/hoist-non-react-statics": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", - "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", - "requires": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, - "@types/js-cookie": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", - "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", - "dev": true - }, - "@types/katex": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", - "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==" - }, - "@types/lodash": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==" - }, - "@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "requires": { - "@types/unist": "*" - } - }, - "@types/ms": { - "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" - }, - "@types/node": { - "version": "22.5.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.1.tgz", - "integrity": "sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==", - "dev": true, - "requires": { - "undici-types": "~6.19.2" - } - }, - "@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "dev": true - }, - "@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" - }, - "@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" - }, - "@types/react": { - "version": "18.3.4", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz", - "integrity": "sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==", - "requires": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "@types/react-copy-to-clipboard": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.7.tgz", - "integrity": "sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==", - "requires": { - "@types/react": "*" - } - }, - "@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, - "@types/react-syntax-highlighter": { - "version": "15.5.13", - "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz", - "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==", - "requires": { - "@types/react": "*" - } - }, - "@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" - }, - "@typescript-eslint/eslint-plugin": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz", - "integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/type-utils": "8.3.0", - "@typescript-eslint/utils": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/parser": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz", - "integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", - "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz", - "integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/utils": "8.3.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", - "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", - "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } - } - }, - "@typescript-eslint/utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", - "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", - "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.3.0", - "eslint-visitor-keys": "^3.4.3" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } - } - }, - "@uiw/codemirror-extensions-basic-setup": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.23.0.tgz", - "integrity": "sha512-+k5nkRpUWGaHr1JWT8jcKsVewlXw5qBgSopm9LW8fZ6KnSNZBycz8kHxh0+WSvckmXEESGptkIsb7dlkmJT/hQ==", - "requires": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/commands": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/search": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0" - } - }, - "@uiw/codemirror-extensions-langs": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-langs/-/codemirror-extensions-langs-4.23.0.tgz", - "integrity": "sha512-WUJnTgS3CIV5TZPjwYO+mvRqxfvSSSKC2a+Wm5Uk3uFoZZ7O/GKi4bKKLsIHQkCwNnd9CHJzwN2dpIVrK1AmLA==", - "requires": { - "@codemirror/lang-angular": "^0.1.0", - "@codemirror/lang-cpp": "^6.0.0", - "@codemirror/lang-css": "^6.2.0", - "@codemirror/lang-html": "^6.4.0", - "@codemirror/lang-java": "^6.0.0", - "@codemirror/lang-javascript": "^6.1.0", - "@codemirror/lang-json": "^6.0.0", - "@codemirror/lang-less": "^6.0.1", - "@codemirror/lang-lezer": "^6.0.0", - "@codemirror/lang-liquid": "^6.0.1", - "@codemirror/lang-markdown": "^6.1.0", - "@codemirror/lang-php": "^6.0.0", - "@codemirror/lang-python": "^6.1.0", - "@codemirror/lang-rust": "^6.0.0", - "@codemirror/lang-sass": "^6.0.1", - "@codemirror/lang-sql": "^6.4.0", - "@codemirror/lang-vue": "^0.1.1", - "@codemirror/lang-wast": "^6.0.0", - "@codemirror/lang-xml": "^6.0.0", - "@codemirror/language-data": ">=6.0.0", - "@codemirror/legacy-modes": ">=6.0.0", - "@nextjournal/lang-clojure": "^1.0.0", - "@replit/codemirror-lang-csharp": "^6.1.0", - "@replit/codemirror-lang-nix": "^6.0.1", - "@replit/codemirror-lang-solidity": "^6.0.1", - "@replit/codemirror-lang-svelte": "^6.0.0", - "codemirror-lang-mermaid": "^0.5.0" - } - }, - "@uiw/react-codemirror": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.23.0.tgz", - "integrity": "sha512-MnqTXfgeLA3fsUUQjqjJgemEuNyoGALgsExVm0NQAllAAi1wfj+IoKFeK+h3XXMlTFRCFYOUh4AHDv0YXJLsOg==", - "requires": { - "@babel/runtime": "^7.18.6", - "@codemirror/commands": "^6.1.0", - "@codemirror/state": "^6.1.1", - "@codemirror/theme-one-dark": "^6.0.0", - "@uiw/codemirror-extensions-basic-setup": "4.23.0", - "codemirror": "^6.0.0" - } - }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" - }, - "@vitejs/plugin-react": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", - "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", - "dev": true, - "requires": { - "@babel/core": "^7.24.5", - "@babel/plugin-transform-react-jsx-self": "^7.24.5", - "@babel/plugin-transform-react-jsx-source": "^7.24.1", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" - } - }, - "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "ahooks": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/ahooks/-/ahooks-3.8.1.tgz", - "integrity": "sha512-JoP9+/RWO7MnI/uSKdvQ8WB10Y3oo1PjLv+4Sv4Vpm19Z86VUMdXh+RhWvMGxZZs06sq2p0xVtFk8Oh5ZObsoA==", - "requires": { - "@babel/runtime": "^7.21.0", - "dayjs": "^1.9.1", - "intersection-observer": "^0.12.0", - "js-cookie": "^3.0.5", - "lodash": "^4.17.21", - "react-fast-compare": "^3.2.2", - "resize-observer-polyfill": "^1.5.1", - "screenfull": "^5.0.0", - "tslib": "^2.4.1" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "antd": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/antd/-/antd-5.20.3.tgz", - "integrity": "sha512-v2s5LJlhuccIKLT17ESXQDkiQJdPK4jXg4x2pmSSRlrKXAxfftn8Zhd/7pdF3qR3OkwheQpSRjynrNZKp9Tgkg==", - "requires": { - "@ant-design/colors": "^7.1.0", - "@ant-design/cssinjs": "^1.21.0", - "@ant-design/cssinjs-utils": "^1.0.3", - "@ant-design/icons": "^5.4.0", - "@ant-design/react-slick": "~1.1.2", - "@babel/runtime": "^7.24.8", - "@ctrl/tinycolor": "^3.6.1", - "@rc-component/color-picker": "~2.0.1", - "@rc-component/mutate-observer": "^1.1.0", - "@rc-component/qrcode": "~1.0.0", - "@rc-component/tour": "~1.15.0", - "@rc-component/trigger": "^2.2.1", - "classnames": "^2.5.1", - "copy-to-clipboard": "^3.3.3", - "dayjs": "^1.11.11", - "rc-cascader": "~3.27.0", - "rc-checkbox": "~3.3.0", - "rc-collapse": "~3.7.3", - "rc-dialog": "~9.5.2", - "rc-drawer": "~7.2.0", - "rc-dropdown": "~4.2.0", - "rc-field-form": "~2.4.0", - "rc-image": "~7.9.0", - "rc-input": "~1.6.3", - "rc-input-number": "~9.2.0", - "rc-mentions": "~2.15.0", - "rc-menu": "~9.14.1", - "rc-motion": "^2.9.2", - "rc-notification": "~5.6.0", - "rc-pagination": "~4.2.0", - "rc-picker": "~4.6.13", - "rc-progress": "~4.0.0", - "rc-rate": "~2.13.0", - "rc-resize-observer": "^1.4.0", - "rc-segmented": "~2.3.0", - "rc-select": "~14.15.1", - "rc-slider": "~11.1.5", - "rc-steps": "~6.0.1", - "rc-switch": "~4.1.0", - "rc-table": "~7.45.7", - "rc-tabs": "~15.1.1", - "rc-textarea": "~1.8.1", - "rc-tooltip": "~6.2.0", - "rc-tree": "~5.8.8", - "rc-tree-select": "~5.22.1", - "rc-upload": "~4.7.0", - "rc-util": "^5.43.0", - "scroll-into-view-if-needed": "^3.1.0", - "throttle-debounce": "^5.0.2" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-tree-filter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", - "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", - "dev": true, - "requires": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "axios": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", - "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", - "requires": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "requires": { - "fill-range": "^7.1.1" - } - }, - "browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - } - }, - "buffer-builder": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", - "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", - "dev": true - }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001653", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz", - "integrity": "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==", - "dev": true - }, - "ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==" - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==" - }, - "character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==" - }, - "character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" - }, - "character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" - }, - "chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "classnames": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" - }, - "code-block-writer": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.3.tgz", - "integrity": "sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==", - "dev": true - }, - "codemirror": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", - "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", - "requires": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/commands": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/search": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0" - } - }, - "codemirror-lang-mermaid": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/codemirror-lang-mermaid/-/codemirror-lang-mermaid-0.5.0.tgz", - "integrity": "sha512-Taw/2gPCyNArQJCxIP/HSUif+3zrvD+6Ugt7KJZ2dUKou/8r3ZhcfG8krNTZfV2iu8AuGnymKuo7bLPFyqsh/A==", - "requires": { - "@codemirror/language": "^6.9.0", - "@lezer/highlight": "^1.1.6", - "@lezer/lr": "^1.3.10" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==" - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, - "compute-scroll-into-view": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz", - "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "copy-to-clipboard": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", - "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", - "requires": { - "toggle-selection": "^1.0.6" - } - }, - "cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "dependencies": { - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - } - } - }, - "crelt": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", - "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" - }, - "debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "requires": { - "ms": "2.1.2" - } - }, - "decode-named-character-reference": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", - "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", - "requires": { - "character-entities": "^2.0.0" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" - }, - "devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "requires": { - "dequal": "^2.0.0" - } - }, - "didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "requires": { - "get-intrinsic": "^1.2.4" - } - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "requires": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "eslint": { - "version": "9.9.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", - "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.9.1", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "eslint-plugin-react-hooks": { - "version": "5.1.0-rc-fb9a90fa48-20240614", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0-rc-fb9a90fa48-20240614.tgz", - "integrity": "sha512-xsiRwaDNF5wWNC4ZHLut+x/YcAxksUd9Rizt7LaEn3bV8VyYRpXnRJQlLOfYaVy9esk4DFP4zPPnoNVjq5Gc0w==", - "dev": true, - "requires": {} - }, - "eslint-plugin-react-refresh": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.11.tgz", - "integrity": "sha512-wrAKxMbVr8qhXTtIKfXqAn5SAtRZt0aXxe5P23Fh4pUAdC6XEsybGLB8P0PI4j1yYqOgUEUlzKAGDfo7rJOjcw==", - "dev": true, - "requires": {} - }, - "eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true - }, - "espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", - "dev": true, - "requires": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - } - }, - "esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "estree-util-is-identifier-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fault": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", - "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", - "requires": { - "format": "^0.2.0" - } - }, - "file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "requires": { - "flat-cache": "^4.0.0" - } - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "requires": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - } - }, - "flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" - }, - "foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "format": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", - "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==" - }, - "fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "requires": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, - "glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "15.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", - "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", - "dev": true - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "requires": { - "es-define-property": "^1.0.0" - } - }, - "has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "requires": { - "function-bind": "^1.1.2" - } - }, - "hast-util-from-dom": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.0.tgz", - "integrity": "sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==", - "requires": { - "@types/hast": "^3.0.0", - "hastscript": "^8.0.0", - "web-namespaces": "^2.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - }, - "comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==" - }, - "hast-util-parse-selector": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", - "requires": { - "@types/hast": "^3.0.0" - } - }, - "hastscript": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", - "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", - "requires": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" - } - }, - "property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==" - }, - "space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==" - } - } - }, - "hast-util-from-html": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.2.tgz", - "integrity": "sha512-HwOHwxdt2zC5KQ/CNoybBntRook2zJvfZE/u5/Ap7aLPe22bDqen7KwGkOqOyzL5zIqKwiYX/OTtE0FWgr6XXA==", - "requires": { - "@types/hast": "^3.0.0", - "devlop": "^1.1.0", - "hast-util-from-parse5": "^8.0.0", - "parse5": "^7.0.0", - "vfile": "^6.0.0", - "vfile-message": "^4.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "hast-util-from-html-isomorphic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", - "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", - "requires": { - "@types/hast": "^3.0.0", - "hast-util-from-dom": "^5.0.0", - "hast-util-from-html": "^2.0.0", - "unist-util-remove-position": "^5.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "hast-util-from-parse5": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", - "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", - "requires": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "hastscript": "^8.0.0", - "property-information": "^6.0.0", - "vfile": "^6.0.0", - "vfile-location": "^5.0.0", - "web-namespaces": "^2.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - }, - "comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==" - }, - "hast-util-parse-selector": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", - "requires": { - "@types/hast": "^3.0.0" - } - }, - "hastscript": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", - "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", - "requires": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" - } - }, - "property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==" - }, - "space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==" - } - } - }, - "hast-util-is-element": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", - "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", - "requires": { - "@types/hast": "^3.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==" - }, - "hast-util-raw": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.4.tgz", - "integrity": "sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==", - "requires": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-from-parse5": "^8.0.0", - "hast-util-to-parse5": "^8.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "parse5": "^7.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "hast-util-to-jsx-runtime": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", - "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", - "requires": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-object": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - }, - "comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==" - }, - "property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==" - }, - "space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==" - } - } - }, - "hast-util-to-parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", - "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", - "requires": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - }, - "comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==" - }, - "property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==" - }, - "space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==" - } - } - }, - "hast-util-to-text": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", - "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", - "requires": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "hast-util-is-element": "^3.0.0", - "unist-util-find-after": "^5.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "requires": { - "@types/hast": "^3.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "hastscript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", - "requires": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" - } - }, - "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" - }, - "hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "requires": { - "react-is": "^16.7.0" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - } - } - }, - "html-url-attributes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.0.tgz", - "integrity": "sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==" - }, - "html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==" - }, - "ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true - }, - "immutable": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inline-style-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", - "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" - }, - "intersection-observer": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.2.tgz", - "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==" - }, - "intl-messageformat": { - "version": "10.5.14", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz", - "integrity": "sha512-IjC6sI0X7YRjjyVH9aUgdftcmZK7WXdHeil4KwbjDnRWjnVitKpAx3rr6t6di1joFp5188VqKcobOPA6mCLG/w==", - "requires": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/fast-memoize": "2.2.0", - "@formatjs/icu-messageformat-parser": "2.7.8", - "tslib": "^2.4.0" - } - }, - "is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" - }, - "is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dev": true, - "requires": { - "hasown": "^2.0.2" - } - }, - "is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "dev": true - }, - "js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json2mq": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", - "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", - "requires": { - "string-convert": "^0.2.0" - } - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "katex": { - "version": "0.16.11", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz", - "integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==", - "requires": { - "commander": "^8.3.0" - }, - "dependencies": { - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" - } - } - }, - "keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lowlight": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", - "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", - "requires": { - "fault": "^1.0.0", - "highlight.js": "~10.7.0" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "markdown-table": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", - "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==" - }, - "mdast-util-find-and-replace": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", - "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", - "requires": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==" - } - } - }, - "mdast-util-from-markdown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", - "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", - "requires": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - } - }, - "mdast-util-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", - "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", - "requires": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - } - }, - "mdast-util-gfm-autolink-literal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", - "requires": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" - } - }, - "mdast-util-gfm-footnote": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", - "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", - "requires": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" - } - }, - "mdast-util-gfm-strikethrough": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", - "requires": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - } - }, - "mdast-util-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", - "requires": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - } - }, - "mdast-util-gfm-task-list-item": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", - "requires": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - } - }, - "mdast-util-math": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", - "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", - "requires": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "longest-streak": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.1.0", - "unist-util-remove-position": "^5.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "mdast-util-mdx-expression": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", - "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", - "requires": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "mdast-util-mdx-jsx": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", - "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", - "requires": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - }, - "character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==" - }, - "character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==" - }, - "is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==" - }, - "is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "requires": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - } - }, - "is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==" - }, - "is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==" - }, - "parse-entities": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", - "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", - "requires": { - "@types/unist": "^2.0.0", - "character-entities": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "dependencies": { - "@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - } - } - } - } - }, - "mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", - "requires": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "requires": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - } - }, - "mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", - "requires": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "requires": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - } - }, - "mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "requires": { - "@types/mdast": "^4.0.0" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromark": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", - "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", - "requires": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-core-commonmark": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", - "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", - "requires": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "requires": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "requires": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "requires": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "requires": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-extension-gfm-table": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", - "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", - "requires": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "requires": { - "micromark-util-types": "^2.0.0" - } - }, - "micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "requires": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-extension-math": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", - "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", - "requires": { - "@types/katex": "^0.16.0", - "devlop": "^1.0.0", - "katex": "^0.16.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-factory-destination": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", - "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", - "requires": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-factory-label": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", - "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", - "requires": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "requires": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-factory-title": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", - "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", - "requires": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-factory-whitespace": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", - "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", - "requires": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-util-character": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", - "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", - "requires": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-util-chunked": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", - "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", - "requires": { - "micromark-util-symbol": "^2.0.0" - } - }, - "micromark-util-classify-character": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", - "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", - "requires": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-util-combine-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", - "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", - "requires": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-util-decode-numeric-character-reference": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", - "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", - "requires": { - "micromark-util-symbol": "^2.0.0" - } - }, - "micromark-util-decode-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", - "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", - "requires": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==" - }, - "micromark-util-html-tag-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", - "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==" - }, - "micromark-util-normalize-identifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", - "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", - "requires": { - "micromark-util-symbol": "^2.0.0" - } - }, - "micromark-util-resolve-all": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", - "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", - "requires": { - "micromark-util-types": "^2.0.0" - } - }, - "micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", - "requires": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "micromark-util-subtokenize": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", - "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", - "requires": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==" - }, - "micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==" - }, - "micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "requires": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - } - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true - }, - "object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" - }, - "optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", - "requires": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - }, - "dependencies": { - "character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" - } - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "requires": { - "entities": "^4.4.0" - } - }, - "path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "requires": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - } - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true - }, - "pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true - }, - "postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", - "dev": true, - "requires": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" - } - }, - "postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - }, - "postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, - "requires": { - "camelcase-css": "^2.0.1" - } - }, - "postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "dev": true, - "requires": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "dependencies": { - "lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "dev": true - } - } - }, - "postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.1.1" - } - }, - "postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==" - }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - } - } - }, - "property-information": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", - "requires": { - "xtend": "^4.0.0" - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, - "qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "requires": { - "side-channel": "^1.0.6" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "rc-cascader": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.27.0.tgz", - "integrity": "sha512-z5uq8VvQadFUBiuZJ7YF5UAUGNkZtdEtcEYiIA94N/Kc2MIKr6lEbN5HyVddvYSgwWlKqnL6pH5bFXFuIK3MNg==", - "requires": { - "@babel/runtime": "^7.12.5", - "array-tree-filter": "^2.1.0", - "classnames": "^2.3.1", - "rc-select": "~14.15.0", - "rc-tree": "~5.8.1", - "rc-util": "^5.37.0" - } - }, - "rc-checkbox": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.3.0.tgz", - "integrity": "sha512-Ih3ZaAcoAiFKJjifzwsGiT/f/quIkxJoklW4yKGho14Olulwn8gN7hOBve0/WGDg5o/l/5mL0w7ff7/YGvefVw==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.3.2", - "rc-util": "^5.25.2" - } - }, - "rc-collapse": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.7.3.tgz", - "integrity": "sha512-60FJcdTRn0X5sELF18TANwtVi7FtModq649H11mYF1jh83DniMoM4MqY627sEKRCTm4+WXfGDcB7hY5oW6xhyw==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^2.3.4", - "rc-util": "^5.27.0" - } - }, - "rc-dialog": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.5.2.tgz", - "integrity": "sha512-qVUjc8JukG+j/pNaHVSRa2GO2/KbV2thm7yO4hepQ902eGdYK913sGkwg/fh9yhKYV1ql3BKIN2xnud3rEXAPw==", - "requires": { - "@babel/runtime": "^7.10.1", - "@rc-component/portal": "^1.0.0-8", - "classnames": "^2.2.6", - "rc-motion": "^2.3.0", - "rc-util": "^5.21.0" - } - }, - "rc-drawer": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.2.0.tgz", - "integrity": "sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==", - "requires": { - "@babel/runtime": "^7.23.9", - "@rc-component/portal": "^1.1.1", - "classnames": "^2.2.6", - "rc-motion": "^2.6.1", - "rc-util": "^5.38.1" - } - }, - "rc-dropdown": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.0.tgz", - "integrity": "sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==", - "requires": { - "@babel/runtime": "^7.18.3", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.2.6", - "rc-util": "^5.17.0" - } - }, - "rc-field-form": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.4.0.tgz", - "integrity": "sha512-XZ/lF9iqf9HXApIHQHqzJK5v2w4mkUMsVqAzOyWVzoiwwXEavY6Tpuw7HavgzIoD+huVff4JghSGcgEfX6eycg==", - "requires": { - "@babel/runtime": "^7.18.0", - "@rc-component/async-validator": "^5.0.3", - "rc-util": "^5.32.2" - } - }, - "rc-image": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.9.0.tgz", - "integrity": "sha512-l4zqO5E0quuLMCtdKfBgj4Suv8tIS011F5k1zBBlK25iMjjiNHxA0VeTzGFtUZERSA45gvpXDg8/P6qNLjR25g==", - "requires": { - "@babel/runtime": "^7.11.2", - "@rc-component/portal": "^1.0.2", - "classnames": "^2.2.6", - "rc-dialog": "~9.5.2", - "rc-motion": "^2.6.2", - "rc-util": "^5.34.1" - } - }, - "rc-input": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.6.3.tgz", - "integrity": "sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==", - "requires": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-util": "^5.18.1" - } - }, - "rc-input-number": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.2.0.tgz", - "integrity": "sha512-5XZFhBCV5f9UQ62AZ2hFbEY8iZT/dm23Q1kAg0H8EvOgD3UDbYYJAayoVIkM3lQaCqYAW5gV0yV3vjw1XtzWHg==", - "requires": { - "@babel/runtime": "^7.10.1", - "@rc-component/mini-decimal": "^1.0.1", - "classnames": "^2.2.5", - "rc-input": "~1.6.0", - "rc-util": "^5.40.1" - } - }, - "rc-mentions": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.15.0.tgz", - "integrity": "sha512-f5v5i7VdqvBDXbphoqcQWmXDif2Msd2arritVoWybrVDuHE6nQ7XCYsybHbV//WylooK52BFDouFvyaRDtXZEw==", - "requires": { - "@babel/runtime": "^7.22.5", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.2.6", - "rc-input": "~1.6.0", - "rc-menu": "~9.14.0", - "rc-textarea": "~1.8.0", - "rc-util": "^5.34.1" - } - }, - "rc-menu": { - "version": "9.14.1", - "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.14.1.tgz", - "integrity": "sha512-5wlRb3M8S4yGlWhSoEYJ7ZVRElyScdcpUHxgiLxkeig1tEdyKrnED3B2fhpN0Rrpdp9jyhnmZR/Lwq2fH5VvDQ==", - "requires": { - "@babel/runtime": "^7.10.1", - "@rc-component/trigger": "^2.0.0", - "classnames": "2.x", - "rc-motion": "^2.4.3", - "rc-overflow": "^1.3.1", - "rc-util": "^5.27.0" - } - }, - "rc-motion": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.2.tgz", - "integrity": "sha512-fUAhHKLDdkAXIDLH0GYwof3raS58dtNUmzLF2MeiR8o6n4thNpSDQhOqQzWE4WfFZDCi9VEN8n7tiB7czREcyw==", - "requires": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-util": "^5.43.0" - } - }, - "rc-notification": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.0.tgz", - "integrity": "sha512-TGQW5T7waOxLwgJG7fXcw8l7AQiFOjaZ7ISF5PrU526nunHRNcTMuzKihQHaF4E/h/KfOCDk3Mv8eqzbu2e28w==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^2.9.0", - "rc-util": "^5.20.1" - } - }, - "rc-overflow": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.2.tgz", - "integrity": "sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==", - "requires": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.37.0" - } - }, - "rc-pagination": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-4.2.0.tgz", - "integrity": "sha512-V6qeANJsT6tmOcZ4XiUmj8JXjRLbkusuufpuoBw2GiAn94fIixYjFLmbruD1Sbhn8fPLDnWawPp4CN37zQorvw==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.3.2", - "rc-util": "^5.38.0" - } - }, - "rc-picker": { - "version": "4.6.14", - "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.6.14.tgz", - "integrity": "sha512-7DuTfUFdkxmsNpWQ0TWv6FPGna5e6KKC4nxtx3x9xhumLz7jb3fhlDdWQvqEL6tpt9DOb1+N5j+wB+lDOSS9kg==", - "requires": { - "@babel/runtime": "^7.24.7", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.2.1", - "rc-overflow": "^1.3.2", - "rc-resize-observer": "^1.4.0", - "rc-util": "^5.43.0" - } - }, - "rc-progress": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", - "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.6", - "rc-util": "^5.16.1" - } - }, - "rc-rate": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.0.tgz", - "integrity": "sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.5", - "rc-util": "^5.0.1" - } - }, - "rc-resize-observer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz", - "integrity": "sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==", - "requires": { - "@babel/runtime": "^7.20.7", - "classnames": "^2.2.1", - "rc-util": "^5.38.0", - "resize-observer-polyfill": "^1.5.1" - } - }, - "rc-segmented": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.3.0.tgz", - "integrity": "sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg==", - "requires": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-motion": "^2.4.4", - "rc-util": "^5.17.0" - } - }, - "rc-select": { - "version": "14.15.1", - "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.15.1.tgz", - "integrity": "sha512-mGvuwW1RMm1NCSI8ZUoRoLRK51R2Nb+QJnmiAvbDRcjh2//ulCkxeV6ZRFTECPpE1t2DPfyqZMPw90SVJzQ7wQ==", - "requires": { - "@babel/runtime": "^7.10.1", - "@rc-component/trigger": "^2.1.1", - "classnames": "2.x", - "rc-motion": "^2.0.1", - "rc-overflow": "^1.3.1", - "rc-util": "^5.16.1", - "rc-virtual-list": "^3.5.2" - } - }, - "rc-slider": { - "version": "11.1.5", - "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.5.tgz", - "integrity": "sha512-b77H5PbjMKsvkYXAYIkn50QuFX6ICQmCTibDinI9q+BHx65/TV4TeU25+oadhSRzykxs0/vBWeKBwRyySOeWlg==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.5", - "rc-util": "^5.36.0" - } - }, - "rc-steps": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", - "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", - "requires": { - "@babel/runtime": "^7.16.7", - "classnames": "^2.2.3", - "rc-util": "^5.16.1" - } - }, - "rc-switch": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", - "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", - "requires": { - "@babel/runtime": "^7.21.0", - "classnames": "^2.2.1", - "rc-util": "^5.30.0" - } - }, - "rc-table": { - "version": "7.45.7", - "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.45.7.tgz", - "integrity": "sha512-wi9LetBL1t1csxyGkMB2p3mCiMt+NDexMlPbXHvQFmBBAsMxrgNSAPwUci2zDLUq9m8QdWc1Nh8suvrpy9mXrg==", - "requires": { - "@babel/runtime": "^7.10.1", - "@rc-component/context": "^1.4.0", - "classnames": "^2.2.5", - "rc-resize-observer": "^1.1.0", - "rc-util": "^5.37.0", - "rc-virtual-list": "^3.14.2" - } - }, - "rc-tabs": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.1.1.tgz", - "integrity": "sha512-Tc7bJvpEdkWIVCUL7yQrMNBJY3j44NcyWS48jF/UKMXuUlzaXK+Z/pEL5LjGcTadtPvVmNqA40yv7hmr+tCOAw==", - "requires": { - "@babel/runtime": "^7.11.2", - "classnames": "2.x", - "rc-dropdown": "~4.2.0", - "rc-menu": "~9.14.0", - "rc-motion": "^2.6.2", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.34.1" - } - }, - "rc-textarea": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.8.1.tgz", - "integrity": "sha512-bm36N2ZqwZAP60ZQg2OY9mPdqWC+m6UTjHc+CqEZOxb3Ia29BGHazY/s5bI8M4113CkqTzhtFUDNA078ZiOx3Q==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.1", - "rc-input": "~1.6.0", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.27.0" - } - }, - "rc-tooltip": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.2.0.tgz", - "integrity": "sha512-iS/3iOAvtDh9GIx1ulY7EFUXUtktFccNLsARo3NPgLf0QW9oT0w3dA9cYWlhqAKmD+uriEwdWz1kH0Qs4zk2Aw==", - "requires": { - "@babel/runtime": "^7.11.2", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.3.1" - } - }, - "rc-tree": { - "version": "5.8.8", - "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.8.8.tgz", - "integrity": "sha512-S+mCMWo91m5AJqjz3PdzKilGgbFm7fFJRFiTDOcoRbD7UfMOPnerXwMworiga0O2XIo383UoWuEfeHs1WOltag==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^2.0.1", - "rc-util": "^5.16.1", - "rc-virtual-list": "^3.5.1" - } - }, - "rc-tree-select": { - "version": "5.22.2", - "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.22.2.tgz", - "integrity": "sha512-WHmWCck4+8mf4/KFTjw70AlnoNPkX4C1TOIzzwxfZ7w8hcNO4bzggoeO2Q3fAedjZteN5I3t2dT0BCZAnHedlQ==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-select": "~14.15.0", - "rc-tree": "~5.8.1", - "rc-util": "^5.16.1" - } - }, - "rc-upload": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.7.0.tgz", - "integrity": "sha512-eUwxYNHlsYe5vYhKFAUGrQG95JrnPzY+BmPi1Daq39fWNl/eOc7v4UODuWrVp2LFkQBuV3cMCG/I68iub6oBrg==", - "requires": { - "@babel/runtime": "^7.18.3", - "classnames": "^2.2.5", - "rc-util": "^5.2.0" - } - }, - "rc-util": { - "version": "5.43.0", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.43.0.tgz", - "integrity": "sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==", - "requires": { - "@babel/runtime": "^7.18.3", - "react-is": "^18.2.0" - } - }, - "rc-virtual-list": { - "version": "3.14.5", - "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.14.5.tgz", - "integrity": "sha512-ZMOnkCLv2wUN8Jz7yI4XiSLa9THlYvf00LuMhb1JlsQCewuU7ydPuHw1rGVPhe9VZYl/5UqODtNd7QKJ2DMGfg==", - "requires": { - "@babel/runtime": "^7.20.0", - "classnames": "^2.2.6", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.36.0" - } - }, - "react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "requires": { - "loose-envify": "^1.1.0" - } - }, - "react-copy-to-clipboard": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", - "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", - "requires": { - "copy-to-clipboard": "^3.3.1", - "prop-types": "^15.8.1" - } - }, - "react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "requires": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - } - }, - "react-fast-compare": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" - }, - "react-intl": { - "version": "6.6.8", - "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.8.tgz", - "integrity": "sha512-M0pkhzcgV31h++2901BiRXWl69hp2zPyLxRrSwRjd1ErXbNoubz/f4M6DrRTd4OiSUrT4ajRQzrmtS5plG4FtA==", - "requires": { - "@formatjs/ecma402-abstract": "2.0.0", - "@formatjs/icu-messageformat-parser": "2.7.8", - "@formatjs/intl": "2.10.4", - "@formatjs/intl-displaynames": "6.6.8", - "@formatjs/intl-listformat": "7.5.7", - "@types/hoist-non-react-statics": "^3.3.1", - "@types/react": "16 || 17 || 18", - "hoist-non-react-statics": "^3.3.2", - "intl-messageformat": "10.5.14", - "tslib": "^2.4.0" - } - }, - "react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, - "react-markdown": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz", - "integrity": "sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==", - "requires": { - "@types/hast": "^3.0.0", - "devlop": "^1.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "html-url-attributes": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "unified": "^11.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true - }, - "react-router": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.1.tgz", - "integrity": "sha512-kIwJveZNwp7teQRI5QmwWo39A5bXRyqpH0COKKmPnyD2vBvDwgFXSqDUYtt1h+FEyfnE8eXr7oe0MxRzVwCcvQ==", - "requires": { - "@remix-run/router": "1.19.1" - } - }, - "react-router-dom": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.1.tgz", - "integrity": "sha512-veut7m41S1fLql4pLhxeSW3jlqs+4MtjRLj0xvuCEXsxusJCbs6I8yn9BxzzDX2XDgafrccY6hwjmd/bL54tFw==", - "requires": { - "@remix-run/router": "1.19.1", - "react-router": "6.26.1" - } - }, - "react-syntax-highlighter": { - "version": "15.5.0", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz", - "integrity": "sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==", - "requires": { - "@babel/runtime": "^7.3.1", - "highlight.js": "^10.4.1", - "lowlight": "^1.17.0", - "prismjs": "^1.27.0", - "refractor": "^3.6.0" - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "requires": { - "pify": "^2.3.0" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "refractor": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", - "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", - "requires": { - "hastscript": "^6.0.0", - "parse-entities": "^2.0.0", - "prismjs": "~1.27.0" - }, - "dependencies": { - "prismjs": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", - "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==" - } - } - }, - "regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "rehype-katex": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz", - "integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==", - "requires": { - "@types/hast": "^3.0.0", - "@types/katex": "^0.16.0", - "hast-util-from-html-isomorphic": "^2.0.0", - "hast-util-to-text": "^4.0.0", - "katex": "^0.16.0", - "unist-util-visit-parents": "^6.0.0", - "vfile": "^6.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "rehype-raw": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", - "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", - "requires": { - "@types/hast": "^3.0.0", - "hast-util-raw": "^9.0.0", - "vfile": "^6.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "remark-gfm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", - "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", - "requires": { - "@types/mdast": "^4.0.0", - "mdast-util-gfm": "^3.0.0", - "micromark-extension-gfm": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "unified": "^11.0.0" - } - }, - "remark-math": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", - "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", - "requires": { - "@types/mdast": "^4.0.0", - "mdast-util-math": "^3.0.0", - "micromark-extension-math": "^3.0.0", - "unified": "^11.0.0" - } - }, - "remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "requires": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - } - }, - "remark-rehype": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", - "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", - "requires": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "dependencies": { - "@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "requires": { - "@types/unist": "*" - } - } - } - }, - "remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", - "requires": { - "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", - "unified": "^11.0.0" - } - }, - "resize-observer-polyfill": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", - "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" - }, - "resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rollup": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.1.tgz", - "integrity": "sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==", - "dev": true, - "requires": { - "@rollup/rollup-android-arm-eabi": "4.21.1", - "@rollup/rollup-android-arm64": "4.21.1", - "@rollup/rollup-darwin-arm64": "4.21.1", - "@rollup/rollup-darwin-x64": "4.21.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.1", - "@rollup/rollup-linux-arm-musleabihf": "4.21.1", - "@rollup/rollup-linux-arm64-gnu": "4.21.1", - "@rollup/rollup-linux-arm64-musl": "4.21.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.1", - "@rollup/rollup-linux-riscv64-gnu": "4.21.1", - "@rollup/rollup-linux-s390x-gnu": "4.21.1", - "@rollup/rollup-linux-x64-gnu": "4.21.1", - "@rollup/rollup-linux-x64-musl": "4.21.1", - "@rollup/rollup-win32-arm64-msvc": "4.21.1", - "@rollup/rollup-win32-ia32-msvc": "4.21.1", - "@rollup/rollup-win32-x64-msvc": "4.21.1", - "@types/estree": "1.0.5", - "fsevents": "~2.3.2" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, - "sass-embedded": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.77.8.tgz", - "integrity": "sha512-WGXA6jcaoBo5Uhw0HX/s6z/sl3zyYQ7ZOnLOJzqwpctFcFmU4L07zn51e2VSkXXFpQZFAdMZNqOGz/7h/fvcRA==", - "dev": true, - "requires": { - "@bufbuild/protobuf": "^1.0.0", - "buffer-builder": "^0.2.0", - "immutable": "^4.0.0", - "rxjs": "^7.4.0", - "sass-embedded-android-arm": "1.77.8", - "sass-embedded-android-arm64": "1.77.8", - "sass-embedded-android-ia32": "1.77.8", - "sass-embedded-android-x64": "1.77.8", - "sass-embedded-darwin-arm64": "1.77.8", - "sass-embedded-darwin-x64": "1.77.8", - "sass-embedded-linux-arm": "1.77.8", - "sass-embedded-linux-arm64": "1.77.8", - "sass-embedded-linux-ia32": "1.77.8", - "sass-embedded-linux-musl-arm": "1.77.8", - "sass-embedded-linux-musl-arm64": "1.77.8", - "sass-embedded-linux-musl-ia32": "1.77.8", - "sass-embedded-linux-musl-x64": "1.77.8", - "sass-embedded-linux-x64": "1.77.8", - "sass-embedded-win32-arm64": "1.77.8", - "sass-embedded-win32-ia32": "1.77.8", - "sass-embedded-win32-x64": "1.77.8", - "supports-color": "^8.1.1", - "varint": "^6.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "sass-embedded-android-arm": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.77.8.tgz", - "integrity": "sha512-GpGL7xZ7V1XpFbnflib/NWbM0euRzineK0iwoo31/ntWKAXGj03iHhGzkSiOwWSFcXgsJJi3eRA5BTmBvK5Q+w==", - "dev": true, - "optional": true - }, - "sass-embedded-android-arm64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.77.8.tgz", - "integrity": "sha512-EmWHLbEx0Zo/f/lTFzMeH2Du+/I4RmSRlEnERSUKQWVp3aBSO04QDvdxfFezgQ+2Yt/ub9WMqBpma9P/8MPsLg==", - "dev": true, - "optional": true - }, - "sass-embedded-android-ia32": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.77.8.tgz", - "integrity": "sha512-+GjfJ3lDezPi4dUUyjQBxlNKXNa+XVWsExtGvVNkv1uKyaOxULJhubVo2G6QTJJU0esJdfeXf5Ca5/J0ph7+7w==", - "dev": true, - "optional": true - }, - "sass-embedded-android-x64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.77.8.tgz", - "integrity": "sha512-YZbFDzGe5NhaMCygShqkeCWtzjhkWxGVunc7ULR97wmxYPQLPeVyx7XFQZc84Aj0lKAJBJS4qRZeqphMqZEJsQ==", - "dev": true, - "optional": true - }, - "sass-embedded-darwin-arm64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.77.8.tgz", - "integrity": "sha512-aifgeVRNE+i43toIkDFFJc/aPLMo0PJ5s5hKb52U+oNdiJE36n65n2L8F/8z3zZRvCa6eYtFY2b7f1QXR3B0LA==", - "dev": true, - "optional": true - }, - "sass-embedded-darwin-x64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.77.8.tgz", - "integrity": "sha512-/VWZQtcWIOek60Zj6Sxk6HebXA1Qyyt3sD8o5qwbTgZnKitB1iEBuNunyGoAgMNeUz2PRd6rVki6hvbas9hQ6w==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-arm": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.77.8.tgz", - "integrity": "sha512-2edZMB6jf0whx3T0zlgH+p131kOEmWp+I4wnKj7ZMUeokiY4Up05d10hSvb0Q63lOrSjFAWu6P5/pcYUUx8arQ==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-arm64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.77.8.tgz", - "integrity": "sha512-6iIOIZtBFa2YfMsHqOb3qake3C9d/zlKxjooKKnTSo+6g6z+CLTzMXe1bOfayb7yxeenElmFoK1k54kWD/40+g==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-ia32": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.77.8.tgz", - "integrity": "sha512-63GsFFHWN5yRLTWiSef32TM/XmjhCBx1DFhoqxmj+Yc6L9Z1h0lDHjjwdG6Sp5XTz5EmsaFKjpDgnQTP9hJX3Q==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-musl-arm": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.77.8.tgz", - "integrity": "sha512-nFkhSl3uu9btubm+JBW7uRglNVJ8W8dGfzVqh3fyQJKS1oyBC3vT3VOtfbT9YivXk28wXscSHpqXZwY7bUuopA==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-musl-arm64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.77.8.tgz", - "integrity": "sha512-j8cgQxNWecYK+aH8ESFsyam/Q6G+9gg8eJegiRVpA9x8yk3ykfHC7UdQWwUcF22ZcuY4zegrjJx8k+thsgsOVA==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-musl-ia32": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.77.8.tgz", - "integrity": "sha512-oWveMe+8TFlP8WBWPna/+Ec5TV0CE+PxEutyi0ltSruBds2zxRq9dPVOqrpPcDN9QUx50vNZC0Afgch0aQEd0g==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-musl-x64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.77.8.tgz", - "integrity": "sha512-2NtRpMXHeFo9kaYxuZ+Ewwo39CE7BTS2JDfXkTjZTZqd8H+8KC53eBh516YQnn2oiqxSiKxm7a6pxbxGZGwXOQ==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-x64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.77.8.tgz", - "integrity": "sha512-ND5qZLWUCpOn7LJfOf0gLSZUWhNIysY+7NZK1Ctq+pM6tpJky3JM5I1jSMplNxv5H3o8p80n0gSm+fcjsEFfjQ==", - "dev": true, - "optional": true - }, - "sass-embedded-win32-arm64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.77.8.tgz", - "integrity": "sha512-7L8zT6xzEvTYj86MvUWnbkWYCNQP+74HvruLILmiPPE+TCgOjgdi750709BtppVJGGZSs40ZuN6mi/YQyGtwXg==", - "dev": true, - "optional": true - }, - "sass-embedded-win32-ia32": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.77.8.tgz", - "integrity": "sha512-7Buh+4bP0WyYn6XPbthkIa3M2vtcR8QIsFVg3JElVlr+8Ng19jqe0t0SwggDgbMX6AdQZC+Wj4F1BprZSok42A==", - "dev": true, - "optional": true - }, - "sass-embedded-win32-x64": { - "version": "1.77.8", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.77.8.tgz", - "integrity": "sha512-rZmLIx4/LLQm+4GW39sRJW0MIlDqmyV0fkRzTmhFP5i/wVC7cuj8TUubPHw18rv2rkHFfBZKZJTCkPjCS5Z+SA==", - "dev": true, - "optional": true - }, - "scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "requires": { - "loose-envify": "^1.1.0" - } - }, - "screenfull": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", - "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==" - }, - "scroll-into-view-if-needed": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", - "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", - "requires": { - "compute-scroll-into-view": "^3.0.2" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - }, - "set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "requires": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "requires": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - } - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true - }, - "space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==" - }, - "string-convert": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", - "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - } - } - }, - "stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "requires": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "dependencies": { - "character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==" - } - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "style-mod": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", - "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" - }, - "style-to-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.7.tgz", - "integrity": "sha512-uSjr59G5u6fbxUfKbb8GcqMGT3Xs9v5IbPkjb0S16GyOeBLAzSRK0CixBv5YrYvzO6TDLzIS6QCn78tkqWngPw==", - "requires": { - "inline-style-parser": "0.2.3" - } - }, - "stylis": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz", - "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==" - }, - "sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "tailwindcss": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz", - "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==", - "dev": true, - "requires": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "throttle-debounce": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", - "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==" - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" - }, - "trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==" - }, - "trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==" - }, - "true-myth": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/true-myth/-/true-myth-4.1.1.tgz", - "integrity": "sha512-rqy30BSpxPznbbTcAcci90oZ1YR4DqvKcNXNerG5gQBU2v4jk0cygheiul5J6ExIMrgDVuanv/MkGfqZbKrNNg==", - "dev": true - }, - "ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "requires": {} - }, - "ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true - }, - "ts-morph": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-13.0.3.tgz", - "integrity": "sha512-pSOfUMx8Ld/WUreoSzvMFQG5i9uEiWIsBYjpU9+TTASOeUa89j5HykomeqVULm1oqWtBdleI3KEFRLrlA3zGIw==", - "dev": true, - "requires": { - "@ts-morph/common": "~0.12.3", - "code-block-writer": "^11.0.0" - } - }, - "ts-prune": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/ts-prune/-/ts-prune-0.10.3.tgz", - "integrity": "sha512-iS47YTbdIcvN8Nh/1BFyziyUqmjXz7GVzWu02RaZXqb+e/3Qe1B7IQ4860krOeCGUeJmterAlaM2FRH0Ue0hjw==", - "dev": true, - "requires": { - "commander": "^6.2.1", - "cosmiconfig": "^7.0.1", - "json5": "^2.1.3", - "lodash": "^4.17.21", - "true-myth": "^4.1.0", - "ts-morph": "^13.0.1" - }, - "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - } - } - }, - "tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "devOptional": true - }, - "typescript-eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz", - "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==", - "dev": true, - "requires": { - "@typescript-eslint/eslint-plugin": "8.3.0", - "@typescript-eslint/parser": "8.3.0", - "@typescript-eslint/utils": "8.3.0" - } - }, - "undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true - }, - "unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", - "requires": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" - } - }, - "unist-util-find-after": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", - "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", - "requires": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - } - }, - "unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "requires": { - "@types/unist": "^3.0.0" - } - }, - "unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "requires": { - "@types/unist": "^3.0.0" - } - }, - "unist-util-remove-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", - "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", - "requires": { - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - } - }, - "unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "requires": { - "@types/unist": "^3.0.0" - } - }, - "unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "requires": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - } - }, - "unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "requires": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - } - }, - "update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, - "requires": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "use-sync-external-store": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", - "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", - "requires": {} - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true - }, - "vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "requires": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - } - }, - "vfile-location": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", - "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", - "requires": { - "@types/unist": "^3.0.0", - "vfile": "^6.0.0" - } - }, - "vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", - "requires": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - } - }, - "vite": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz", - "integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==", - "dev": true, - "requires": { - "esbuild": "^0.21.3", - "fsevents": "~2.3.3", - "postcss": "^8.4.41", - "rollup": "^4.20.0" - } - }, - "w3c-keyname": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" - }, - "web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - }, - "zustand": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz", - "integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==", - "requires": { - "use-sync-external-store": "1.2.2" - } - }, - "zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==" - } - } -} diff --git a/projects/web/package.json b/projects/web/package.json deleted file mode 100644 index c2044ac92008d457ad52e73199f994722d91deb9..0000000000000000000000000000000000000000 --- a/projects/web/package.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "name": "my-react-app", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite --host ", - "build": "tsc --noEmit && vite build", - "lint": "eslint .", - "preview": "vite preview" - }, - "dependencies": { - "@ant-design/icons": "^5.4.0", - "@codemirror/view": "^6.33.0", - "@tanstack/react-query": "^5.56.2", - "@types/lodash": "^4.17.7", - "@types/qs": "^6.9.15", - "@types/react-copy-to-clipboard": "^5.0.7", - "@types/react-syntax-highlighter": "^15.5.13", - "@uiw/codemirror-extensions-langs": "^4.23.0", - "@uiw/react-codemirror": "^4.23.0", - "ahooks": "^3.8.1", - "antd": "^5.20.3", - "axios": "^1.7.5", - "canvas": "^2.11.2", - "classnames": "^2.5.1", - "js-cookie": "^3.0.5", - "lodash": "^4.17.21", - "path2d": "^0.2.1", - "qs": "^6.13.0", - "react": "^18.3.1", - "react-copy-to-clipboard": "^5.1.0", - "react-dom": "^18.3.1", - "react-intl": "^6.6.8", - "react-markdown": "^9.0.1", - "react-query": "^3.39.3", - "react-router-dom": "^6.26.1", - "react-syntax-highlighter": "^15.5.0", - "rehype-katex": "^7.0.1", - "rehype-raw": "^7.0.0", - "remark-gfm": "^4.0.0", - "remark-math": "^6.0.0", - "zustand": "^4.5.5" - }, - "devDependencies": { - "@eslint/js": "^9.9.0", - "@types/js-cookie": "^3.0.6", - "@types/node": "^22.5.1", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.1", - "autoprefixer": "^10.4.20", - "eslint": "^9.9.0", - "eslint-plugin-react-hooks": "^5.1.0-rc.0", - "eslint-plugin-react-refresh": "^0.4.9", - "globals": "^15.9.0", - "less": "^4.2.0", - "postcss": "^8.4.41", - "sass-embedded": "^1.77.8", - "tailwindcss": "^3.4.10", - "ts-prune": "^0.10.3", - "typescript": "^5.5.3", - "typescript-eslint": "^8.0.1", - "vite": "^5.4.1" - } -} \ No newline at end of file diff --git a/projects/web/pnpm-lock.yaml b/projects/web/pnpm-lock.yaml deleted file mode 100644 index d84729b649a56c402f7d94c7a1fd6a86fe732f6c..0000000000000000000000000000000000000000 --- a/projects/web/pnpm-lock.yaml +++ /dev/null @@ -1,5951 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -dependencies: - '@ant-design/icons': - specifier: ^5.4.0 - version: 5.4.0(react-dom@18.3.1)(react@18.3.1) - '@codemirror/view': - specifier: ^6.33.0 - version: 6.33.0 - '@tanstack/react-query': - specifier: ^5.56.2 - version: 5.56.2(react@18.3.1) - '@types/lodash': - specifier: ^4.17.7 - version: 4.17.7 - '@types/qs': - specifier: ^6.9.15 - version: 6.9.15 - '@types/react-copy-to-clipboard': - specifier: ^5.0.7 - version: 5.0.7 - '@types/react-syntax-highlighter': - specifier: ^15.5.13 - version: 15.5.13 - '@uiw/codemirror-extensions-langs': - specifier: ^4.23.0 - version: 4.23.0(@codemirror/autocomplete@6.18.0)(@codemirror/language-data@6.5.1)(@codemirror/language@6.10.2)(@codemirror/legacy-modes@6.4.1)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1)(@lezer/highlight@1.2.1)(@lezer/javascript@1.4.17)(@lezer/lr@1.4.2) - '@uiw/react-codemirror': - specifier: ^4.23.0 - version: 4.23.0(@babel/runtime@7.25.6)(@codemirror/autocomplete@6.18.0)(@codemirror/language@6.10.2)(@codemirror/lint@6.8.1)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.33.0)(codemirror@6.0.1)(react-dom@18.3.1)(react@18.3.1) - ahooks: - specifier: ^3.8.1 - version: 3.8.1(react@18.3.1) - antd: - specifier: ^5.20.3 - version: 5.20.5(react-dom@18.3.1)(react@18.3.1) - axios: - specifier: ^1.7.5 - version: 1.7.7 - classnames: - specifier: ^2.5.1 - version: 2.5.1 - js-cookie: - specifier: ^3.0.5 - version: 3.0.5 - lodash: - specifier: ^4.17.21 - version: 4.17.21 - qs: - specifier: ^6.13.0 - version: 6.13.0 - react: - specifier: ^18.3.1 - version: 18.3.1 - react-copy-to-clipboard: - specifier: ^5.1.0 - version: 5.1.0(react@18.3.1) - react-dom: - specifier: ^18.3.1 - version: 18.3.1(react@18.3.1) - react-intl: - specifier: ^6.6.8 - version: 6.6.8(react@18.3.1)(typescript@5.5.4) - react-markdown: - specifier: ^9.0.1 - version: 9.0.1(@types/react@18.3.5)(react@18.3.1) - react-query: - specifier: ^3.39.3 - version: 3.39.3(react-dom@18.3.1)(react@18.3.1) - react-router-dom: - specifier: ^6.26.1 - version: 6.26.1(react-dom@18.3.1)(react@18.3.1) - react-syntax-highlighter: - specifier: ^15.5.0 - version: 15.5.0(react@18.3.1) - rehype-katex: - specifier: ^7.0.1 - version: 7.0.1 - rehype-raw: - specifier: ^7.0.0 - version: 7.0.0 - remark-gfm: - specifier: ^4.0.0 - version: 4.0.0 - remark-math: - specifier: ^6.0.0 - version: 6.0.0 - zustand: - specifier: ^4.5.5 - version: 4.5.5(@types/react@18.3.5)(react@18.3.1) - -devDependencies: - '@eslint/js': - specifier: ^9.9.0 - version: 9.9.1 - '@types/js-cookie': - specifier: ^3.0.6 - version: 3.0.6 - '@types/node': - specifier: ^22.5.1 - version: 22.5.4 - '@types/react': - specifier: ^18.3.3 - version: 18.3.5 - '@types/react-dom': - specifier: ^18.3.0 - version: 18.3.0 - '@vitejs/plugin-react': - specifier: ^4.3.1 - version: 4.3.1(vite@5.4.3) - autoprefixer: - specifier: ^10.4.20 - version: 10.4.20(postcss@8.4.45) - eslint: - specifier: ^9.9.0 - version: 9.9.1 - eslint-plugin-react-hooks: - specifier: ^5.1.0-rc.0 - version: 5.1.0-rc-fb9a90fa48-20240614(eslint@9.9.1) - eslint-plugin-react-refresh: - specifier: ^0.4.9 - version: 0.4.11(eslint@9.9.1) - globals: - specifier: ^15.9.0 - version: 15.9.0 - postcss: - specifier: ^8.4.41 - version: 8.4.45 - sass-embedded: - specifier: ^1.77.8 - version: 1.78.0 - tailwindcss: - specifier: ^3.4.10 - version: 3.4.10 - ts-prune: - specifier: ^0.10.3 - version: 0.10.3 - typescript: - specifier: ^5.5.3 - version: 5.5.4 - typescript-eslint: - specifier: ^8.0.1 - version: 8.4.0(eslint@9.9.1)(typescript@5.5.4) - vite: - specifier: ^5.4.1 - version: 5.4.3(@types/node@22.5.4)(sass-embedded@1.78.0) - -packages: - - /@alloc/quick-lru@5.2.0: - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - dev: true - - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@ant-design/colors@7.1.0: - resolution: {integrity: sha512-MMoDGWn1y9LdQJQSHiCC20x3uZ3CwQnv9QMz6pCmJOrqdgM9YxsoVVY0wtrdXbmfSgnV0KNk6zi09NAhMR2jvg==} - dependencies: - '@ctrl/tinycolor': 3.6.1 - dev: false - - /@ant-design/cssinjs-utils@1.0.3(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-BrztZZKuoYcJK8uEH40ylBemf/Mu/QPiDos56g2bv6eUoniQkgQHOCOvA3+pncoFO1TaS8xcUCIqGzDA0I+ZVQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@ant-design/cssinjs': 1.21.1(react-dom@18.3.1)(react@18.3.1) - '@babel/runtime': 7.25.6 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@ant-design/cssinjs@1.21.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-tyWnlK+XH7Bumd0byfbCiZNK43HEubMoCcu9VxwsAwiHdHTgWa+tMN0/yvxa+e8EzuFP1WdUNNPclRpVtD33lg==} - peerDependencies: - react: '>=16.0.0' - react-dom: '>=16.0.0' - dependencies: - '@babel/runtime': 7.25.6 - '@emotion/hash': 0.8.0 - '@emotion/unitless': 0.7.5 - classnames: 2.5.1 - csstype: 3.1.3 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - stylis: 4.3.4 - dev: false - - /@ant-design/fast-color@2.0.6: - resolution: {integrity: sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==} - engines: {node: '>=8.x'} - dependencies: - '@babel/runtime': 7.25.6 - dev: false - - /@ant-design/icons-svg@4.4.2: - resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==} - dev: false - - /@ant-design/icons@5.4.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-QZbWC5xQYexCI5q4/fehSEkchJr5UGtvAJweT743qKUQQGs9IH2DehNLP49DJ3Ii9m9CijD2HN6fNy3WKhIFdA==} - engines: {node: '>=8'} - peerDependencies: - react: '>=16.0.0' - react-dom: '>=16.0.0' - dependencies: - '@ant-design/colors': 7.1.0 - '@ant-design/icons-svg': 4.4.2 - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@ant-design/react-slick@1.1.2(react@18.3.1): - resolution: {integrity: sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==} - peerDependencies: - react: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - json2mq: 0.2.0 - react: 18.3.1 - resize-observer-polyfill: 1.5.1 - throttle-debounce: 5.0.2 - dev: false - - /@babel/code-frame@7.24.7: - resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.7 - picocolors: 1.1.0 - dev: true - - /@babel/compat-data@7.25.4: - resolution: {integrity: sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.25.2: - resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.6 - '@babel/helper-compilation-targets': 7.25.2 - '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) - '@babel/helpers': 7.25.6 - '@babel/parser': 7.25.6 - '@babel/template': 7.25.0 - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 - convert-source-map: 2.0.0 - debug: 4.3.6 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/generator@7.25.6: - resolution: {integrity: sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.25.6 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - - /@babel/helper-compilation-targets@7.25.2: - resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.25.4 - '@babel/helper-validator-option': 7.24.8 - browserslist: 4.23.3 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-module-imports@7.24.7: - resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-module-transforms@7.25.2(@babel/core@7.25.2): - resolution: {integrity: sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - '@babel/traverse': 7.25.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-plugin-utils@7.24.8: - resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-simple-access@7.24.7: - resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-string-parser@7.24.8: - resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.24.7: - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.24.8: - resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers@7.25.6: - resolution: {integrity: sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.25.0 - '@babel/types': 7.25.6 - dev: true - - /@babel/highlight@7.24.7: - resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.24.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.1.0 - dev: true - - /@babel/parser@7.25.6: - resolution: {integrity: sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.25.6 - dev: true - - /@babel/plugin-transform-react-jsx-self@7.24.7(@babel/core@7.25.2): - resolution: {integrity: sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - dev: true - - /@babel/plugin-transform-react-jsx-source@7.24.7(@babel/core@7.25.2): - resolution: {integrity: sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - dev: true - - /@babel/runtime@7.25.6: - resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - dev: false - - /@babel/template@7.25.0: - resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 - dev: true - - /@babel/traverse@7.25.6: - resolution: {integrity: sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.6 - '@babel/parser': 7.25.6 - '@babel/template': 7.25.0 - '@babel/types': 7.25.6 - debug: 4.3.6 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.25.6: - resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.8 - '@babel/helper-validator-identifier': 7.24.7 - to-fast-properties: 2.0.0 - dev: true - - /@bufbuild/protobuf@1.10.0: - resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} - dev: true - - /@codemirror/autocomplete@6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1): - resolution: {integrity: sha512-5DbOvBbY4qW5l57cjDsmmpDh3/TeK1vXfTHa+BUMrRzdWdcxKZ4U4V7vQaTtOpApNU4kLS4FQ6cINtLg245LXA==} - peerDependencies: - '@codemirror/language': ^6.0.0 - '@codemirror/state': ^6.0.0 - '@codemirror/view': ^6.0.0 - '@lezer/common': ^1.0.0 - dependencies: - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - dev: false - - /@codemirror/commands@6.6.1: - resolution: {integrity: sha512-iBfKbyIoXS1FGdsKcZmnrxmbc8VcbMrSgD7AVrsnX+WyAYjmUDWvE93dt5D874qS4CCVu4O1JpbagHdXbbLiOw==} - dependencies: - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - dev: false - - /@codemirror/lang-angular@0.1.3: - resolution: {integrity: sha512-xgeWGJQQl1LyStvndWtruUvb4SnBZDAu/gvFH/ZU+c0W25tQR8e5hq7WTwiIY2dNxnf+49mRiGI/9yxIwB6f5w==} - dependencies: - '@codemirror/lang-html': 6.4.9 - '@codemirror/lang-javascript': 6.2.2 - '@codemirror/language': 6.10.2 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@codemirror/lang-cpp@6.0.2: - resolution: {integrity: sha512-6oYEYUKHvrnacXxWxYa6t4puTlbN3dgV662BDfSH8+MfjQjVmP697/KYTDOqpxgerkvoNm7q5wlFMBeX8ZMocg==} - dependencies: - '@codemirror/language': 6.10.2 - '@lezer/cpp': 1.1.2 - dev: false - - /@codemirror/lang-css@6.2.1(@codemirror/view@6.33.0): - resolution: {integrity: sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@lezer/common': 1.2.1 - '@lezer/css': 1.1.8 - transitivePeerDependencies: - - '@codemirror/view' - dev: false - - /@codemirror/lang-go@6.0.1(@codemirror/view@6.33.0): - resolution: {integrity: sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@lezer/common': 1.2.1 - '@lezer/go': 1.0.0 - transitivePeerDependencies: - - '@codemirror/view' - dev: false - - /@codemirror/lang-html@6.4.9: - resolution: {integrity: sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/lang-css': 6.2.1(@codemirror/view@6.33.0) - '@codemirror/lang-javascript': 6.2.2 - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - '@lezer/css': 1.1.8 - '@lezer/html': 1.3.10 - dev: false - - /@codemirror/lang-java@6.0.1: - resolution: {integrity: sha512-OOnmhH67h97jHzCuFaIEspbmsT98fNdhVhmA3zCxW0cn7l8rChDhZtwiwJ/JOKXgfm4J+ELxQihxaI7bj7mJRg==} - dependencies: - '@codemirror/language': 6.10.2 - '@lezer/java': 1.1.2 - dev: false - - /@codemirror/lang-javascript@6.2.2: - resolution: {integrity: sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/lint': 6.8.1 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - '@lezer/javascript': 1.4.17 - dev: false - - /@codemirror/lang-json@6.0.1: - resolution: {integrity: sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==} - dependencies: - '@codemirror/language': 6.10.2 - '@lezer/json': 1.0.2 - dev: false - - /@codemirror/lang-less@6.0.2(@codemirror/view@6.33.0): - resolution: {integrity: sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==} - dependencies: - '@codemirror/lang-css': 6.2.1(@codemirror/view@6.33.0) - '@codemirror/language': 6.10.2 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - transitivePeerDependencies: - - '@codemirror/view' - dev: false - - /@codemirror/lang-lezer@6.0.1: - resolution: {integrity: sha512-WHwjI7OqKFBEfkunohweqA5B/jIlxaZso6Nl3weVckz8EafYbPZldQEKSDb4QQ9H9BUkle4PVELP4sftKoA0uQ==} - dependencies: - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@lezer/common': 1.2.1 - '@lezer/lezer': 1.1.2 - dev: false - - /@codemirror/lang-liquid@6.2.1: - resolution: {integrity: sha512-J1Mratcm6JLNEiX+U2OlCDTysGuwbHD76XwuL5o5bo9soJtSbz2g6RU3vGHFyS5DC8rgVmFSzi7i6oBftm7tnA==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/lang-html': 6.4.9 - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@codemirror/lang-markdown@6.2.5: - resolution: {integrity: sha512-Hgke565YcO4fd9pe2uLYxnMufHO5rQwRr+AAhFq8ABuhkrjyX8R5p5s+hZUTdV60O0dMRjxKhBLxz8pu/MkUVA==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/lang-html': 6.4.9 - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - '@lezer/markdown': 1.3.1 - dev: false - - /@codemirror/lang-php@6.0.1: - resolution: {integrity: sha512-ublojMdw/PNWa7qdN5TMsjmqkNuTBD3k6ndZ4Z0S25SBAiweFGyY68AS3xNcIOlb6DDFDvKlinLQ40vSLqf8xA==} - dependencies: - '@codemirror/lang-html': 6.4.9 - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@lezer/common': 1.2.1 - '@lezer/php': 1.0.2 - dev: false - - /@codemirror/lang-python@6.1.6(@codemirror/view@6.33.0): - resolution: {integrity: sha512-ai+01WfZhWqM92UqjnvorkxosZ2aq2u28kHvr+N3gu012XqY2CThD67JPMHnGceRfXPDBmn1HnyqowdpF57bNg==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@lezer/common': 1.2.1 - '@lezer/python': 1.1.14 - transitivePeerDependencies: - - '@codemirror/view' - dev: false - - /@codemirror/lang-rust@6.0.1: - resolution: {integrity: sha512-344EMWFBzWArHWdZn/NcgkwMvZIWUR1GEBdwG8FEp++6o6vT6KL9V7vGs2ONsKxxFUPXKI0SPcWhyYyl2zPYxQ==} - dependencies: - '@codemirror/language': 6.10.2 - '@lezer/rust': 1.0.2 - dev: false - - /@codemirror/lang-sass@6.0.2(@codemirror/view@6.33.0): - resolution: {integrity: sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==} - dependencies: - '@codemirror/lang-css': 6.2.1(@codemirror/view@6.33.0) - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@lezer/common': 1.2.1 - '@lezer/sass': 1.0.6 - transitivePeerDependencies: - - '@codemirror/view' - dev: false - - /@codemirror/lang-sql@6.7.1(@codemirror/view@6.33.0): - resolution: {integrity: sha512-flQa7zemrLKk0TIrOJnpeyH/b29BcVybtsTeZMgAo40O6kGbrnUSCgwI3TF5iJY3O9VXJKKCA+i0CBVvDfr88w==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - transitivePeerDependencies: - - '@codemirror/view' - dev: false - - /@codemirror/lang-vue@0.1.3: - resolution: {integrity: sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==} - dependencies: - '@codemirror/lang-html': 6.4.9 - '@codemirror/lang-javascript': 6.2.2 - '@codemirror/language': 6.10.2 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@codemirror/lang-wast@6.0.2: - resolution: {integrity: sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==} - dependencies: - '@codemirror/language': 6.10.2 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@codemirror/lang-xml@6.1.0: - resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - '@lezer/xml': 1.0.5 - dev: false - - /@codemirror/lang-yaml@6.1.1(@codemirror/view@6.33.0): - resolution: {integrity: sha512-HV2NzbK9bbVnjWxwObuZh5FuPCowx51mEfoFT9y3y+M37fA3+pbxx4I7uePuygFzDsAmCTwQSc/kXh/flab4uw==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/yaml': 1.0.3 - transitivePeerDependencies: - - '@codemirror/view' - dev: false - - /@codemirror/language-data@6.5.1(@codemirror/view@6.33.0): - resolution: {integrity: sha512-0sWxeUSNlBr6OmkqybUTImADFUP0M3P0IiSde4nc24bz/6jIYzqYSgkOSLS+CBIoW1vU8Q9KUWXscBXeoMVC9w==} - dependencies: - '@codemirror/lang-angular': 0.1.3 - '@codemirror/lang-cpp': 6.0.2 - '@codemirror/lang-css': 6.2.1(@codemirror/view@6.33.0) - '@codemirror/lang-go': 6.0.1(@codemirror/view@6.33.0) - '@codemirror/lang-html': 6.4.9 - '@codemirror/lang-java': 6.0.1 - '@codemirror/lang-javascript': 6.2.2 - '@codemirror/lang-json': 6.0.1 - '@codemirror/lang-less': 6.0.2(@codemirror/view@6.33.0) - '@codemirror/lang-liquid': 6.2.1 - '@codemirror/lang-markdown': 6.2.5 - '@codemirror/lang-php': 6.0.1 - '@codemirror/lang-python': 6.1.6(@codemirror/view@6.33.0) - '@codemirror/lang-rust': 6.0.1 - '@codemirror/lang-sass': 6.0.2(@codemirror/view@6.33.0) - '@codemirror/lang-sql': 6.7.1(@codemirror/view@6.33.0) - '@codemirror/lang-vue': 0.1.3 - '@codemirror/lang-wast': 6.0.2 - '@codemirror/lang-xml': 6.1.0 - '@codemirror/lang-yaml': 6.1.1(@codemirror/view@6.33.0) - '@codemirror/language': 6.10.2 - '@codemirror/legacy-modes': 6.4.1 - transitivePeerDependencies: - - '@codemirror/view' - dev: false - - /@codemirror/language@6.10.2: - resolution: {integrity: sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==} - dependencies: - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - style-mod: 4.1.2 - dev: false - - /@codemirror/legacy-modes@6.4.1: - resolution: {integrity: sha512-vdg3XY7OAs5uLDx2Iw+cGfnwtd7kM+Et/eMsqAGTfT/JKiVBQZXosTzjEbWAi/FrY6DcQIz8mQjBozFHZEUWQA==} - dependencies: - '@codemirror/language': 6.10.2 - dev: false - - /@codemirror/lint@6.8.1: - resolution: {integrity: sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==} - dependencies: - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - crelt: 1.0.6 - dev: false - - /@codemirror/search@6.5.6: - resolution: {integrity: sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==} - dependencies: - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - crelt: 1.0.6 - dev: false - - /@codemirror/state@6.4.1: - resolution: {integrity: sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==} - dev: false - - /@codemirror/theme-one-dark@6.1.2: - resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==} - dependencies: - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/highlight': 1.2.1 - dev: false - - /@codemirror/view@6.33.0: - resolution: {integrity: sha512-AroaR3BvnjRW8fiZBalAaK+ZzB5usGgI014YKElYZvQdNH5ZIidHlO+cyf/2rWzyBFRkvG6VhiXeAEbC53P2YQ==} - dependencies: - '@codemirror/state': 6.4.1 - style-mod: 4.1.2 - w3c-keyname: 2.2.8 - dev: false - - /@ctrl/tinycolor@3.6.1: - resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} - engines: {node: '>=10'} - dev: false - - /@emotion/hash@0.8.0: - resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} - dev: false - - /@emotion/unitless@0.7.5: - resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} - dev: false - - /@esbuild/aix-ppc64@0.21.5: - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64@0.21.5: - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.21.5: - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.21.5: - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.21.5: - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.21.5: - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.21.5: - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.21.5: - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.21.5: - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.21.5: - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.21.5: - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.21.5: - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.21.5: - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.21.5: - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.21.5: - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.21.5: - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.21.5: - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.21.5: - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.21.5: - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.21.5: - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.21.5: - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.21.5: - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.21.5: - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@eslint-community/eslint-utils@4.4.0(eslint@9.9.1): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 9.9.1 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.11.0: - resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/config-array@0.18.0: - resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@eslint/object-schema': 2.1.4 - debug: 4.3.6 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/eslintrc@3.1.0: - resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.6 - espree: 10.1.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@9.9.1: - resolution: {integrity: sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /@eslint/object-schema@2.1.4: - resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /@formatjs/ecma402-abstract@2.0.0: - resolution: {integrity: sha512-rRqXOqdFmk7RYvj4khklyqzcfQl9vEL/usogncBHRZfZBDOwMGuSRNFl02fu5KGHXdbinju+YXyuR+Nk8xlr/g==} - dependencies: - '@formatjs/intl-localematcher': 0.5.4 - tslib: 2.7.0 - dev: false - - /@formatjs/fast-memoize@2.2.0: - resolution: {integrity: sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==} - dependencies: - tslib: 2.7.0 - dev: false - - /@formatjs/icu-messageformat-parser@2.7.8: - resolution: {integrity: sha512-nBZJYmhpcSX0WeJ5SDYUkZ42AgR3xiyhNCsQweFx3cz/ULJjym8bHAzWKvG5e2+1XO98dBYC0fWeeAECAVSwLA==} - dependencies: - '@formatjs/ecma402-abstract': 2.0.0 - '@formatjs/icu-skeleton-parser': 1.8.2 - tslib: 2.7.0 - dev: false - - /@formatjs/icu-skeleton-parser@1.8.2: - resolution: {integrity: sha512-k4ERKgw7aKGWJZgTarIcNEmvyTVD9FYh0mTrrBMHZ1b8hUu6iOJ4SzsZlo3UNAvHYa+PnvntIwRPt1/vy4nA9Q==} - dependencies: - '@formatjs/ecma402-abstract': 2.0.0 - tslib: 2.7.0 - dev: false - - /@formatjs/intl-displaynames@6.6.8: - resolution: {integrity: sha512-Lgx6n5KxN16B3Pb05z3NLEBQkGoXnGjkTBNCZI+Cn17YjHJ3fhCeEJJUqRlIZmJdmaXQhjcQVDp6WIiNeRYT5g==} - dependencies: - '@formatjs/ecma402-abstract': 2.0.0 - '@formatjs/intl-localematcher': 0.5.4 - tslib: 2.7.0 - dev: false - - /@formatjs/intl-listformat@7.5.7: - resolution: {integrity: sha512-MG2TSChQJQT9f7Rlv+eXwUFiG24mKSzmF144PLb8m8OixyXqn4+YWU+5wZracZGCgVTVmx8viCf7IH3QXoiB2g==} - dependencies: - '@formatjs/ecma402-abstract': 2.0.0 - '@formatjs/intl-localematcher': 0.5.4 - tslib: 2.7.0 - dev: false - - /@formatjs/intl-localematcher@0.5.4: - resolution: {integrity: sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==} - dependencies: - tslib: 2.7.0 - dev: false - - /@formatjs/intl@2.10.4(typescript@5.5.4): - resolution: {integrity: sha512-56483O+HVcL0c7VucAS2tyH020mt9XTozZO67cwtGg0a7KWDukS/FzW3OnvaHmTHDuYsoPIzO+ZHVfU6fT/bJw==} - peerDependencies: - typescript: ^4.7 || 5 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@formatjs/ecma402-abstract': 2.0.0 - '@formatjs/fast-memoize': 2.2.0 - '@formatjs/icu-messageformat-parser': 2.7.8 - '@formatjs/intl-displaynames': 6.6.8 - '@formatjs/intl-listformat': 7.5.7 - intl-messageformat: 10.5.14 - tslib: 2.7.0 - typescript: 5.5.4 - dev: false - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/retry@0.3.0: - resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} - engines: {node: '>=18.18'} - dev: true - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/sourcemap-codec@1.5.0: - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - dev: true - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - dev: true - - /@lezer/common@1.2.1: - resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==} - dev: false - - /@lezer/cpp@1.1.2: - resolution: {integrity: sha512-macwKtyeUO0EW86r3xWQCzOV9/CF8imJLpJlPv3sDY57cPGeUZ8gXWOWNlJr52TVByMV3PayFQCA5SHEERDmVQ==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/css@1.1.8: - resolution: {integrity: sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/go@1.0.0: - resolution: {integrity: sha512-co9JfT3QqX1YkrMmourYw2Z8meGC50Ko4d54QEcQbEYpvdUvN4yb0NBZdn/9ertgvjsySxHsKzH3lbm3vqJ4Jw==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/highlight@1.2.1: - resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==} - dependencies: - '@lezer/common': 1.2.1 - dev: false - - /@lezer/html@1.3.10: - resolution: {integrity: sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/java@1.1.2: - resolution: {integrity: sha512-3j8X70JvYf0BZt8iSRLXLkt0Ry1hVUgH6wT32yBxH/Xi55nW2VMhc1Az4SKwu4YGSmxCm1fsqDDcHTuFjC8pmg==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/javascript@1.4.17: - resolution: {integrity: sha512-bYW4ctpyGK+JMumDApeUzuIezX01H76R1foD6LcRX224FWfyYit/HYxiPGDjXXe/wQWASjCvVGoukTH68+0HIA==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/json@1.0.2: - resolution: {integrity: sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/lezer@1.1.2: - resolution: {integrity: sha512-O8yw3CxPhzYHB1hvwbdozjnAslhhR8A5BH7vfEMof0xk3p+/DFDfZkA9Tde6J+88WgtwaHy4Sy6ThZSkaI0Evw==} - dependencies: - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/lr@1.4.2: - resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==} - dependencies: - '@lezer/common': 1.2.1 - dev: false - - /@lezer/markdown@1.3.1: - resolution: {integrity: sha512-DGlzU/i8DC8k0uz1F+jeePrkATl0jWakauTzftMQOcbaMkHbNSRki/4E2tOzJWsVpoKYhe7iTJ03aepdwVUXUA==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - dev: false - - /@lezer/php@1.0.2: - resolution: {integrity: sha512-GN7BnqtGRpFyeoKSEqxvGvhJQiI4zkgmYnDk/JIyc7H7Ifc1tkPnUn/R2R8meH3h/aBf5rzjvU8ZQoyiNDtDrA==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/python@1.1.14: - resolution: {integrity: sha512-ykDOb2Ti24n76PJsSa4ZoDF0zH12BSw1LGfQXCYJhJyOGiFTfGaX0Du66Ze72R+u/P35U+O6I9m8TFXov1JzsA==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/rust@1.0.2: - resolution: {integrity: sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/sass@1.0.6: - resolution: {integrity: sha512-w/RCO2dIzZH1To8p+xjs8cE+yfgGus8NZ/dXeWl/QzHyr+TeBs71qiE70KPImEwvTsmEjoWh0A5SxMzKd5BWBQ==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/xml@1.0.5: - resolution: {integrity: sha512-VFouqOzmUWfIg+tfmpcdV33ewtK+NSwd4ngSe1aG7HFb4BN0ExyY1b8msp+ndFrnlG4V4iC8yXacjFtrwERnaw==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@lezer/yaml@1.0.3: - resolution: {integrity: sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==} - dependencies: - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@nextjournal/lang-clojure@1.0.0: - resolution: {integrity: sha512-gOCV71XrYD0DhwGoPMWZmZ0r92/lIHsqQu9QWdpZYYBwiChNwMO4sbVMP7eTuAqffFB2BTtCSC+1skSH9d3bNg==} - dependencies: - '@codemirror/language': 6.10.2 - '@nextjournal/lezer-clojure': 1.0.0 - dev: false - - /@nextjournal/lezer-clojure@1.0.0: - resolution: {integrity: sha512-VZyuGu4zw5mkTOwQBTaGVNWmsOZAPw5ZRxu1/Knk/Xfs7EDBIogwIs5UXTYkuECX5ZQB8eOB+wKA2pc7VyqaZQ==} - dependencies: - '@lezer/lr': 1.4.2 - dev: false - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - dev: true - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - - /@rc-component/async-validator@5.0.4: - resolution: {integrity: sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==} - engines: {node: '>=14.x'} - dependencies: - '@babel/runtime': 7.25.6 - dev: false - - /@rc-component/color-picker@2.0.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@ant-design/fast-color': 2.0.6 - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@rc-component/context@1.4.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@rc-component/mini-decimal@1.1.0: - resolution: {integrity: sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==} - engines: {node: '>=8.x'} - dependencies: - '@babel/runtime': 7.25.6 - dev: false - - /@rc-component/mutate-observer@1.1.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@rc-component/portal@1.1.2(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@rc-component/qrcode@1.0.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@rc-component/tour@1.15.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/portal': 1.1.2(react-dom@18.3.1)(react@18.3.1) - '@rc-component/trigger': 2.2.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@rc-component/trigger@2.2.2(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-xDyi0fJ3IV6XJEReMOewS9PEnnuLHKz4rjbgIniDsJFHjL5nROuUlu64mfo90jglLDkQUxRwK7aTtumA65/zYQ==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/portal': 1.1.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@remix-run/router@1.19.1: - resolution: {integrity: sha512-S45oynt/WH19bHbIXjtli6QmwNYvaz+vtnubvNpNDvUOoA/OWh6j1OikIP3G+v5GHdxyC6EXoChG3HgYGEUfcg==} - engines: {node: '>=14.0.0'} - dev: false - - /@replit/codemirror-lang-csharp@6.2.0(@codemirror/autocomplete@6.18.0)(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1)(@lezer/highlight@1.2.1)(@lezer/lr@1.4.2): - resolution: {integrity: sha512-6utbaWkoymhoAXj051mkRp+VIJlpwUgCX9Toevz3YatiZsz512fw3OVCedXQx+WcR0wb6zVHjChnuxqfCLtFVQ==} - peerDependencies: - '@codemirror/autocomplete': ^6.0.0 - '@codemirror/language': ^6.0.0 - '@codemirror/state': ^6.0.0 - '@codemirror/view': ^6.0.0 - '@lezer/common': ^1.0.0 - '@lezer/highlight': ^1.0.0 - '@lezer/lr': ^1.0.0 - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@replit/codemirror-lang-nix@6.0.1(@codemirror/autocomplete@6.18.0)(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1)(@lezer/highlight@1.2.1)(@lezer/lr@1.4.2): - resolution: {integrity: sha512-lvzjoYn9nfJzBD5qdm3Ut6G3+Or2wEacYIDJ49h9+19WSChVnxv4ojf+rNmQ78ncuxIt/bfbMvDLMeMP0xze6g==} - peerDependencies: - '@codemirror/autocomplete': ^6.0.0 - '@codemirror/language': ^6.0.0 - '@codemirror/state': ^6.0.0 - '@codemirror/view': ^6.0.0 - '@lezer/common': ^1.0.0 - '@lezer/highlight': ^1.0.0 - '@lezer/lr': ^1.0.0 - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /@replit/codemirror-lang-solidity@6.0.2(@codemirror/language@6.10.2): - resolution: {integrity: sha512-/dpTVH338KFV6SaDYYSadkB4bI/0B0QRF/bkt1XS3t3QtyR49mn6+2k0OUQhvt2ZSO7kt10J+OPilRAtgbmX0w==} - peerDependencies: - '@codemirror/language': ^6.0.0 - dependencies: - '@codemirror/language': 6.10.2 - '@lezer/highlight': 1.2.1 - dev: false - - /@replit/codemirror-lang-svelte@6.0.0(@codemirror/autocomplete@6.18.0)(@codemirror/lang-css@6.2.1)(@codemirror/lang-html@6.4.9)(@codemirror/lang-javascript@6.2.2)(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1)(@lezer/highlight@1.2.1)(@lezer/javascript@1.4.17)(@lezer/lr@1.4.2): - resolution: {integrity: sha512-U2OqqgMM6jKelL0GNWbAmqlu1S078zZNoBqlJBW+retTc5M4Mha6/Y2cf4SVg6ddgloJvmcSpt4hHrVoM4ePRA==} - peerDependencies: - '@codemirror/autocomplete': ^6.0.0 - '@codemirror/lang-css': ^6.0.1 - '@codemirror/lang-html': ^6.2.0 - '@codemirror/lang-javascript': ^6.1.1 - '@codemirror/language': ^6.0.0 - '@codemirror/state': ^6.0.0 - '@codemirror/view': ^6.0.0 - '@lezer/common': ^1.0.0 - '@lezer/highlight': ^1.0.0 - '@lezer/javascript': ^1.2.0 - '@lezer/lr': ^1.0.0 - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/lang-css': 6.2.1(@codemirror/view@6.33.0) - '@codemirror/lang-html': 6.4.9 - '@codemirror/lang-javascript': 6.2.2 - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - '@lezer/common': 1.2.1 - '@lezer/highlight': 1.2.1 - '@lezer/javascript': 1.4.17 - '@lezer/lr': 1.4.2 - dev: false - - /@rollup/rollup-android-arm-eabi@4.21.2: - resolution: {integrity: sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm64@4.21.2: - resolution: {integrity: sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-arm64@4.21.2: - resolution: {integrity: sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-x64@4.21.2: - resolution: {integrity: sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.21.2: - resolution: {integrity: sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-musleabihf@4.21.2: - resolution: {integrity: sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.21.2: - resolution: {integrity: sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.21.2: - resolution: {integrity: sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-powerpc64le-gnu@4.21.2: - resolution: {integrity: sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-riscv64-gnu@4.21.2: - resolution: {integrity: sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-s390x-gnu@4.21.2: - resolution: {integrity: sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.21.2: - resolution: {integrity: sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.21.2: - resolution: {integrity: sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.21.2: - resolution: {integrity: sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.21.2: - resolution: {integrity: sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.21.2: - resolution: {integrity: sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@tanstack/query-core@5.56.2: - resolution: {integrity: sha512-gor0RI3/R5rVV3gXfddh1MM+hgl0Z4G7tj6Xxpq6p2I03NGPaJ8dITY9Gz05zYYb/EJq9vPas/T4wn9EaDPd4Q==} - dev: false - - /@tanstack/react-query@5.56.2(react@18.3.1): - resolution: {integrity: sha512-SR0GzHVo6yzhN72pnRhkEFRAHMsUo5ZPzAxfTMvUxFIDVS6W9LYUp6nXW3fcHVdg0ZJl8opSH85jqahvm6DSVg==} - peerDependencies: - react: ^18 || ^19 - dependencies: - '@tanstack/query-core': 5.56.2 - react: 18.3.1 - dev: false - - /@ts-morph/common@0.12.3: - resolution: {integrity: sha512-4tUmeLyXJnJWvTFOKtcNJ1yh0a3SsTLi2MUoyj8iUNznFRN1ZquaNe7Oukqrnki2FzZkm0J9adCNLDZxUzvj+w==} - dependencies: - fast-glob: 3.3.2 - minimatch: 3.1.2 - mkdirp: 1.0.4 - path-browserify: 1.0.1 - dev: true - - /@types/babel__core@7.20.5: - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - dependencies: - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 - '@types/babel__generator': 7.6.8 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.6 - dev: true - - /@types/babel__generator@7.6.8: - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} - dependencies: - '@babel/types': 7.25.6 - dev: true - - /@types/babel__template@7.4.4: - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - dependencies: - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 - dev: true - - /@types/babel__traverse@7.20.6: - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - dependencies: - '@babel/types': 7.25.6 - dev: true - - /@types/debug@4.1.12: - resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - dependencies: - '@types/ms': 0.7.34 - dev: false - - /@types/estree-jsx@1.0.5: - resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} - dependencies: - '@types/estree': 1.0.5 - dev: false - - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - - /@types/hast@2.3.10: - resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==} - dependencies: - '@types/unist': 2.0.11 - dev: false - - /@types/hast@3.0.4: - resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} - dependencies: - '@types/unist': 3.0.3 - dev: false - - /@types/hoist-non-react-statics@3.3.5: - resolution: {integrity: sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==} - dependencies: - '@types/react': 18.3.5 - hoist-non-react-statics: 3.3.2 - dev: false - - /@types/js-cookie@3.0.6: - resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} - dev: true - - /@types/katex@0.16.7: - resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} - dev: false - - /@types/lodash@4.17.7: - resolution: {integrity: sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==} - dev: false - - /@types/mdast@4.0.4: - resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - dependencies: - '@types/unist': 3.0.3 - dev: false - - /@types/ms@0.7.34: - resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} - dev: false - - /@types/node@22.5.4: - resolution: {integrity: sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==} - dependencies: - undici-types: 6.19.8 - dev: true - - /@types/parse-json@4.0.2: - resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - dev: true - - /@types/prop-types@15.7.12: - resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} - - /@types/qs@6.9.15: - resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} - dev: false - - /@types/react-copy-to-clipboard@5.0.7: - resolution: {integrity: sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==} - dependencies: - '@types/react': 18.3.5 - dev: false - - /@types/react-dom@18.3.0: - resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} - dependencies: - '@types/react': 18.3.5 - dev: true - - /@types/react-syntax-highlighter@15.5.13: - resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==} - dependencies: - '@types/react': 18.3.5 - dev: false - - /@types/react@18.3.5: - resolution: {integrity: sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==} - dependencies: - '@types/prop-types': 15.7.12 - csstype: 3.1.3 - - /@types/unist@2.0.11: - resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - dev: false - - /@types/unist@3.0.3: - resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - dev: false - - /@typescript-eslint/eslint-plugin@8.4.0(@typescript-eslint/parser@8.4.0)(eslint@9.9.1)(typescript@5.5.4): - resolution: {integrity: sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.4.0(eslint@9.9.1)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 8.4.0 - '@typescript-eslint/type-utils': 8.4.0(eslint@9.9.1)(typescript@5.5.4) - '@typescript-eslint/utils': 8.4.0(eslint@9.9.1)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 8.4.0 - eslint: 9.9.1 - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@8.4.0(eslint@9.9.1)(typescript@5.5.4): - resolution: {integrity: sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 8.4.0 - '@typescript-eslint/types': 8.4.0 - '@typescript-eslint/typescript-estree': 8.4.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 8.4.0 - debug: 4.3.6 - eslint: 9.9.1 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@8.4.0: - resolution: {integrity: sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@typescript-eslint/types': 8.4.0 - '@typescript-eslint/visitor-keys': 8.4.0 - dev: true - - /@typescript-eslint/type-utils@8.4.0(eslint@9.9.1)(typescript@5.5.4): - resolution: {integrity: sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 8.4.0(typescript@5.5.4) - '@typescript-eslint/utils': 8.4.0(eslint@9.9.1)(typescript@5.5.4) - debug: 4.3.6 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - eslint - - supports-color - dev: true - - /@typescript-eslint/types@8.4.0: - resolution: {integrity: sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /@typescript-eslint/typescript-estree@8.4.0(typescript@5.5.4): - resolution: {integrity: sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 8.4.0 - '@typescript-eslint/visitor-keys': 8.4.0 - debug: 4.3.6 - fast-glob: 3.3.2 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@8.4.0(eslint@9.9.1)(typescript@5.5.4): - resolution: {integrity: sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1) - '@typescript-eslint/scope-manager': 8.4.0 - '@typescript-eslint/types': 8.4.0 - '@typescript-eslint/typescript-estree': 8.4.0(typescript@5.5.4) - eslint: 9.9.1 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@8.4.0: - resolution: {integrity: sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@typescript-eslint/types': 8.4.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@uiw/codemirror-extensions-basic-setup@4.23.0(@codemirror/autocomplete@6.18.0)(@codemirror/commands@6.6.1)(@codemirror/language@6.10.2)(@codemirror/lint@6.8.1)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0): - resolution: {integrity: sha512-+k5nkRpUWGaHr1JWT8jcKsVewlXw5qBgSopm9LW8fZ6KnSNZBycz8kHxh0+WSvckmXEESGptkIsb7dlkmJT/hQ==} - peerDependencies: - '@codemirror/autocomplete': '>=6.0.0' - '@codemirror/commands': '>=6.0.0' - '@codemirror/language': '>=6.0.0' - '@codemirror/lint': '>=6.0.0' - '@codemirror/search': '>=6.0.0' - '@codemirror/state': '>=6.0.0' - '@codemirror/view': '>=6.0.0' - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/commands': 6.6.1 - '@codemirror/language': 6.10.2 - '@codemirror/lint': 6.8.1 - '@codemirror/search': 6.5.6 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - dev: false - - /@uiw/codemirror-extensions-langs@4.23.0(@codemirror/autocomplete@6.18.0)(@codemirror/language-data@6.5.1)(@codemirror/language@6.10.2)(@codemirror/legacy-modes@6.4.1)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1)(@lezer/highlight@1.2.1)(@lezer/javascript@1.4.17)(@lezer/lr@1.4.2): - resolution: {integrity: sha512-WUJnTgS3CIV5TZPjwYO+mvRqxfvSSSKC2a+Wm5Uk3uFoZZ7O/GKi4bKKLsIHQkCwNnd9CHJzwN2dpIVrK1AmLA==} - peerDependencies: - '@codemirror/language-data': '>=6.0.0' - '@codemirror/legacy-modes': '>=6.0.0' - dependencies: - '@codemirror/lang-angular': 0.1.3 - '@codemirror/lang-cpp': 6.0.2 - '@codemirror/lang-css': 6.2.1(@codemirror/view@6.33.0) - '@codemirror/lang-html': 6.4.9 - '@codemirror/lang-java': 6.0.1 - '@codemirror/lang-javascript': 6.2.2 - '@codemirror/lang-json': 6.0.1 - '@codemirror/lang-less': 6.0.2(@codemirror/view@6.33.0) - '@codemirror/lang-lezer': 6.0.1 - '@codemirror/lang-liquid': 6.2.1 - '@codemirror/lang-markdown': 6.2.5 - '@codemirror/lang-php': 6.0.1 - '@codemirror/lang-python': 6.1.6(@codemirror/view@6.33.0) - '@codemirror/lang-rust': 6.0.1 - '@codemirror/lang-sass': 6.0.2(@codemirror/view@6.33.0) - '@codemirror/lang-sql': 6.7.1(@codemirror/view@6.33.0) - '@codemirror/lang-vue': 0.1.3 - '@codemirror/lang-wast': 6.0.2 - '@codemirror/lang-xml': 6.1.0 - '@codemirror/language-data': 6.5.1(@codemirror/view@6.33.0) - '@codemirror/legacy-modes': 6.4.1 - '@nextjournal/lang-clojure': 1.0.0 - '@replit/codemirror-lang-csharp': 6.2.0(@codemirror/autocomplete@6.18.0)(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1)(@lezer/highlight@1.2.1)(@lezer/lr@1.4.2) - '@replit/codemirror-lang-nix': 6.0.1(@codemirror/autocomplete@6.18.0)(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1)(@lezer/highlight@1.2.1)(@lezer/lr@1.4.2) - '@replit/codemirror-lang-solidity': 6.0.2(@codemirror/language@6.10.2) - '@replit/codemirror-lang-svelte': 6.0.0(@codemirror/autocomplete@6.18.0)(@codemirror/lang-css@6.2.1)(@codemirror/lang-html@6.4.9)(@codemirror/lang-javascript@6.2.2)(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1)(@lezer/highlight@1.2.1)(@lezer/javascript@1.4.17)(@lezer/lr@1.4.2) - codemirror-lang-mermaid: 0.5.0 - transitivePeerDependencies: - - '@codemirror/autocomplete' - - '@codemirror/language' - - '@codemirror/state' - - '@codemirror/view' - - '@lezer/common' - - '@lezer/highlight' - - '@lezer/javascript' - - '@lezer/lr' - dev: false - - /@uiw/react-codemirror@4.23.0(@babel/runtime@7.25.6)(@codemirror/autocomplete@6.18.0)(@codemirror/language@6.10.2)(@codemirror/lint@6.8.1)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.33.0)(codemirror@6.0.1)(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-MnqTXfgeLA3fsUUQjqjJgemEuNyoGALgsExVm0NQAllAAi1wfj+IoKFeK+h3XXMlTFRCFYOUh4AHDv0YXJLsOg==} - peerDependencies: - '@babel/runtime': '>=7.11.0' - '@codemirror/state': '>=6.0.0' - '@codemirror/theme-one-dark': '>=6.0.0' - '@codemirror/view': '>=6.0.0' - codemirror: '>=6.0.0' - react: '>=16.8.0' - react-dom: '>=16.8.0' - dependencies: - '@babel/runtime': 7.25.6 - '@codemirror/commands': 6.6.1 - '@codemirror/state': 6.4.1 - '@codemirror/theme-one-dark': 6.1.2 - '@codemirror/view': 6.33.0 - '@uiw/codemirror-extensions-basic-setup': 4.23.0(@codemirror/autocomplete@6.18.0)(@codemirror/commands@6.6.1)(@codemirror/language@6.10.2)(@codemirror/lint@6.8.1)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0) - codemirror: 6.0.1(@lezer/common@1.2.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - '@codemirror/autocomplete' - - '@codemirror/language' - - '@codemirror/lint' - - '@codemirror/search' - dev: false - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: false - - /@vitejs/plugin-react@4.3.1(vite@5.4.3): - resolution: {integrity: sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.2.0 || ^5.0.0 - dependencies: - '@babel/core': 7.25.2 - '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.25.2) - '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.25.2) - '@types/babel__core': 7.20.5 - react-refresh: 0.14.2 - vite: 5.4.3(@types/node@22.5.4)(sass-embedded@1.78.0) - transitivePeerDependencies: - - supports-color - dev: true - - /acorn-jsx@5.3.2(acorn@8.12.1): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.12.1 - dev: true - - /acorn@8.12.1: - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /ahooks@3.8.1(react@18.3.1): - resolution: {integrity: sha512-JoP9+/RWO7MnI/uSKdvQ8WB10Y3oo1PjLv+4Sv4Vpm19Z86VUMdXh+RhWvMGxZZs06sq2p0xVtFk8Oh5ZObsoA==} - engines: {node: '>=8.0.0'} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@babel/runtime': 7.25.6 - dayjs: 1.11.13 - intersection-observer: 0.12.2 - js-cookie: 3.0.5 - lodash: 4.17.21 - react: 18.3.1 - react-fast-compare: 3.2.2 - resize-observer-polyfill: 1.5.1 - screenfull: 5.2.0 - tslib: 2.7.0 - dev: false - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /antd@5.20.5(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-w/oVwoZAt5qP0PKhOkCmYXe06kXuoTh7UdQlltba/IzpbCCEh465z3Qw3i9HZY745HtOIS6ze707mVsORzN18g==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@ant-design/colors': 7.1.0 - '@ant-design/cssinjs': 1.21.1(react-dom@18.3.1)(react@18.3.1) - '@ant-design/cssinjs-utils': 1.0.3(react-dom@18.3.1)(react@18.3.1) - '@ant-design/icons': 5.4.0(react-dom@18.3.1)(react@18.3.1) - '@ant-design/react-slick': 1.1.2(react@18.3.1) - '@babel/runtime': 7.25.6 - '@ctrl/tinycolor': 3.6.1 - '@rc-component/color-picker': 2.0.1(react-dom@18.3.1)(react@18.3.1) - '@rc-component/mutate-observer': 1.1.0(react-dom@18.3.1)(react@18.3.1) - '@rc-component/qrcode': 1.0.0(react-dom@18.3.1)(react@18.3.1) - '@rc-component/tour': 1.15.1(react-dom@18.3.1)(react@18.3.1) - '@rc-component/trigger': 2.2.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - copy-to-clipboard: 3.3.3 - dayjs: 1.11.13 - rc-cascader: 3.28.1(react-dom@18.3.1)(react@18.3.1) - rc-checkbox: 3.3.0(react-dom@18.3.1)(react@18.3.1) - rc-collapse: 3.7.3(react-dom@18.3.1)(react@18.3.1) - rc-dialog: 9.5.2(react-dom@18.3.1)(react@18.3.1) - rc-drawer: 7.2.0(react-dom@18.3.1)(react@18.3.1) - rc-dropdown: 4.2.0(react-dom@18.3.1)(react@18.3.1) - rc-field-form: 2.4.0(react-dom@18.3.1)(react@18.3.1) - rc-image: 7.9.0(react-dom@18.3.1)(react@18.3.1) - rc-input: 1.6.3(react-dom@18.3.1)(react@18.3.1) - rc-input-number: 9.2.0(react-dom@18.3.1)(react@18.3.1) - rc-mentions: 2.15.0(react-dom@18.3.1)(react@18.3.1) - rc-menu: 9.14.1(react-dom@18.3.1)(react@18.3.1) - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-notification: 5.6.0(react-dom@18.3.1)(react@18.3.1) - rc-pagination: 4.2.0(react-dom@18.3.1)(react@18.3.1) - rc-picker: 4.6.14(dayjs@1.11.13)(react-dom@18.3.1)(react@18.3.1) - rc-progress: 4.0.0(react-dom@18.3.1)(react@18.3.1) - rc-rate: 2.13.0(react-dom@18.3.1)(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1)(react@18.3.1) - rc-segmented: 2.3.0(react-dom@18.3.1)(react@18.3.1) - rc-select: 14.15.2(react-dom@18.3.1)(react@18.3.1) - rc-slider: 11.1.5(react-dom@18.3.1)(react@18.3.1) - rc-steps: 6.0.1(react-dom@18.3.1)(react@18.3.1) - rc-switch: 4.1.0(react-dom@18.3.1)(react@18.3.1) - rc-table: 7.45.7(react-dom@18.3.1)(react@18.3.1) - rc-tabs: 15.1.1(react-dom@18.3.1)(react@18.3.1) - rc-textarea: 1.8.1(react-dom@18.3.1)(react@18.3.1) - rc-tooltip: 6.2.0(react-dom@18.3.1)(react@18.3.1) - rc-tree: 5.9.0(react-dom@18.3.1)(react@18.3.1) - rc-tree-select: 5.23.0(react-dom@18.3.1)(react@18.3.1) - rc-upload: 4.7.0(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - scroll-into-view-if-needed: 3.1.0 - throttle-debounce: 5.0.2 - transitivePeerDependencies: - - date-fns - - luxon - - moment - dev: false - - /any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /arg@5.0.2: - resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /array-tree-filter@2.1.0: - resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} - dev: false - - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: false - - /autoprefixer@10.4.20(postcss@8.4.45): - resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - dependencies: - browserslist: 4.23.3 - caniuse-lite: 1.0.30001655 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.1.0 - postcss: 8.4.45 - postcss-value-parser: 4.2.0 - dev: true - - /axios@1.7.7: - resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} - dependencies: - follow-redirects: 1.15.8 - form-data: 4.0.0 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - dev: false - - /bail@2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - dev: false - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - /big-integer@1.6.52: - resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} - engines: {node: '>=0.6'} - dev: false - - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.1.1 - dev: true - - /broadcast-channel@3.7.0: - resolution: {integrity: sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==} - dependencies: - '@babel/runtime': 7.25.6 - detect-node: 2.1.0 - js-sha3: 0.8.0 - microseconds: 0.2.0 - nano-time: 1.0.0 - oblivious-set: 1.0.0 - rimraf: 3.0.2 - unload: 2.2.0 - dev: false - - /browserslist@4.23.3: - resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001655 - electron-to-chromium: 1.5.14 - node-releases: 2.0.18 - update-browserslist-db: 1.1.0(browserslist@4.23.3) - dev: true - - /buffer-builder@0.2.0: - resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==} - dev: true - - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - dev: false - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /camelcase-css@2.0.1: - resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} - engines: {node: '>= 6'} - dev: true - - /caniuse-lite@1.0.30001655: - resolution: {integrity: sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==} - dev: true - - /ccount@2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - dev: false - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /character-entities-html4@2.1.0: - resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} - dev: false - - /character-entities-legacy@1.1.4: - resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} - dev: false - - /character-entities-legacy@3.0.0: - resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} - dev: false - - /character-entities@1.2.4: - resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} - dev: false - - /character-entities@2.0.2: - resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - dev: false - - /character-reference-invalid@1.1.4: - resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} - dev: false - - /character-reference-invalid@2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - dev: false - - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /classnames@2.5.1: - resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} - dev: false - - /code-block-writer@11.0.3: - resolution: {integrity: sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==} - dev: true - - /codemirror-lang-mermaid@0.5.0: - resolution: {integrity: sha512-Taw/2gPCyNArQJCxIP/HSUif+3zrvD+6Ugt7KJZ2dUKou/8r3ZhcfG8krNTZfV2iu8AuGnymKuo7bLPFyqsh/A==} - dependencies: - '@codemirror/language': 6.10.2 - '@lezer/highlight': 1.2.1 - '@lezer/lr': 1.4.2 - dev: false - - /codemirror@6.0.1(@lezer/common@1.2.1): - resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==} - dependencies: - '@codemirror/autocomplete': 6.18.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.33.0)(@lezer/common@1.2.1) - '@codemirror/commands': 6.6.1 - '@codemirror/language': 6.10.2 - '@codemirror/lint': 6.8.1 - '@codemirror/search': 6.5.6 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.33.0 - transitivePeerDependencies: - - '@lezer/common' - dev: false - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: false - - /comma-separated-tokens@1.0.8: - resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==} - dev: false - - /comma-separated-tokens@2.0.3: - resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - dev: false - - /commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - dev: true - - /commander@6.2.1: - resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} - engines: {node: '>= 6'} - dev: true - - /commander@8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - dev: false - - /compute-scroll-into-view@3.1.0: - resolution: {integrity: sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==} - dev: false - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /copy-to-clipboard@3.3.3: - resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} - dependencies: - toggle-selection: 1.0.6 - dev: false - - /cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} - dependencies: - '@types/parse-json': 4.0.2 - import-fresh: 3.3.0 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - dev: true - - /crelt@1.0.6: - resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} - dev: false - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - /dayjs@1.11.13: - resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - dev: false - - /debug@4.3.6: - resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /decode-named-character-reference@1.0.2: - resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} - dependencies: - character-entities: 2.0.2 - dev: false - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - dev: false - - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: false - - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - dev: false - - /detect-node@2.1.0: - resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} - dev: false - - /devlop@1.1.0: - resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - dependencies: - dequal: 2.0.3 - dev: false - - /didyoumean@1.2.2: - resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - dev: true - - /dlv@1.1.3: - resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - dev: true - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /electron-to-chromium@1.5.14: - resolution: {integrity: sha512-bEfPECb3fJ15eaDnu9LEJ2vPGD6W1vt7vZleSVyFhYuMIKm3vz/g9lt7IvEzgdwj58RjbPKUF2rXTCN/UW47tQ==} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - dev: false - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - dev: false - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: false - - /esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - dev: true - - /escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - dev: false - - /eslint-plugin-react-hooks@5.1.0-rc-fb9a90fa48-20240614(eslint@9.9.1): - resolution: {integrity: sha512-xsiRwaDNF5wWNC4ZHLut+x/YcAxksUd9Rizt7LaEn3bV8VyYRpXnRJQlLOfYaVy9esk4DFP4zPPnoNVjq5Gc0w==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - dependencies: - eslint: 9.9.1 - dev: true - - /eslint-plugin-react-refresh@0.4.11(eslint@9.9.1): - resolution: {integrity: sha512-wrAKxMbVr8qhXTtIKfXqAn5SAtRZt0aXxe5P23Fh4pUAdC6XEsybGLB8P0PI4j1yYqOgUEUlzKAGDfo7rJOjcw==} - peerDependencies: - eslint: '>=7' - dependencies: - eslint: 9.9.1 - dev: true - - /eslint-scope@8.0.2: - resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint-visitor-keys@4.0.0: - resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /eslint@9.9.1: - resolution: {integrity: sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1) - '@eslint-community/regexpp': 4.11.0 - '@eslint/config-array': 0.18.0 - '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.9.1 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.3.0 - '@nodelib/fs.walk': 1.2.8 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.6 - escape-string-regexp: 4.0.0 - eslint-scope: 8.0.2 - eslint-visitor-keys: 4.0.0 - espree: 10.1.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@10.1.0: - resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) - eslint-visitor-keys: 4.0.0 - dev: true - - /esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /estree-util-is-identifier-name@3.0.0: - resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} - dev: false - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: false - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 - dev: true - - /fault@1.0.4: - resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==} - dependencies: - format: 0.2.2 - dev: false - - /file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - dependencies: - flat-cache: 4.0.1 - dev: true - - /fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - dev: true - - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: true - - /follow-redirects@1.15.8: - resolution: {integrity: sha512-xgrmBhBToVKay1q2Tao5LI26B83UhrB/vM1avwVSDzt8rx3rO6AizBAaF46EgksTVr+rFTQaqZZ9MVBfUe4nig==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dev: false - - /foreground-child@3.3.0: - resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: true - - /form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: false - - /format@0.2.2: - resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} - engines: {node: '>=0.4.x'} - dev: false - - /fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: false - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - dev: false - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true - dependencies: - foreground-child: 3.3.0 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.0 - path-scurry: 1.11.1 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: false - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - dev: true - - /globals@15.9.0: - resolution: {integrity: sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==} - engines: {node: '>=18'} - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.4 - dev: false - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - dev: false - - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - dev: false - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: false - - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - - /hast-util-from-dom@5.0.0: - resolution: {integrity: sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==} - dependencies: - '@types/hast': 3.0.4 - hastscript: 8.0.0 - web-namespaces: 2.0.1 - dev: false - - /hast-util-from-html-isomorphic@2.0.0: - resolution: {integrity: sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==} - dependencies: - '@types/hast': 3.0.4 - hast-util-from-dom: 5.0.0 - hast-util-from-html: 2.0.2 - unist-util-remove-position: 5.0.0 - dev: false - - /hast-util-from-html@2.0.2: - resolution: {integrity: sha512-HwOHwxdt2zC5KQ/CNoybBntRook2zJvfZE/u5/Ap7aLPe22bDqen7KwGkOqOyzL5zIqKwiYX/OTtE0FWgr6XXA==} - dependencies: - '@types/hast': 3.0.4 - devlop: 1.1.0 - hast-util-from-parse5: 8.0.1 - parse5: 7.1.2 - vfile: 6.0.3 - vfile-message: 4.0.2 - dev: false - - /hast-util-from-parse5@8.0.1: - resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - devlop: 1.1.0 - hastscript: 8.0.0 - property-information: 6.5.0 - vfile: 6.0.3 - vfile-location: 5.0.3 - web-namespaces: 2.0.1 - dev: false - - /hast-util-is-element@3.0.0: - resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} - dependencies: - '@types/hast': 3.0.4 - dev: false - - /hast-util-parse-selector@2.2.5: - resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==} - dev: false - - /hast-util-parse-selector@4.0.0: - resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} - dependencies: - '@types/hast': 3.0.4 - dev: false - - /hast-util-raw@9.0.4: - resolution: {integrity: sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==} - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - '@ungap/structured-clone': 1.2.0 - hast-util-from-parse5: 8.0.1 - hast-util-to-parse5: 8.0.0 - html-void-elements: 3.0.0 - mdast-util-to-hast: 13.2.0 - parse5: 7.1.2 - unist-util-position: 5.0.0 - unist-util-visit: 5.0.0 - vfile: 6.0.3 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - dev: false - - /hast-util-to-jsx-runtime@2.3.0: - resolution: {integrity: sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==} - dependencies: - '@types/estree': 1.0.5 - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - comma-separated-tokens: 2.0.3 - devlop: 1.1.0 - estree-util-is-identifier-name: 3.0.0 - hast-util-whitespace: 3.0.0 - mdast-util-mdx-expression: 2.0.0 - mdast-util-mdx-jsx: 3.1.3 - mdast-util-mdxjs-esm: 2.0.1 - property-information: 6.5.0 - space-separated-tokens: 2.0.2 - style-to-object: 1.0.7 - unist-util-position: 5.0.0 - vfile-message: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: false - - /hast-util-to-parse5@8.0.0: - resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} - dependencies: - '@types/hast': 3.0.4 - comma-separated-tokens: 2.0.3 - devlop: 1.1.0 - property-information: 6.5.0 - space-separated-tokens: 2.0.2 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - dev: false - - /hast-util-to-text@4.0.2: - resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - hast-util-is-element: 3.0.0 - unist-util-find-after: 5.0.0 - dev: false - - /hast-util-whitespace@3.0.0: - resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} - dependencies: - '@types/hast': 3.0.4 - dev: false - - /hastscript@6.0.0: - resolution: {integrity: sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==} - dependencies: - '@types/hast': 2.3.10 - comma-separated-tokens: 1.0.8 - hast-util-parse-selector: 2.2.5 - property-information: 5.6.0 - space-separated-tokens: 1.1.5 - dev: false - - /hastscript@8.0.0: - resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} - dependencies: - '@types/hast': 3.0.4 - comma-separated-tokens: 2.0.3 - hast-util-parse-selector: 4.0.0 - property-information: 6.5.0 - space-separated-tokens: 2.0.2 - dev: false - - /highlight.js@10.7.3: - resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} - dev: false - - /hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - dependencies: - react-is: 16.13.1 - dev: false - - /html-url-attributes@3.0.0: - resolution: {integrity: sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==} - dev: false - - /html-void-elements@3.0.0: - resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} - dev: false - - /ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - dev: true - - /immutable@4.3.7: - resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: false - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: false - - /inline-style-parser@0.2.3: - resolution: {integrity: sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==} - dev: false - - /intersection-observer@0.12.2: - resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} - dev: false - - /intl-messageformat@10.5.14: - resolution: {integrity: sha512-IjC6sI0X7YRjjyVH9aUgdftcmZK7WXdHeil4KwbjDnRWjnVitKpAx3rr6t6di1joFp5188VqKcobOPA6mCLG/w==} - dependencies: - '@formatjs/ecma402-abstract': 2.0.0 - '@formatjs/fast-memoize': 2.2.0 - '@formatjs/icu-messageformat-parser': 2.7.8 - tslib: 2.7.0 - dev: false - - /is-alphabetical@1.0.4: - resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} - dev: false - - /is-alphabetical@2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} - dev: false - - /is-alphanumerical@1.0.4: - resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} - dependencies: - is-alphabetical: 1.0.4 - is-decimal: 1.0.4 - dev: false - - /is-alphanumerical@2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 - dev: false - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.3.0 - dev: true - - /is-core-module@2.15.1: - resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} - engines: {node: '>= 0.4'} - dependencies: - hasown: 2.0.2 - dev: true - - /is-decimal@1.0.4: - resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} - dev: false - - /is-decimal@2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - dev: false - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-hexadecimal@1.0.4: - resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} - dev: false - - /is-hexadecimal@2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - dev: false - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: false - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /jiti@1.21.6: - resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} - hasBin: true - dev: true - - /js-cookie@3.0.5: - resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} - engines: {node: '>=14'} - dev: false - - /js-sha3@0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} - dev: false - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json2mq@0.2.0: - resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} - dependencies: - string-convert: 0.2.1 - dev: false - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /katex@0.16.11: - resolution: {integrity: sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==} - hasBin: true - dependencies: - commander: 8.3.0 - dev: false - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - dev: true - - /lilconfig@3.1.2: - resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} - engines: {node: '>=14'} - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - /longest-streak@3.1.0: - resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - dev: false - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - dev: false - - /lowlight@1.20.0: - resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==} - dependencies: - fault: 1.0.4 - highlight.js: 10.7.3 - dev: false - - /lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /markdown-table@3.0.3: - resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} - dev: false - - /match-sorter@6.3.4: - resolution: {integrity: sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==} - dependencies: - '@babel/runtime': 7.25.6 - remove-accents: 0.5.0 - dev: false - - /mdast-util-find-and-replace@3.0.1: - resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} - dependencies: - '@types/mdast': 4.0.4 - escape-string-regexp: 5.0.0 - unist-util-is: 6.0.0 - unist-util-visit-parents: 6.0.1 - dev: false - - /mdast-util-from-markdown@2.0.1: - resolution: {integrity: sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==} - dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - decode-named-character-reference: 1.0.2 - devlop: 1.1.0 - mdast-util-to-string: 4.0.0 - micromark: 4.0.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-decode-string: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - unist-util-stringify-position: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-gfm-autolink-literal@2.0.1: - resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} - dependencies: - '@types/mdast': 4.0.4 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-find-and-replace: 3.0.1 - micromark-util-character: 2.1.0 - dev: false - - /mdast-util-gfm-footnote@2.0.0: - resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - micromark-util-normalize-identifier: 2.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-gfm-strikethrough@2.0.0: - resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} - dependencies: - '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-gfm-table@2.0.0: - resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - markdown-table: 3.0.3 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-gfm-task-list-item@2.0.0: - resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-gfm@3.0.0: - resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} - dependencies: - mdast-util-from-markdown: 2.0.1 - mdast-util-gfm-autolink-literal: 2.0.1 - mdast-util-gfm-footnote: 2.0.0 - mdast-util-gfm-strikethrough: 2.0.0 - mdast-util-gfm-table: 2.0.0 - mdast-util-gfm-task-list-item: 2.0.0 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-math@3.0.0: - resolution: {integrity: sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==} - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - longest-streak: 3.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - unist-util-remove-position: 5.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-mdx-expression@2.0.0: - resolution: {integrity: sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-mdx-jsx@3.1.3: - resolution: {integrity: sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - parse-entities: 4.0.1 - stringify-entities: 4.0.4 - unist-util-stringify-position: 4.0.0 - vfile-message: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-mdxjs-esm@2.0.1: - resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-phrasing@4.1.0: - resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} - dependencies: - '@types/mdast': 4.0.4 - unist-util-is: 6.0.0 - dev: false - - /mdast-util-to-hast@13.2.0: - resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@ungap/structured-clone': 1.2.0 - devlop: 1.1.0 - micromark-util-sanitize-uri: 2.0.0 - trim-lines: 3.0.1 - unist-util-position: 5.0.0 - unist-util-visit: 5.0.0 - vfile: 6.0.3 - dev: false - - /mdast-util-to-markdown@2.1.0: - resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} - dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - longest-streak: 3.1.0 - mdast-util-phrasing: 4.1.0 - mdast-util-to-string: 4.0.0 - micromark-util-decode-string: 2.0.0 - unist-util-visit: 5.0.0 - zwitch: 2.0.4 - dev: false - - /mdast-util-to-string@4.0.0: - resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - dependencies: - '@types/mdast': 4.0.4 - dev: false - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /micromark-core-commonmark@2.0.1: - resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==} - dependencies: - decode-named-character-reference: 1.0.2 - devlop: 1.1.0 - micromark-factory-destination: 2.0.0 - micromark-factory-label: 2.0.0 - micromark-factory-space: 2.0.0 - micromark-factory-title: 2.0.0 - micromark-factory-whitespace: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-classify-character: 2.0.0 - micromark-util-html-tag-name: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-subtokenize: 2.0.1 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-extension-gfm-autolink-literal@2.1.0: - resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-extension-gfm-footnote@2.1.0: - resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} - dependencies: - devlop: 1.1.0 - micromark-core-commonmark: 2.0.1 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-extension-gfm-strikethrough@2.1.0: - resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-classify-character: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-extension-gfm-table@2.1.0: - resolution: {integrity: sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==} - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-extension-gfm-tagfilter@2.0.0: - resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} - dependencies: - micromark-util-types: 2.0.0 - dev: false - - /micromark-extension-gfm-task-list-item@2.1.0: - resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-extension-gfm@3.0.0: - resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} - dependencies: - micromark-extension-gfm-autolink-literal: 2.1.0 - micromark-extension-gfm-footnote: 2.1.0 - micromark-extension-gfm-strikethrough: 2.1.0 - micromark-extension-gfm-table: 2.1.0 - micromark-extension-gfm-tagfilter: 2.0.0 - micromark-extension-gfm-task-list-item: 2.1.0 - micromark-util-combine-extensions: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-extension-math@3.1.0: - resolution: {integrity: sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==} - dependencies: - '@types/katex': 0.16.7 - devlop: 1.1.0 - katex: 0.16.11 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-factory-destination@2.0.0: - resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-factory-label@2.0.0: - resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} - dependencies: - devlop: 1.1.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-factory-space@2.0.0: - resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-factory-title@2.0.0: - resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} - dependencies: - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-factory-whitespace@2.0.0: - resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} - dependencies: - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-util-character@2.1.0: - resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} - dependencies: - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-util-chunked@2.0.0: - resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} - dependencies: - micromark-util-symbol: 2.0.0 - dev: false - - /micromark-util-classify-character@2.0.0: - resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-util-combine-extensions@2.0.0: - resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} - dependencies: - micromark-util-chunked: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-util-decode-numeric-character-reference@2.0.1: - resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} - dependencies: - micromark-util-symbol: 2.0.0 - dev: false - - /micromark-util-decode-string@2.0.0: - resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} - dependencies: - decode-named-character-reference: 1.0.2 - micromark-util-character: 2.1.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-symbol: 2.0.0 - dev: false - - /micromark-util-encode@2.0.0: - resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} - dev: false - - /micromark-util-html-tag-name@2.0.0: - resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} - dev: false - - /micromark-util-normalize-identifier@2.0.0: - resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} - dependencies: - micromark-util-symbol: 2.0.0 - dev: false - - /micromark-util-resolve-all@2.0.0: - resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} - dependencies: - micromark-util-types: 2.0.0 - dev: false - - /micromark-util-sanitize-uri@2.0.0: - resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-encode: 2.0.0 - micromark-util-symbol: 2.0.0 - dev: false - - /micromark-util-subtokenize@2.0.1: - resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==} - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: false - - /micromark-util-symbol@2.0.0: - resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} - dev: false - - /micromark-util-types@2.0.0: - resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} - dev: false - - /micromark@4.0.0: - resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} - dependencies: - '@types/debug': 4.1.12 - debug: 4.3.6 - decode-named-character-reference: 1.0.2 - devlop: 1.1.0 - micromark-core-commonmark: 2.0.1 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-combine-extensions: 2.0.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-encode: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-subtokenize: 2.0.1 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - dev: true - - /microseconds@0.2.0: - resolution: {integrity: sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==} - dev: false - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: false - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: false - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - - /minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - /mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - dev: true - - /nano-time@1.0.0: - resolution: {integrity: sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==} - dependencies: - big-integer: 1.6.52 - dev: false - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: true - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - /object-hash@3.0.0: - resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} - engines: {node: '>= 6'} - dev: true - - /object-inspect@1.13.2: - resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} - engines: {node: '>= 0.4'} - dev: false - - /oblivious-set@1.0.0: - resolution: {integrity: sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==} - dev: false - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: false - - /optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - dev: true - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /package-json-from-dist@1.0.0: - resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-entities@2.0.0: - resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} - dependencies: - character-entities: 1.2.4 - character-entities-legacy: 1.1.4 - character-reference-invalid: 1.1.4 - is-alphanumerical: 1.0.4 - is-decimal: 1.0.4 - is-hexadecimal: 1.0.4 - dev: false - - /parse-entities@4.0.1: - resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} - dependencies: - '@types/unist': 2.0.11 - character-entities: 2.0.2 - character-entities-legacy: 3.0.0 - character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.0.2 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - is-hexadecimal: 2.0.1 - dev: false - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.24.7 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /parse5@7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} - dependencies: - entities: 4.5.0 - dev: false - - /path-browserify@1.0.1: - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: false - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - dev: true - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /picocolors@1.1.0: - resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} - dev: true - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - dev: true - - /pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - dev: true - - /postcss-import@15.1.0(postcss@8.4.45): - resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} - engines: {node: '>=14.0.0'} - peerDependencies: - postcss: ^8.0.0 - dependencies: - postcss: 8.4.45 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.8 - dev: true - - /postcss-js@4.0.1(postcss@8.4.45): - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} - engines: {node: ^12 || ^14 || >= 16} - peerDependencies: - postcss: ^8.4.21 - dependencies: - camelcase-css: 2.0.1 - postcss: 8.4.45 - dev: true - - /postcss-load-config@4.0.2(postcss@8.4.45): - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - dependencies: - lilconfig: 3.1.2 - postcss: 8.4.45 - yaml: 2.5.1 - dev: true - - /postcss-nested@6.2.0(postcss@8.4.45): - resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.2.14 - dependencies: - postcss: 8.4.45 - postcss-selector-parser: 6.1.2 - dev: true - - /postcss-selector-parser@6.1.2: - resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - dev: true - - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: true - - /postcss@8.4.45: - resolution: {integrity: sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.1.0 - source-map-js: 1.2.0 - dev: true - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prismjs@1.27.0: - resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==} - engines: {node: '>=6'} - dev: false - - /prismjs@1.29.0: - resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} - engines: {node: '>=6'} - dev: false - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: false - - /property-information@5.6.0: - resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==} - dependencies: - xtend: 4.0.2 - dev: false - - /property-information@6.5.0: - resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} - dev: false - - /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: false - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true - - /qs@6.13.0: - resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - dev: false - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /rc-cascader@3.28.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-9+8oHIMWVLHxuaapDiqFNmD9KSyKN/P4bo9x/MBuDbyTqP8f2/POmmZxdXWBO3yq/uE3pKyQCXYNUxrNfHRv2A==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - array-tree-filter: 2.1.0 - classnames: 2.5.1 - rc-select: 14.15.2(react-dom@18.3.1)(react@18.3.1) - rc-tree: 5.9.0(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-checkbox@3.3.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-Ih3ZaAcoAiFKJjifzwsGiT/f/quIkxJoklW4yKGho14Olulwn8gN7hOBve0/WGDg5o/l/5mL0w7ff7/YGvefVw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-collapse@3.7.3(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-60FJcdTRn0X5sELF18TANwtVi7FtModq649H11mYF1jh83DniMoM4MqY627sEKRCTm4+WXfGDcB7hY5oW6xhyw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-dialog@9.5.2(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-qVUjc8JukG+j/pNaHVSRa2GO2/KbV2thm7yO4hepQ902eGdYK913sGkwg/fh9yhKYV1ql3BKIN2xnud3rEXAPw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/portal': 1.1.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-drawer@7.2.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/portal': 1.1.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-dropdown@4.2.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==} - peerDependencies: - react: '>=16.11.0' - react-dom: '>=16.11.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/trigger': 2.2.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-field-form@2.4.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-XZ/lF9iqf9HXApIHQHqzJK5v2w4mkUMsVqAzOyWVzoiwwXEavY6Tpuw7HavgzIoD+huVff4JghSGcgEfX6eycg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/async-validator': 5.0.4 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-image@7.9.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-l4zqO5E0quuLMCtdKfBgj4Suv8tIS011F5k1zBBlK25iMjjiNHxA0VeTzGFtUZERSA45gvpXDg8/P6qNLjR25g==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/portal': 1.1.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - rc-dialog: 9.5.2(react-dom@18.3.1)(react@18.3.1) - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-input-number@9.2.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-5XZFhBCV5f9UQ62AZ2hFbEY8iZT/dm23Q1kAg0H8EvOgD3UDbYYJAayoVIkM3lQaCqYAW5gV0yV3vjw1XtzWHg==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/mini-decimal': 1.1.0 - classnames: 2.5.1 - rc-input: 1.6.3(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-input@1.6.3(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==} - peerDependencies: - react: '>=16.0.0' - react-dom: '>=16.0.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-mentions@2.15.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-f5v5i7VdqvBDXbphoqcQWmXDif2Msd2arritVoWybrVDuHE6nQ7XCYsybHbV//WylooK52BFDouFvyaRDtXZEw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/trigger': 2.2.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - rc-input: 1.6.3(react-dom@18.3.1)(react@18.3.1) - rc-menu: 9.14.1(react-dom@18.3.1)(react@18.3.1) - rc-textarea: 1.8.1(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-menu@9.14.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-5wlRb3M8S4yGlWhSoEYJ7ZVRElyScdcpUHxgiLxkeig1tEdyKrnED3B2fhpN0Rrpdp9jyhnmZR/Lwq2fH5VvDQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/trigger': 2.2.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-overflow: 1.3.2(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-motion@2.9.2(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-fUAhHKLDdkAXIDLH0GYwof3raS58dtNUmzLF2MeiR8o6n4thNpSDQhOqQzWE4WfFZDCi9VEN8n7tiB7czREcyw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-notification@5.6.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-TGQW5T7waOxLwgJG7fXcw8l7AQiFOjaZ7ISF5PrU526nunHRNcTMuzKihQHaF4E/h/KfOCDk3Mv8eqzbu2e28w==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-overflow@1.3.2(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-resize-observer: 1.4.0(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-pagination@4.2.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-V6qeANJsT6tmOcZ4XiUmj8JXjRLbkusuufpuoBw2GiAn94fIixYjFLmbruD1Sbhn8fPLDnWawPp4CN37zQorvw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-picker@4.6.14(dayjs@1.11.13)(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-7DuTfUFdkxmsNpWQ0TWv6FPGna5e6KKC4nxtx3x9xhumLz7jb3fhlDdWQvqEL6tpt9DOb1+N5j+wB+lDOSS9kg==} - engines: {node: '>=8.x'} - peerDependencies: - date-fns: '>= 2.x' - dayjs: '>= 1.x' - luxon: '>= 3.x' - moment: '>= 2.x' - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - date-fns: - optional: true - dayjs: - optional: true - luxon: - optional: true - moment: - optional: true - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/trigger': 2.2.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - dayjs: 1.11.13 - rc-overflow: 1.3.2(react-dom@18.3.1)(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-progress@4.0.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-rate@2.13.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-resize-observer@1.4.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - resize-observer-polyfill: 1.5.1 - dev: false - - /rc-segmented@2.3.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg==} - peerDependencies: - react: '>=16.0.0' - react-dom: '>=16.0.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-select@14.15.2(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-oNoXlaFmpqXYcQDzcPVLrEqS2J9c+/+oJuGrlXeVVX/gVgrbHa5YcyiRUXRydFjyuA7GP3elRuLF7Y3Tfwltlw==} - engines: {node: '>=8.x'} - peerDependencies: - react: '*' - react-dom: '*' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/trigger': 2.2.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-overflow: 1.3.2(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - rc-virtual-list: 3.14.5(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-slider@11.1.5(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-b77H5PbjMKsvkYXAYIkn50QuFX6ICQmCTibDinI9q+BHx65/TV4TeU25+oadhSRzykxs0/vBWeKBwRyySOeWlg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-steps@6.0.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-switch@4.1.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-table@7.45.7(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-wi9LetBL1t1csxyGkMB2p3mCiMt+NDexMlPbXHvQFmBBAsMxrgNSAPwUci2zDLUq9m8QdWc1Nh8suvrpy9mXrg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/context': 1.4.0(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - rc-resize-observer: 1.4.0(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - rc-virtual-list: 3.14.5(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-tabs@15.1.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-Tc7bJvpEdkWIVCUL7yQrMNBJY3j44NcyWS48jF/UKMXuUlzaXK+Z/pEL5LjGcTadtPvVmNqA40yv7hmr+tCOAw==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-dropdown: 4.2.0(react-dom@18.3.1)(react@18.3.1) - rc-menu: 9.14.1(react-dom@18.3.1)(react@18.3.1) - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-textarea@1.8.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-bm36N2ZqwZAP60ZQg2OY9mPdqWC+m6UTjHc+CqEZOxb3Ia29BGHazY/s5bI8M4113CkqTzhtFUDNA078ZiOx3Q==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-input: 1.6.3(react-dom@18.3.1)(react@18.3.1) - rc-resize-observer: 1.4.0(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-tooltip@6.2.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-iS/3iOAvtDh9GIx1ulY7EFUXUtktFccNLsARo3NPgLf0QW9oT0w3dA9cYWlhqAKmD+uriEwdWz1kH0Qs4zk2Aw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - '@rc-component/trigger': 2.2.2(react-dom@18.3.1)(react@18.3.1) - classnames: 2.5.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-tree-select@5.23.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-aQGi2tFSRw1WbXv0UVXPzHm09E0cSvUVZMLxQtMv3rnZZpNmdRXWrnd9QkLNlVH31F+X5rgghmdSFF3yZW0N9A==} - peerDependencies: - react: '*' - react-dom: '*' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-select: 14.15.2(react-dom@18.3.1)(react@18.3.1) - rc-tree: 5.9.0(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-tree@5.9.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-CPrgOvm9d/9E+izTONKSngNzQdIEjMox2PBufWjS1wf7vxtvmCWzK1SlpHbRY6IaBfJIeZ+88RkcIevf729cRg==} - engines: {node: '>=10.x'} - peerDependencies: - react: '*' - react-dom: '*' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-motion: 2.9.2(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - rc-virtual-list: 3.14.5(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-upload@4.7.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-eUwxYNHlsYe5vYhKFAUGrQG95JrnPzY+BmPi1Daq39fWNl/eOc7v4UODuWrVp2LFkQBuV3cMCG/I68iub6oBrg==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /rc-util@5.43.0(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-is: 18.3.1 - dev: false - - /rc-virtual-list@3.14.5(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-ZMOnkCLv2wUN8Jz7yI4XiSLa9THlYvf00LuMhb1JlsQCewuU7ydPuHw1rGVPhe9VZYl/5UqODtNd7QKJ2DMGfg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - dependencies: - '@babel/runtime': 7.25.6 - classnames: 2.5.1 - rc-resize-observer: 1.4.0(react-dom@18.3.1)(react@18.3.1) - rc-util: 5.43.0(react-dom@18.3.1)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /react-copy-to-clipboard@5.1.0(react@18.3.1): - resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==} - peerDependencies: - react: ^15.3.0 || 16 || 17 || 18 - dependencies: - copy-to-clipboard: 3.3.3 - prop-types: 15.8.1 - react: 18.3.1 - dev: false - - /react-dom@18.3.1(react@18.3.1): - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} - peerDependencies: - react: ^18.3.1 - dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 - dev: false - - /react-fast-compare@3.2.2: - resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} - dev: false - - /react-intl@6.6.8(react@18.3.1)(typescript@5.5.4): - resolution: {integrity: sha512-M0pkhzcgV31h++2901BiRXWl69hp2zPyLxRrSwRjd1ErXbNoubz/f4M6DrRTd4OiSUrT4ajRQzrmtS5plG4FtA==} - peerDependencies: - react: ^16.6.0 || 17 || 18 - typescript: ^4.7 || 5 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@formatjs/ecma402-abstract': 2.0.0 - '@formatjs/icu-messageformat-parser': 2.7.8 - '@formatjs/intl': 2.10.4(typescript@5.5.4) - '@formatjs/intl-displaynames': 6.6.8 - '@formatjs/intl-listformat': 7.5.7 - '@types/hoist-non-react-statics': 3.3.5 - '@types/react': 18.3.5 - hoist-non-react-statics: 3.3.2 - intl-messageformat: 10.5.14 - react: 18.3.1 - tslib: 2.7.0 - typescript: 5.5.4 - dev: false - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - dev: false - - /react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - dev: false - - /react-markdown@9.0.1(@types/react@18.3.5)(react@18.3.1): - resolution: {integrity: sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==} - peerDependencies: - '@types/react': '>=18' - react: '>=18' - dependencies: - '@types/hast': 3.0.4 - '@types/react': 18.3.5 - devlop: 1.1.0 - hast-util-to-jsx-runtime: 2.3.0 - html-url-attributes: 3.0.0 - mdast-util-to-hast: 13.2.0 - react: 18.3.1 - remark-parse: 11.0.0 - remark-rehype: 11.1.0 - unified: 11.0.5 - unist-util-visit: 5.0.0 - vfile: 6.0.3 - transitivePeerDependencies: - - supports-color - dev: false - - /react-query@3.39.3(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: '*' - react-native: '*' - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - dependencies: - '@babel/runtime': 7.25.6 - broadcast-channel: 3.7.0 - match-sorter: 6.3.4 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /react-refresh@0.14.2: - resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} - engines: {node: '>=0.10.0'} - dev: true - - /react-router-dom@6.26.1(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-veut7m41S1fLql4pLhxeSW3jlqs+4MtjRLj0xvuCEXsxusJCbs6I8yn9BxzzDX2XDgafrccY6hwjmd/bL54tFw==} - engines: {node: '>=14.0.0'} - peerDependencies: - react: '>=16.8' - react-dom: '>=16.8' - dependencies: - '@remix-run/router': 1.19.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-router: 6.26.1(react@18.3.1) - dev: false - - /react-router@6.26.1(react@18.3.1): - resolution: {integrity: sha512-kIwJveZNwp7teQRI5QmwWo39A5bXRyqpH0COKKmPnyD2vBvDwgFXSqDUYtt1h+FEyfnE8eXr7oe0MxRzVwCcvQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - react: '>=16.8' - dependencies: - '@remix-run/router': 1.19.1 - react: 18.3.1 - dev: false - - /react-syntax-highlighter@15.5.0(react@18.3.1): - resolution: {integrity: sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==} - peerDependencies: - react: '>= 0.14.0' - dependencies: - '@babel/runtime': 7.25.6 - highlight.js: 10.7.3 - lowlight: 1.20.0 - prismjs: 1.29.0 - react: 18.3.1 - refractor: 3.6.0 - dev: false - - /react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - dev: false - - /read-cache@1.0.0: - resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - dependencies: - pify: 2.3.0 - dev: true - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /refractor@3.6.0: - resolution: {integrity: sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==} - dependencies: - hastscript: 6.0.0 - parse-entities: 2.0.0 - prismjs: 1.27.0 - dev: false - - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - dev: false - - /rehype-katex@7.0.1: - resolution: {integrity: sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==} - dependencies: - '@types/hast': 3.0.4 - '@types/katex': 0.16.7 - hast-util-from-html-isomorphic: 2.0.0 - hast-util-to-text: 4.0.2 - katex: 0.16.11 - unist-util-visit-parents: 6.0.1 - vfile: 6.0.3 - dev: false - - /rehype-raw@7.0.0: - resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} - dependencies: - '@types/hast': 3.0.4 - hast-util-raw: 9.0.4 - vfile: 6.0.3 - dev: false - - /remark-gfm@4.0.0: - resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} - dependencies: - '@types/mdast': 4.0.4 - mdast-util-gfm: 3.0.0 - micromark-extension-gfm: 3.0.0 - remark-parse: 11.0.0 - remark-stringify: 11.0.0 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - dev: false - - /remark-math@6.0.0: - resolution: {integrity: sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==} - dependencies: - '@types/mdast': 4.0.4 - mdast-util-math: 3.0.0 - micromark-extension-math: 3.1.0 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - dev: false - - /remark-parse@11.0.0: - resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} - dependencies: - '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.1 - micromark-util-types: 2.0.0 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - dev: false - - /remark-rehype@11.1.0: - resolution: {integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==} - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - mdast-util-to-hast: 13.2.0 - unified: 11.0.5 - vfile: 6.0.3 - dev: false - - /remark-stringify@11.0.0: - resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} - dependencies: - '@types/mdast': 4.0.4 - mdast-util-to-markdown: 2.1.0 - unified: 11.0.5 - dev: false - - /remove-accents@0.5.0: - resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} - dev: false - - /resize-observer-polyfill@1.5.1: - resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} - dev: false - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.15.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - dependencies: - glob: 7.2.3 - dev: false - - /rollup@4.21.2: - resolution: {integrity: sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.21.2 - '@rollup/rollup-android-arm64': 4.21.2 - '@rollup/rollup-darwin-arm64': 4.21.2 - '@rollup/rollup-darwin-x64': 4.21.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.21.2 - '@rollup/rollup-linux-arm-musleabihf': 4.21.2 - '@rollup/rollup-linux-arm64-gnu': 4.21.2 - '@rollup/rollup-linux-arm64-musl': 4.21.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.21.2 - '@rollup/rollup-linux-riscv64-gnu': 4.21.2 - '@rollup/rollup-linux-s390x-gnu': 4.21.2 - '@rollup/rollup-linux-x64-gnu': 4.21.2 - '@rollup/rollup-linux-x64-musl': 4.21.2 - '@rollup/rollup-win32-arm64-msvc': 4.21.2 - '@rollup/rollup-win32-ia32-msvc': 4.21.2 - '@rollup/rollup-win32-x64-msvc': 4.21.2 - fsevents: 2.3.3 - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - dependencies: - tslib: 2.7.0 - dev: true - - /sass-embedded-android-arm64@1.78.0: - resolution: {integrity: sha512-2sAr11EgwPudAuyk4Ite+fWGYJspiFSiZDU2D8/vjjI7BaB9FG6ksYqww3svoMMnjPUWBCjKPDELpZTxViLJbw==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-android-arm@1.78.0: - resolution: {integrity: sha512-YM6nrmKsj+ImaSTd96F+jzbWSbhPkRN4kedbLgIJ5FsILNa9NAqhmrCQz9pdcjuAhyfxWImdUACsT23CPGENZQ==} - engines: {node: '>=14.0.0'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-android-ia32@1.78.0: - resolution: {integrity: sha512-TyJOo4TgnHpOfC/PfqCBqd+jGRanWoRd4Br/0KAfIvaIFjTGIPdk26vUyDVugV1J8QUEY4INGE8EXAuDeRldUQ==} - engines: {node: '>=14.0.0'} - cpu: [ia32] - os: [android] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-android-riscv64@1.78.0: - resolution: {integrity: sha512-wwajpsVRuhb7ixrkA3Yu60V2LtROYn45PIYeda30/MrMJi9k3xEqHLhodTexFm6wZoKclGSDZ6L9U5q0XyRKiQ==} - engines: {node: '>=14.0.0'} - cpu: [riscv64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-android-x64@1.78.0: - resolution: {integrity: sha512-k5l66PO0LgSHMDbDzAQ/vqrXMlJ3r42ZHJA8MJvUbA6sQxTzDS381V7L+EhOATwyI225j2FhEeTHW6rr4WBQzA==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-darwin-arm64@1.78.0: - resolution: {integrity: sha512-3JaxceFSR6N+a22hPYYkj1p45eBaWTt/M8MPTbfzU3TGZrU9bmRX7WlUVtXTo1yYI2iMf22nCv0PQ5ExFF3FMQ==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-darwin-x64@1.78.0: - resolution: {integrity: sha512-UMTijqE3fJ8vEaaD7GPG7G3GsHuPKOdpS8vuA2v2uwO3BPFp/rEKah66atvGqvGO+0JYApkSv0YTnnexSrkHIQ==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-linux-arm64@1.78.0: - resolution: {integrity: sha512-juMIMpp3DIAiQ842y+boqh0u2SjN4m3mDKrDfMuBznj8DSQoy9J/3e4hLh3g+p0/j83WuROu5nNoYxm2Xz8rww==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-linux-arm@1.78.0: - resolution: {integrity: sha512-JafT+Co0RK8oO3g9TfVRuG7tkYeh35yDGTgqCFxLrktnkiw5pmIagCfpjxk5GBcSfJMOzhCgclTCDJWAuHGuMQ==} - engines: {node: '>=14.0.0'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-linux-ia32@1.78.0: - resolution: {integrity: sha512-Gy8GW5g6WX9t8CT2Dto5AL6ikB+pG7aAXWXvfu3RFHktixSwSbyy6CeGqSk1t0xyJCFkQQA/V8HU9bNdeHiBxg==} - engines: {node: '>=14.0.0'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-linux-musl-arm64@1.78.0: - resolution: {integrity: sha512-Lu/TlRHbe9aJY7B7PwWCJz7pTT5Rc50VkApWEmPiU/nu0mGbSpg0Xwar6pNeG8+98ubgKKdRb01N3bvclf5a4A==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-linux-musl-arm@1.78.0: - resolution: {integrity: sha512-DUVXtcsfsiOJ2Zwp4Y3T6KZWX8h0gWpzmFUrx+gSIbg67vV8Ww2DWMjWRwqLe7HOLTYBegMBYpMgMgZiPtXhIA==} - engines: {node: '>=14.0.0'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-linux-musl-ia32@1.78.0: - resolution: {integrity: sha512-1E5ywUnq6MRPAecr2r/vDOBr93wXyculEmfyF5JRG8mUufMaxGIhfx64OQE6Drjs+EDURcYZ+Qcg6/ubJWqhcw==} - engines: {node: '>=14.0.0'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-linux-musl-riscv64@1.78.0: - resolution: {integrity: sha512-YvQEvX7ctn5BwC79+HBagDYIciEkwcl2NLgoydmEsBO/0+ncMKSGnjsn/iRzErbq1KJNyjGEni8eSHlrtQI1vQ==} - engines: {node: '>=14.0.0'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-linux-musl-x64@1.78.0: - resolution: {integrity: sha512-azdUcZZvZmtUBslIKr2/l4aQrTX7BvO96TD0GLdWz9vuXZrokYm09AJZEnb5j6Pk5I4Xr0yM6BG1Vgcbzqi5Zg==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-linux-riscv64@1.78.0: - resolution: {integrity: sha512-g8M6vqHMjZUoH9C1WJsgwu+qmwdJAAMDaJTM1emeAScUZMTaQGzm+Q6C5oSGnAGR3XLT/drgbHhbmruXDgkdeQ==} - engines: {node: '>=14.0.0'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-linux-x64@1.78.0: - resolution: {integrity: sha512-m997ThzpMwql4u6LzZCoHPIQkgK6bbLPLc7ydemo2Wusqzh6j8XAGxVT5oANp6s2Dmj+yh49pKDozal+tzEX9w==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-win32-arm64@1.78.0: - resolution: {integrity: sha512-qTLIIC5URYRmeuYYllfoL0K1cHSUd+f3sFHAA6fjtdgf288usd6ToCbWpuFb0BtVceEfGQX8lEp+teOG7n7Quw==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-win32-ia32@1.78.0: - resolution: {integrity: sha512-BrOWh18T6Y9xgCokGXElEnd8j03fO4W83bwJ9wHRRkrQWaeHtHs3XWW0fX1j2brngWUTjU+jcYUijWF1Z60krw==} - engines: {node: '>=14.0.0'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /sass-embedded-win32-x64@1.78.0: - resolution: {integrity: sha512-C14iFDJd7oGhmQehRiEL7GtzMmLwubcDqsBarQ+u9LbHoDlUQfIPd7y8mVtNgtxJCdrAO/jc5qR4C+85yE3xPQ==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /sass-embedded@1.78.0: - resolution: {integrity: sha512-NR2kvhWVFABmBm0AqgFw9OweQycs0Qs+/teJ9Su+BUY7up+f8S5F/Zi+7QtAqJlewsQyUNfzm1vRuM+20lBwRQ==} - engines: {node: '>=16.0.0'} - hasBin: true - dependencies: - '@bufbuild/protobuf': 1.10.0 - buffer-builder: 0.2.0 - immutable: 4.3.7 - rxjs: 7.8.1 - supports-color: 8.1.1 - varint: 6.0.0 - optionalDependencies: - sass-embedded-android-arm: 1.78.0 - sass-embedded-android-arm64: 1.78.0 - sass-embedded-android-ia32: 1.78.0 - sass-embedded-android-riscv64: 1.78.0 - sass-embedded-android-x64: 1.78.0 - sass-embedded-darwin-arm64: 1.78.0 - sass-embedded-darwin-x64: 1.78.0 - sass-embedded-linux-arm: 1.78.0 - sass-embedded-linux-arm64: 1.78.0 - sass-embedded-linux-ia32: 1.78.0 - sass-embedded-linux-musl-arm: 1.78.0 - sass-embedded-linux-musl-arm64: 1.78.0 - sass-embedded-linux-musl-ia32: 1.78.0 - sass-embedded-linux-musl-riscv64: 1.78.0 - sass-embedded-linux-musl-x64: 1.78.0 - sass-embedded-linux-riscv64: 1.78.0 - sass-embedded-linux-x64: 1.78.0 - sass-embedded-win32-arm64: 1.78.0 - sass-embedded-win32-ia32: 1.78.0 - sass-embedded-win32-x64: 1.78.0 - dev: true - - /scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - dependencies: - loose-envify: 1.4.0 - dev: false - - /screenfull@5.2.0: - resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} - engines: {node: '>=0.10.0'} - dev: false - - /scroll-into-view-if-needed@3.1.0: - resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} - dependencies: - compute-scroll-into-view: 3.1.0 - dev: false - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - dev: false - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.2 - dev: false - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true - - /source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - dev: true - - /space-separated-tokens@1.1.5: - resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} - dev: false - - /space-separated-tokens@2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - dev: false - - /string-convert@0.2.1: - resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} - dev: false - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - dev: true - - /stringify-entities@4.0.4: - resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} - dependencies: - character-entities-html4: 2.1.0 - character-entities-legacy: 3.0.0 - dev: false - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /style-mod@4.1.2: - resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==} - dev: false - - /style-to-object@1.0.7: - resolution: {integrity: sha512-uSjr59G5u6fbxUfKbb8GcqMGT3Xs9v5IbPkjb0S16GyOeBLAzSRK0CixBv5YrYvzO6TDLzIS6QCn78tkqWngPw==} - dependencies: - inline-style-parser: 0.2.3 - dev: false - - /stylis@4.3.4: - resolution: {integrity: sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==} - dev: false - - /sucrase@3.35.0: - resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - commander: 4.1.1 - glob: 10.4.5 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.6 - ts-interface-checker: 0.1.13 - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /tailwindcss@3.4.10: - resolution: {integrity: sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==} - engines: {node: '>=14.0.0'} - hasBin: true - dependencies: - '@alloc/quick-lru': 5.2.0 - arg: 5.0.2 - chokidar: 3.6.0 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.2 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.21.6 - lilconfig: 2.1.0 - micromatch: 4.0.8 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.1.0 - postcss: 8.4.45 - postcss-import: 15.1.0(postcss@8.4.45) - postcss-js: 4.0.1(postcss@8.4.45) - postcss-load-config: 4.0.2(postcss@8.4.45) - postcss-nested: 6.2.0(postcss@8.4.45) - postcss-selector-parser: 6.1.2 - resolve: 1.22.8 - sucrase: 3.35.0 - transitivePeerDependencies: - - ts-node - dev: true - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - dependencies: - thenify: 3.3.1 - dev: true - - /thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - dependencies: - any-promise: 1.3.0 - dev: true - - /throttle-debounce@5.0.2: - resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} - engines: {node: '>=12.22'} - dev: false - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /toggle-selection@1.0.6: - resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} - dev: false - - /trim-lines@3.0.1: - resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} - dev: false - - /trough@2.2.0: - resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - dev: false - - /true-myth@4.1.1: - resolution: {integrity: sha512-rqy30BSpxPznbbTcAcci90oZ1YR4DqvKcNXNerG5gQBU2v4jk0cygheiul5J6ExIMrgDVuanv/MkGfqZbKrNNg==} - engines: {node: 10.* || >= 12.*} - dev: true - - /ts-api-utils@1.3.0(typescript@5.5.4): - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.5.4 - dev: true - - /ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - dev: true - - /ts-morph@13.0.3: - resolution: {integrity: sha512-pSOfUMx8Ld/WUreoSzvMFQG5i9uEiWIsBYjpU9+TTASOeUa89j5HykomeqVULm1oqWtBdleI3KEFRLrlA3zGIw==} - dependencies: - '@ts-morph/common': 0.12.3 - code-block-writer: 11.0.3 - dev: true - - /ts-prune@0.10.3: - resolution: {integrity: sha512-iS47YTbdIcvN8Nh/1BFyziyUqmjXz7GVzWu02RaZXqb+e/3Qe1B7IQ4860krOeCGUeJmterAlaM2FRH0Ue0hjw==} - hasBin: true - dependencies: - commander: 6.2.1 - cosmiconfig: 7.1.0 - json5: 2.2.3 - lodash: 4.17.21 - true-myth: 4.1.1 - ts-morph: 13.0.3 - dev: true - - /tslib@2.7.0: - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /typescript-eslint@8.4.0(eslint@9.9.1)(typescript@5.5.4): - resolution: {integrity: sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 8.4.0(@typescript-eslint/parser@8.4.0)(eslint@9.9.1)(typescript@5.5.4) - '@typescript-eslint/parser': 8.4.0(eslint@9.9.1)(typescript@5.5.4) - '@typescript-eslint/utils': 8.4.0(eslint@9.9.1)(typescript@5.5.4) - typescript: 5.5.4 - transitivePeerDependencies: - - eslint - - supports-color - dev: true - - /typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} - engines: {node: '>=14.17'} - hasBin: true - - /undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - dev: true - - /unified@11.0.5: - resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} - dependencies: - '@types/unist': 3.0.3 - bail: 2.0.2 - devlop: 1.1.0 - extend: 3.0.2 - is-plain-obj: 4.1.0 - trough: 2.2.0 - vfile: 6.0.3 - dev: false - - /unist-util-find-after@5.0.0: - resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} - dependencies: - '@types/unist': 3.0.3 - unist-util-is: 6.0.0 - dev: false - - /unist-util-is@6.0.0: - resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} - dependencies: - '@types/unist': 3.0.3 - dev: false - - /unist-util-position@5.0.0: - resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} - dependencies: - '@types/unist': 3.0.3 - dev: false - - /unist-util-remove-position@5.0.0: - resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} - dependencies: - '@types/unist': 3.0.3 - unist-util-visit: 5.0.0 - dev: false - - /unist-util-stringify-position@4.0.0: - resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} - dependencies: - '@types/unist': 3.0.3 - dev: false - - /unist-util-visit-parents@6.0.1: - resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} - dependencies: - '@types/unist': 3.0.3 - unist-util-is: 6.0.0 - dev: false - - /unist-util-visit@5.0.0: - resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - dependencies: - '@types/unist': 3.0.3 - unist-util-is: 6.0.0 - unist-util-visit-parents: 6.0.1 - dev: false - - /unload@2.2.0: - resolution: {integrity: sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==} - dependencies: - '@babel/runtime': 7.25.6 - detect-node: 2.1.0 - dev: false - - /update-browserslist-db@1.1.0(browserslist@4.23.3): - resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.3 - escalade: 3.2.0 - picocolors: 1.1.0 - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - - /use-sync-external-store@1.2.2(react@18.3.1): - resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - react: 18.3.1 - dev: false - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true - - /varint@6.0.0: - resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} - dev: true - - /vfile-location@5.0.3: - resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} - dependencies: - '@types/unist': 3.0.3 - vfile: 6.0.3 - dev: false - - /vfile-message@4.0.2: - resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} - dependencies: - '@types/unist': 3.0.3 - unist-util-stringify-position: 4.0.0 - dev: false - - /vfile@6.0.3: - resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - dependencies: - '@types/unist': 3.0.3 - vfile-message: 4.0.2 - dev: false - - /vite@5.4.3(@types/node@22.5.4)(sass-embedded@1.78.0): - resolution: {integrity: sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - '@types/node': 22.5.4 - esbuild: 0.21.5 - postcss: 8.4.45 - rollup: 4.21.2 - sass-embedded: 1.78.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /w3c-keyname@2.2.8: - resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} - dev: false - - /web-namespaces@2.0.1: - resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - dev: false - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: false - - /xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - dev: false - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - dev: true - - /yaml@2.5.1: - resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} - engines: {node: '>= 14'} - hasBin: true - dev: true - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true - - /zustand@4.5.5(@types/react@18.3.5)(react@18.3.1): - resolution: {integrity: sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==} - engines: {node: '>=12.7.0'} - peerDependencies: - '@types/react': '>=16.8' - immer: '>=9.0.6' - react: '>=16.8' - peerDependenciesMeta: - '@types/react': - optional: true - immer: - optional: true - react: - optional: true - dependencies: - '@types/react': 18.3.5 - react: 18.3.1 - use-sync-external-store: 1.2.2(react@18.3.1) - dev: false - - /zwitch@2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - dev: false diff --git a/projects/web/postcss.config.js b/projects/web/postcss.config.js deleted file mode 100644 index 2e7af2b7f1a6f391da1631d93968a9d487ba977d..0000000000000000000000000000000000000000 --- a/projects/web/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/projects/web/public/iconfont.js b/projects/web/public/iconfont.js deleted file mode 100644 index bb790a138cc4d2211f67ac6738b94fcf43b30350..0000000000000000000000000000000000000000 --- a/projects/web/public/iconfont.js +++ /dev/null @@ -1 +0,0 @@ -window._iconfont_svg_string_4519198='',(h=>{var a=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,i,t,v,c,d=function(a,l){l.parentNode.insertBefore(a,l)};if(a&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_4519198,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?d(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),o()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(t=o,v=h.document,c=!1,m(),v.onreadystatechange=function(){"complete"==v.readyState&&(v.onreadystatechange=null,z())})}function z(){c||(c=!0,t())}function m(){try{v.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}z()}})(window); \ No newline at end of file diff --git a/projects/web/public/logo.svg b/projects/web/public/logo.svg deleted file mode 100644 index 17f246300728fa672867c1cdc9c317646bad5925..0000000000000000000000000000000000000000 --- a/projects/web/public/logo.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/web/public/pdfjs-dist/build/pdf.mjs b/projects/web/public/pdfjs-dist/build/pdf.mjs deleted file mode 100644 index f995c0db63d8ca0424c95e45803b05cf4e6c9991..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/build/pdf.mjs +++ /dev/null @@ -1,19814 +0,0 @@ -/** - * @licstart The following is the entire license notice for the - * JavaScript code in this page - * - * Copyright 2023 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @licend The above is the entire license notice for the - * JavaScript code in this page - */ - -/******/ var __webpack_modules__ = ({ - -/***/ 976: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - - -// EXPORTS -__webpack_require__.d(__webpack_exports__, { - AnnotationLayer: () => (/* binding */ AnnotationLayer), - FreeTextAnnotationElement: () => (/* binding */ FreeTextAnnotationElement), - InkAnnotationElement: () => (/* binding */ InkAnnotationElement), - StampAnnotationElement: () => (/* binding */ StampAnnotationElement) -}); - -// EXTERNAL MODULE: ./src/shared/util.js -var util = __webpack_require__(292); -// EXTERNAL MODULE: ./src/display/display_utils.js -var display_utils = __webpack_require__(419); -// EXTERNAL MODULE: ./src/display/annotation_storage.js -var annotation_storage = __webpack_require__(792); -;// CONCATENATED MODULE: ./src/shared/scripting_utils.js -function makeColorComp(n) { - return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, "0"); -} -function scaleAndClamp(x) { - return Math.max(0, Math.min(255, 255 * x)); -} -class ColorConverters { - static CMYK_G([c, y, m, k]) { - return ["G", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)]; - } - static G_CMYK([g]) { - return ["CMYK", 0, 0, 0, 1 - g]; - } - static G_RGB([g]) { - return ["RGB", g, g, g]; - } - static G_rgb([g]) { - g = scaleAndClamp(g); - return [g, g, g]; - } - static G_HTML([g]) { - const G = makeColorComp(g); - return `#${G}${G}${G}`; - } - static RGB_G([r, g, b]) { - return ["G", 0.3 * r + 0.59 * g + 0.11 * b]; - } - static RGB_rgb(color) { - return color.map(scaleAndClamp); - } - static RGB_HTML(color) { - return `#${color.map(makeColorComp).join("")}`; - } - static T_HTML() { - return "#00000000"; - } - static T_rgb() { - return [null]; - } - static CMYK_RGB([c, y, m, k]) { - return ["RGB", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)]; - } - static CMYK_rgb([c, y, m, k]) { - return [scaleAndClamp(1 - Math.min(1, c + k)), scaleAndClamp(1 - Math.min(1, m + k)), scaleAndClamp(1 - Math.min(1, y + k))]; - } - static CMYK_HTML(components) { - const rgb = this.CMYK_RGB(components).slice(1); - return this.RGB_HTML(rgb); - } - static RGB_CMYK([r, g, b]) { - const c = 1 - r; - const m = 1 - g; - const y = 1 - b; - const k = Math.min(c, m, y); - return ["CMYK", c, m, y, k]; - } -} - -// EXTERNAL MODULE: ./src/display/xfa_layer.js -var xfa_layer = __webpack_require__(284); -;// CONCATENATED MODULE: ./src/display/annotation_layer.js - - - - - -const DEFAULT_TAB_INDEX = 1000; -const DEFAULT_FONT_SIZE = 9; -const GetElementsByNameSet = new WeakSet(); -function getRectDims(rect) { - return { - width: rect[2] - rect[0], - height: rect[3] - rect[1] - }; -} -class AnnotationElementFactory { - static create(parameters) { - const subtype = parameters.data.annotationType; - switch (subtype) { - case util.AnnotationType.LINK: - return new LinkAnnotationElement(parameters); - case util.AnnotationType.TEXT: - return new TextAnnotationElement(parameters); - case util.AnnotationType.WIDGET: - const fieldType = parameters.data.fieldType; - switch (fieldType) { - case "Tx": - return new TextWidgetAnnotationElement(parameters); - case "Btn": - if (parameters.data.radioButton) { - return new RadioButtonWidgetAnnotationElement(parameters); - } else if (parameters.data.checkBox) { - return new CheckboxWidgetAnnotationElement(parameters); - } - return new PushButtonWidgetAnnotationElement(parameters); - case "Ch": - return new ChoiceWidgetAnnotationElement(parameters); - case "Sig": - return new SignatureWidgetAnnotationElement(parameters); - } - return new WidgetAnnotationElement(parameters); - case util.AnnotationType.POPUP: - return new PopupAnnotationElement(parameters); - case util.AnnotationType.FREETEXT: - return new FreeTextAnnotationElement(parameters); - case util.AnnotationType.LINE: - return new LineAnnotationElement(parameters); - case util.AnnotationType.SQUARE: - return new SquareAnnotationElement(parameters); - case util.AnnotationType.CIRCLE: - return new CircleAnnotationElement(parameters); - case util.AnnotationType.POLYLINE: - return new PolylineAnnotationElement(parameters); - case util.AnnotationType.CARET: - return new CaretAnnotationElement(parameters); - case util.AnnotationType.INK: - return new InkAnnotationElement(parameters); - case util.AnnotationType.POLYGON: - return new PolygonAnnotationElement(parameters); - case util.AnnotationType.HIGHLIGHT: - return new HighlightAnnotationElement(parameters); - case util.AnnotationType.UNDERLINE: - return new UnderlineAnnotationElement(parameters); - case util.AnnotationType.SQUIGGLY: - return new SquigglyAnnotationElement(parameters); - case util.AnnotationType.STRIKEOUT: - return new StrikeOutAnnotationElement(parameters); - case util.AnnotationType.STAMP: - return new StampAnnotationElement(parameters); - case util.AnnotationType.FILEATTACHMENT: - return new FileAttachmentAnnotationElement(parameters); - default: - return new AnnotationElement(parameters); - } - } -} -class AnnotationElement { - #updates = null; - #hasBorder = false; - constructor(parameters, { - isRenderable = false, - ignoreBorder = false, - createQuadrilaterals = false - } = {}) { - this.isRenderable = isRenderable; - this.data = parameters.data; - this.layer = parameters.layer; - this.linkService = parameters.linkService; - this.downloadManager = parameters.downloadManager; - this.imageResourcesPath = parameters.imageResourcesPath; - this.renderForms = parameters.renderForms; - this.svgFactory = parameters.svgFactory; - this.annotationStorage = parameters.annotationStorage; - this.enableScripting = parameters.enableScripting; - this.hasJSActions = parameters.hasJSActions; - this._fieldObjects = parameters.fieldObjects; - this.parent = parameters.parent; - if (isRenderable) { - this.container = this._createContainer(ignoreBorder); - } - if (createQuadrilaterals) { - this._createQuadrilaterals(); - } - } - static _hasPopupData({ - titleObj, - contentsObj, - richText - }) { - return !!(titleObj?.str || contentsObj?.str || richText?.str); - } - get hasPopupData() { - return AnnotationElement._hasPopupData(this.data); - } - updateEdited(params) { - if (!this.container) { - return; - } - this.#updates ||= { - rect: this.data.rect.slice(0) - }; - const { - rect - } = params; - if (rect) { - this.#setRectEdited(rect); - } - } - resetEdited() { - if (!this.#updates) { - return; - } - this.#setRectEdited(this.#updates.rect); - this.#updates = null; - } - #setRectEdited(rect) { - const { - container: { - style - }, - data: { - rect: currentRect, - rotation - }, - parent: { - viewport: { - rawDims: { - pageWidth, - pageHeight, - pageX, - pageY - } - } - } - } = this; - currentRect?.splice(0, 4, ...rect); - const { - width, - height - } = getRectDims(rect); - style.left = `${100 * (rect[0] - pageX) / pageWidth}%`; - style.top = `${100 * (pageHeight - rect[3] + pageY) / pageHeight}%`; - if (rotation === 0) { - style.width = `${100 * width / pageWidth}%`; - style.height = `${100 * height / pageHeight}%`; - } else { - this.setRotation(rotation); - } - } - _createContainer(ignoreBorder) { - const { - data, - parent: { - page, - viewport - } - } = this; - const container = document.createElement("section"); - container.setAttribute("data-annotation-id", data.id); - if (!(this instanceof WidgetAnnotationElement)) { - container.tabIndex = DEFAULT_TAB_INDEX; - } - const { - style - } = container; - style.zIndex = this.parent.zIndex++; - if (data.popupRef) { - container.setAttribute("aria-haspopup", "dialog"); - } - if (data.alternativeText) { - container.title = data.alternativeText; - } - if (data.noRotate) { - container.classList.add("norotate"); - } - if (!data.rect || this instanceof PopupAnnotationElement) { - const { - rotation - } = data; - if (!data.hasOwnCanvas && rotation !== 0) { - this.setRotation(rotation, container); - } - return container; - } - const { - width, - height - } = getRectDims(data.rect); - if (!ignoreBorder && data.borderStyle.width > 0) { - style.borderWidth = `${data.borderStyle.width}px`; - const horizontalRadius = data.borderStyle.horizontalCornerRadius; - const verticalRadius = data.borderStyle.verticalCornerRadius; - if (horizontalRadius > 0 || verticalRadius > 0) { - const radius = `calc(${horizontalRadius}px * var(--scale-factor)) / calc(${verticalRadius}px * var(--scale-factor))`; - style.borderRadius = radius; - } else if (this instanceof RadioButtonWidgetAnnotationElement) { - const radius = `calc(${width}px * var(--scale-factor)) / calc(${height}px * var(--scale-factor))`; - style.borderRadius = radius; - } - switch (data.borderStyle.style) { - case util.AnnotationBorderStyleType.SOLID: - style.borderStyle = "solid"; - break; - case util.AnnotationBorderStyleType.DASHED: - style.borderStyle = "dashed"; - break; - case util.AnnotationBorderStyleType.BEVELED: - (0,util.warn)("Unimplemented border style: beveled"); - break; - case util.AnnotationBorderStyleType.INSET: - (0,util.warn)("Unimplemented border style: inset"); - break; - case util.AnnotationBorderStyleType.UNDERLINE: - style.borderBottomStyle = "solid"; - break; - default: - break; - } - const borderColor = data.borderColor || null; - if (borderColor) { - this.#hasBorder = true; - style.borderColor = util.Util.makeHexColor(borderColor[0] | 0, borderColor[1] | 0, borderColor[2] | 0); - } else { - style.borderWidth = 0; - } - } - const rect = util.Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]); - const { - pageWidth, - pageHeight, - pageX, - pageY - } = viewport.rawDims; - style.left = `${100 * (rect[0] - pageX) / pageWidth}%`; - style.top = `${100 * (rect[1] - pageY) / pageHeight}%`; - const { - rotation - } = data; - if (data.hasOwnCanvas || rotation === 0) { - style.width = `${100 * width / pageWidth}%`; - style.height = `${100 * height / pageHeight}%`; - } else { - this.setRotation(rotation, container); - } - return container; - } - setRotation(angle, container = this.container) { - if (!this.data.rect) { - return; - } - const { - pageWidth, - pageHeight - } = this.parent.viewport.rawDims; - const { - width, - height - } = getRectDims(this.data.rect); - let elementWidth, elementHeight; - if (angle % 180 === 0) { - elementWidth = 100 * width / pageWidth; - elementHeight = 100 * height / pageHeight; - } else { - elementWidth = 100 * height / pageWidth; - elementHeight = 100 * width / pageHeight; - } - container.style.width = `${elementWidth}%`; - container.style.height = `${elementHeight}%`; - container.setAttribute("data-main-rotation", (360 - angle) % 360); - } - get _commonActions() { - const setColor = (jsName, styleName, event) => { - const color = event.detail[jsName]; - const colorType = color[0]; - const colorArray = color.slice(1); - event.target.style[styleName] = ColorConverters[`${colorType}_HTML`](colorArray); - this.annotationStorage.setValue(this.data.id, { - [styleName]: ColorConverters[`${colorType}_rgb`](colorArray) - }); - }; - return (0,util.shadow)(this, "_commonActions", { - display: event => { - const { - display - } = event.detail; - const hidden = display % 2 === 1; - this.container.style.visibility = hidden ? "hidden" : "visible"; - this.annotationStorage.setValue(this.data.id, { - noView: hidden, - noPrint: display === 1 || display === 2 - }); - }, - print: event => { - this.annotationStorage.setValue(this.data.id, { - noPrint: !event.detail.print - }); - }, - hidden: event => { - const { - hidden - } = event.detail; - this.container.style.visibility = hidden ? "hidden" : "visible"; - this.annotationStorage.setValue(this.data.id, { - noPrint: hidden, - noView: hidden - }); - }, - focus: event => { - setTimeout(() => event.target.focus({ - preventScroll: false - }), 0); - }, - userName: event => { - event.target.title = event.detail.userName; - }, - readonly: event => { - event.target.disabled = event.detail.readonly; - }, - required: event => { - this._setRequired(event.target, event.detail.required); - }, - bgColor: event => { - setColor("bgColor", "backgroundColor", event); - }, - fillColor: event => { - setColor("fillColor", "backgroundColor", event); - }, - fgColor: event => { - setColor("fgColor", "color", event); - }, - textColor: event => { - setColor("textColor", "color", event); - }, - borderColor: event => { - setColor("borderColor", "borderColor", event); - }, - strokeColor: event => { - setColor("strokeColor", "borderColor", event); - }, - rotation: event => { - const angle = event.detail.rotation; - this.setRotation(angle); - this.annotationStorage.setValue(this.data.id, { - rotation: angle - }); - } - }); - } - _dispatchEventFromSandbox(actions, jsEvent) { - const commonActions = this._commonActions; - for (const name of Object.keys(jsEvent.detail)) { - const action = actions[name] || commonActions[name]; - action?.(jsEvent); - } - } - _setDefaultPropertiesFromJS(element) { - if (!this.enableScripting) { - return; - } - const storedData = this.annotationStorage.getRawValue(this.data.id); - if (!storedData) { - return; - } - const commonActions = this._commonActions; - for (const [actionName, detail] of Object.entries(storedData)) { - const action = commonActions[actionName]; - if (action) { - const eventProxy = { - detail: { - [actionName]: detail - }, - target: element - }; - action(eventProxy); - delete storedData[actionName]; - } - } - } - _createQuadrilaterals() { - if (!this.container) { - return; - } - const { - quadPoints - } = this.data; - if (!quadPoints) { - return; - } - const [rectBlX, rectBlY, rectTrX, rectTrY] = this.data.rect; - if (quadPoints.length === 1) { - const [, { - x: trX, - y: trY - }, { - x: blX, - y: blY - }] = quadPoints[0]; - if (rectTrX === trX && rectTrY === trY && rectBlX === blX && rectBlY === blY) { - return; - } - } - const { - style - } = this.container; - let svgBuffer; - if (this.#hasBorder) { - const { - borderColor, - borderWidth - } = style; - style.borderWidth = 0; - svgBuffer = ["url('data:image/svg+xml;utf8,", ``, ``]; - this.container.classList.add("hasBorder"); - } - const width = rectTrX - rectBlX; - const height = rectTrY - rectBlY; - const { - svgFactory - } = this; - const svg = svgFactory.createElement("svg"); - svg.classList.add("quadrilateralsContainer"); - svg.setAttribute("width", 0); - svg.setAttribute("height", 0); - const defs = svgFactory.createElement("defs"); - svg.append(defs); - const clipPath = svgFactory.createElement("clipPath"); - const id = `clippath_${this.data.id}`; - clipPath.setAttribute("id", id); - clipPath.setAttribute("clipPathUnits", "objectBoundingBox"); - defs.append(clipPath); - for (const [, { - x: trX, - y: trY - }, { - x: blX, - y: blY - }] of quadPoints) { - const rect = svgFactory.createElement("rect"); - const x = (blX - rectBlX) / width; - const y = (rectTrY - trY) / height; - const rectWidth = (trX - blX) / width; - const rectHeight = (trY - blY) / height; - rect.setAttribute("x", x); - rect.setAttribute("y", y); - rect.setAttribute("width", rectWidth); - rect.setAttribute("height", rectHeight); - clipPath.append(rect); - svgBuffer?.push(``); - } - if (this.#hasBorder) { - svgBuffer.push(`')`); - style.backgroundImage = svgBuffer.join(""); - } - this.container.append(svg); - this.container.style.clipPath = `url(#${id})`; - } - _createPopup() { - const { - container, - data - } = this; - container.setAttribute("aria-haspopup", "dialog"); - const popup = new PopupAnnotationElement({ - data: { - color: data.color, - titleObj: data.titleObj, - modificationDate: data.modificationDate, - contentsObj: data.contentsObj, - richText: data.richText, - parentRect: data.rect, - borderStyle: 0, - id: `popup_${data.id}`, - rotation: data.rotation - }, - parent: this.parent, - elements: [this] - }); - this.parent.div.append(popup.render()); - } - render() { - (0,util.unreachable)("Abstract method `AnnotationElement.render` called"); - } - _getElementsByName(name, skipId = null) { - const fields = []; - if (this._fieldObjects) { - const fieldObj = this._fieldObjects[name]; - if (fieldObj) { - for (const { - page, - id, - exportValues - } of fieldObj) { - if (page === -1) { - continue; - } - if (id === skipId) { - continue; - } - const exportValue = typeof exportValues === "string" ? exportValues : null; - const domElement = document.querySelector(`[data-element-id="${id}"]`); - if (domElement && !GetElementsByNameSet.has(domElement)) { - (0,util.warn)(`_getElementsByName - element not allowed: ${id}`); - continue; - } - fields.push({ - id, - exportValue, - domElement - }); - } - } - return fields; - } - for (const domElement of document.getElementsByName(name)) { - const { - exportValue - } = domElement; - const id = domElement.getAttribute("data-element-id"); - if (id === skipId) { - continue; - } - if (!GetElementsByNameSet.has(domElement)) { - continue; - } - fields.push({ - id, - exportValue, - domElement - }); - } - return fields; - } - show() { - if (this.container) { - this.container.hidden = false; - } - this.popup?.maybeShow(); - } - hide() { - if (this.container) { - this.container.hidden = true; - } - this.popup?.forceHide(); - } - getElementsToTriggerPopup() { - return this.container; - } - addHighlightArea() { - const triggers = this.getElementsToTriggerPopup(); - if (Array.isArray(triggers)) { - for (const element of triggers) { - element.classList.add("highlightArea"); - } - } else { - triggers.classList.add("highlightArea"); - } - } - get _isEditable() { - return false; - } - _editOnDoubleClick() { - if (!this._isEditable) { - return; - } - const { - annotationEditorType: mode, - data: { - id: editId - } - } = this; - this.container.addEventListener("dblclick", () => { - this.linkService.eventBus?.dispatch("switchannotationeditormode", { - source: this, - mode, - editId - }); - }); - } -} -class LinkAnnotationElement extends AnnotationElement { - constructor(parameters, options = null) { - super(parameters, { - isRenderable: true, - ignoreBorder: !!options?.ignoreBorder, - createQuadrilaterals: true - }); - this.isTooltipOnly = parameters.data.isTooltipOnly; - } - render() { - const { - data, - linkService - } = this; - const link = document.createElement("a"); - link.setAttribute("data-element-id", data.id); - let isBound = false; - if (data.url) { - linkService.addLinkAttributes(link, data.url, data.newWindow); - isBound = true; - } else if (data.action) { - this._bindNamedAction(link, data.action); - isBound = true; - } else if (data.attachment) { - this.#bindAttachment(link, data.attachment, data.attachmentDest); - isBound = true; - } else if (data.setOCGState) { - this.#bindSetOCGState(link, data.setOCGState); - isBound = true; - } else if (data.dest) { - this._bindLink(link, data.dest); - isBound = true; - } else { - if (data.actions && (data.actions.Action || data.actions["Mouse Up"] || data.actions["Mouse Down"]) && this.enableScripting && this.hasJSActions) { - this._bindJSAction(link, data); - isBound = true; - } - if (data.resetForm) { - this._bindResetFormAction(link, data.resetForm); - isBound = true; - } else if (this.isTooltipOnly && !isBound) { - this._bindLink(link, ""); - isBound = true; - } - } - this.container.classList.add("linkAnnotation"); - if (isBound) { - this.container.append(link); - } - return this.container; - } - #setInternalLink() { - this.container.setAttribute("data-internal-link", ""); - } - _bindLink(link, destination) { - link.href = this.linkService.getDestinationHash(destination); - link.onclick = () => { - if (destination) { - this.linkService.goToDestination(destination); - } - return false; - }; - if (destination || destination === "") { - this.#setInternalLink(); - } - } - _bindNamedAction(link, action) { - link.href = this.linkService.getAnchorUrl(""); - link.onclick = () => { - this.linkService.executeNamedAction(action); - return false; - }; - this.#setInternalLink(); - } - #bindAttachment(link, attachment, dest = null) { - link.href = this.linkService.getAnchorUrl(""); - link.onclick = () => { - this.downloadManager?.openOrDownloadData(attachment.content, attachment.filename, dest); - return false; - }; - this.#setInternalLink(); - } - #bindSetOCGState(link, action) { - link.href = this.linkService.getAnchorUrl(""); - link.onclick = () => { - this.linkService.executeSetOCGState(action); - return false; - }; - this.#setInternalLink(); - } - _bindJSAction(link, data) { - link.href = this.linkService.getAnchorUrl(""); - const map = new Map([["Action", "onclick"], ["Mouse Up", "onmouseup"], ["Mouse Down", "onmousedown"]]); - for (const name of Object.keys(data.actions)) { - const jsName = map.get(name); - if (!jsName) { - continue; - } - link[jsName] = () => { - this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { - source: this, - detail: { - id: data.id, - name - } - }); - return false; - }; - } - if (!link.onclick) { - link.onclick = () => false; - } - this.#setInternalLink(); - } - _bindResetFormAction(link, resetForm) { - const otherClickAction = link.onclick; - if (!otherClickAction) { - link.href = this.linkService.getAnchorUrl(""); - } - this.#setInternalLink(); - if (!this._fieldObjects) { - (0,util.warn)(`_bindResetFormAction - "resetForm" action not supported, ` + "ensure that the `fieldObjects` parameter is provided."); - if (!otherClickAction) { - link.onclick = () => false; - } - return; - } - link.onclick = () => { - otherClickAction?.(); - const { - fields: resetFormFields, - refs: resetFormRefs, - include - } = resetForm; - const allFields = []; - if (resetFormFields.length !== 0 || resetFormRefs.length !== 0) { - const fieldIds = new Set(resetFormRefs); - for (const fieldName of resetFormFields) { - const fields = this._fieldObjects[fieldName] || []; - for (const { - id - } of fields) { - fieldIds.add(id); - } - } - for (const fields of Object.values(this._fieldObjects)) { - for (const field of fields) { - if (fieldIds.has(field.id) === include) { - allFields.push(field); - } - } - } - } else { - for (const fields of Object.values(this._fieldObjects)) { - allFields.push(...fields); - } - } - const storage = this.annotationStorage; - const allIds = []; - for (const field of allFields) { - const { - id - } = field; - allIds.push(id); - switch (field.type) { - case "text": - { - const value = field.defaultValue || ""; - storage.setValue(id, { - value - }); - break; - } - case "checkbox": - case "radiobutton": - { - const value = field.defaultValue === field.exportValues; - storage.setValue(id, { - value - }); - break; - } - case "combobox": - case "listbox": - { - const value = field.defaultValue || ""; - storage.setValue(id, { - value - }); - break; - } - default: - continue; - } - const domElement = document.querySelector(`[data-element-id="${id}"]`); - if (!domElement) { - continue; - } else if (!GetElementsByNameSet.has(domElement)) { - (0,util.warn)(`_bindResetFormAction - element not allowed: ${id}`); - continue; - } - domElement.dispatchEvent(new Event("resetform")); - } - if (this.enableScripting) { - this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { - source: this, - detail: { - id: "app", - ids: allIds, - name: "ResetForm" - } - }); - } - return false; - }; - } -} -class TextAnnotationElement extends AnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: true - }); - } - render() { - this.container.classList.add("textAnnotation"); - const image = document.createElement("img"); - image.src = this.imageResourcesPath + "annotation-" + this.data.name.toLowerCase() + ".svg"; - image.setAttribute("data-l10n-id", "pdfjs-text-annotation-type"); - image.setAttribute("data-l10n-args", JSON.stringify({ - type: this.data.name - })); - if (!this.data.popupRef && this.hasPopupData) { - this._createPopup(); - } - this.container.append(image); - return this.container; - } -} -class WidgetAnnotationElement extends AnnotationElement { - render() { - return this.container; - } - showElementAndHideCanvas(element) { - if (this.data.hasOwnCanvas) { - if (element.previousSibling?.nodeName === "CANVAS") { - element.previousSibling.hidden = true; - } - element.hidden = false; - } - } - _getKeyModifier(event) { - return util.FeatureTest.platform.isMac ? event.metaKey : event.ctrlKey; - } - _setEventListener(element, elementData, baseName, eventName, valueGetter) { - if (baseName.includes("mouse")) { - element.addEventListener(baseName, event => { - this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { - source: this, - detail: { - id: this.data.id, - name: eventName, - value: valueGetter(event), - shift: event.shiftKey, - modifier: this._getKeyModifier(event) - } - }); - }); - } else { - element.addEventListener(baseName, event => { - if (baseName === "blur") { - if (!elementData.focused || !event.relatedTarget) { - return; - } - elementData.focused = false; - } else if (baseName === "focus") { - if (elementData.focused) { - return; - } - elementData.focused = true; - } - if (!valueGetter) { - return; - } - this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { - source: this, - detail: { - id: this.data.id, - name: eventName, - value: valueGetter(event) - } - }); - }); - } - } - _setEventListeners(element, elementData, names, getter) { - for (const [baseName, eventName] of names) { - if (eventName === "Action" || this.data.actions?.[eventName]) { - if (eventName === "Focus" || eventName === "Blur") { - elementData ||= { - focused: false - }; - } - this._setEventListener(element, elementData, baseName, eventName, getter); - if (eventName === "Focus" && !this.data.actions?.Blur) { - this._setEventListener(element, elementData, "blur", "Blur", null); - } else if (eventName === "Blur" && !this.data.actions?.Focus) { - this._setEventListener(element, elementData, "focus", "Focus", null); - } - } - } - } - _setBackgroundColor(element) { - const color = this.data.backgroundColor || null; - element.style.backgroundColor = color === null ? "transparent" : util.Util.makeHexColor(color[0], color[1], color[2]); - } - _setTextStyle(element) { - const TEXT_ALIGNMENT = ["left", "center", "right"]; - const { - fontColor - } = this.data.defaultAppearanceData; - const fontSize = this.data.defaultAppearanceData.fontSize || DEFAULT_FONT_SIZE; - const style = element.style; - let computedFontSize; - const BORDER_SIZE = 2; - const roundToOneDecimal = x => Math.round(10 * x) / 10; - if (this.data.multiLine) { - const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE); - const numberOfLines = Math.round(height / (util.LINE_FACTOR * fontSize)) || 1; - const lineHeight = height / numberOfLines; - computedFontSize = Math.min(fontSize, roundToOneDecimal(lineHeight / util.LINE_FACTOR)); - } else { - const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE); - computedFontSize = Math.min(fontSize, roundToOneDecimal(height / util.LINE_FACTOR)); - } - style.fontSize = `calc(${computedFontSize}px * var(--scale-factor))`; - style.color = util.Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]); - if (this.data.textAlignment !== null) { - style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment]; - } - } - _setRequired(element, isRequired) { - if (isRequired) { - element.setAttribute("required", true); - } else { - element.removeAttribute("required"); - } - element.setAttribute("aria-required", isRequired); - } -} -class TextWidgetAnnotationElement extends WidgetAnnotationElement { - constructor(parameters) { - const isRenderable = parameters.renderForms || parameters.data.hasOwnCanvas || !parameters.data.hasAppearance && !!parameters.data.fieldValue; - super(parameters, { - isRenderable - }); - } - setPropertyOnSiblings(base, key, value, keyInStorage) { - const storage = this.annotationStorage; - for (const element of this._getElementsByName(base.name, base.id)) { - if (element.domElement) { - element.domElement[key] = value; - } - storage.setValue(element.id, { - [keyInStorage]: value - }); - } - } - render() { - const storage = this.annotationStorage; - const id = this.data.id; - this.container.classList.add("textWidgetAnnotation"); - let element = null; - if (this.renderForms) { - const storedData = storage.getValue(id, { - value: this.data.fieldValue - }); - let textContent = storedData.value || ""; - const maxLen = storage.getValue(id, { - charLimit: this.data.maxLen - }).charLimit; - if (maxLen && textContent.length > maxLen) { - textContent = textContent.slice(0, maxLen); - } - let fieldFormattedValues = storedData.formattedValue || this.data.textContent?.join("\n") || null; - if (fieldFormattedValues && this.data.comb) { - fieldFormattedValues = fieldFormattedValues.replaceAll(/\s+/g, ""); - } - const elementData = { - userValue: textContent, - formattedValue: fieldFormattedValues, - lastCommittedValue: null, - commitKey: 1, - focused: false - }; - if (this.data.multiLine) { - element = document.createElement("textarea"); - element.textContent = fieldFormattedValues ?? textContent; - if (this.data.doNotScroll) { - element.style.overflowY = "hidden"; - } - } else { - element = document.createElement("input"); - element.type = "text"; - element.setAttribute("value", fieldFormattedValues ?? textContent); - if (this.data.doNotScroll) { - element.style.overflowX = "hidden"; - } - } - if (this.data.hasOwnCanvas) { - element.hidden = true; - } - GetElementsByNameSet.add(element); - element.setAttribute("data-element-id", id); - element.disabled = this.data.readOnly; - element.name = this.data.fieldName; - element.tabIndex = DEFAULT_TAB_INDEX; - this._setRequired(element, this.data.required); - if (maxLen) { - element.maxLength = maxLen; - } - element.addEventListener("input", event => { - storage.setValue(id, { - value: event.target.value - }); - this.setPropertyOnSiblings(element, "value", event.target.value, "value"); - elementData.formattedValue = null; - }); - element.addEventListener("resetform", event => { - const defaultValue = this.data.defaultFieldValue ?? ""; - element.value = elementData.userValue = defaultValue; - elementData.formattedValue = null; - }); - let blurListener = event => { - const { - formattedValue - } = elementData; - if (formattedValue !== null && formattedValue !== undefined) { - event.target.value = formattedValue; - } - event.target.scrollLeft = 0; - }; - if (this.enableScripting && this.hasJSActions) { - element.addEventListener("focus", event => { - if (elementData.focused) { - return; - } - const { - target - } = event; - if (elementData.userValue) { - target.value = elementData.userValue; - } - elementData.lastCommittedValue = target.value; - elementData.commitKey = 1; - if (!this.data.actions?.Focus) { - elementData.focused = true; - } - }); - element.addEventListener("updatefromsandbox", jsEvent => { - this.showElementAndHideCanvas(jsEvent.target); - const actions = { - value(event) { - elementData.userValue = event.detail.value ?? ""; - storage.setValue(id, { - value: elementData.userValue.toString() - }); - event.target.value = elementData.userValue; - }, - formattedValue(event) { - const { - formattedValue - } = event.detail; - elementData.formattedValue = formattedValue; - if (formattedValue !== null && formattedValue !== undefined && event.target !== document.activeElement) { - event.target.value = formattedValue; - } - storage.setValue(id, { - formattedValue - }); - }, - selRange(event) { - event.target.setSelectionRange(...event.detail.selRange); - }, - charLimit: event => { - const { - charLimit - } = event.detail; - const { - target - } = event; - if (charLimit === 0) { - target.removeAttribute("maxLength"); - return; - } - target.setAttribute("maxLength", charLimit); - let value = elementData.userValue; - if (!value || value.length <= charLimit) { - return; - } - value = value.slice(0, charLimit); - target.value = elementData.userValue = value; - storage.setValue(id, { - value - }); - this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { - source: this, - detail: { - id, - name: "Keystroke", - value, - willCommit: true, - commitKey: 1, - selStart: target.selectionStart, - selEnd: target.selectionEnd - } - }); - } - }; - this._dispatchEventFromSandbox(actions, jsEvent); - }); - element.addEventListener("keydown", event => { - elementData.commitKey = 1; - let commitKey = -1; - if (event.key === "Escape") { - commitKey = 0; - } else if (event.key === "Enter" && !this.data.multiLine) { - commitKey = 2; - } else if (event.key === "Tab") { - elementData.commitKey = 3; - } - if (commitKey === -1) { - return; - } - const { - value - } = event.target; - if (elementData.lastCommittedValue === value) { - return; - } - elementData.lastCommittedValue = value; - elementData.userValue = value; - this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { - source: this, - detail: { - id, - name: "Keystroke", - value, - willCommit: true, - commitKey, - selStart: event.target.selectionStart, - selEnd: event.target.selectionEnd - } - }); - }); - const _blurListener = blurListener; - blurListener = null; - element.addEventListener("blur", event => { - if (!elementData.focused || !event.relatedTarget) { - return; - } - if (!this.data.actions?.Blur) { - elementData.focused = false; - } - const { - value - } = event.target; - elementData.userValue = value; - if (elementData.lastCommittedValue !== value) { - this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { - source: this, - detail: { - id, - name: "Keystroke", - value, - willCommit: true, - commitKey: elementData.commitKey, - selStart: event.target.selectionStart, - selEnd: event.target.selectionEnd - } - }); - } - _blurListener(event); - }); - if (this.data.actions?.Keystroke) { - element.addEventListener("beforeinput", event => { - elementData.lastCommittedValue = null; - const { - data, - target - } = event; - const { - value, - selectionStart, - selectionEnd - } = target; - let selStart = selectionStart, - selEnd = selectionEnd; - switch (event.inputType) { - case "deleteWordBackward": - { - const match = value.substring(0, selectionStart).match(/\w*[^\w]*$/); - if (match) { - selStart -= match[0].length; - } - break; - } - case "deleteWordForward": - { - const match = value.substring(selectionStart).match(/^[^\w]*\w*/); - if (match) { - selEnd += match[0].length; - } - break; - } - case "deleteContentBackward": - if (selectionStart === selectionEnd) { - selStart -= 1; - } - break; - case "deleteContentForward": - if (selectionStart === selectionEnd) { - selEnd += 1; - } - break; - } - event.preventDefault(); - this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { - source: this, - detail: { - id, - name: "Keystroke", - value, - change: data || "", - willCommit: false, - selStart, - selEnd - } - }); - }); - } - this._setEventListeners(element, elementData, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.value); - } - if (blurListener) { - element.addEventListener("blur", blurListener); - } - if (this.data.comb) { - const fieldWidth = this.data.rect[2] - this.data.rect[0]; - const combWidth = fieldWidth / maxLen; - element.classList.add("comb"); - element.style.letterSpacing = `calc(${combWidth}px * var(--scale-factor) - 1ch)`; - } - } else { - element = document.createElement("div"); - element.textContent = this.data.fieldValue; - element.style.verticalAlign = "middle"; - element.style.display = "table-cell"; - if (this.data.hasOwnCanvas) { - element.hidden = true; - } - } - this._setTextStyle(element); - this._setBackgroundColor(element); - this._setDefaultPropertiesFromJS(element); - this.container.append(element); - return this.container; - } -} -class SignatureWidgetAnnotationElement extends WidgetAnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: !!parameters.data.hasOwnCanvas - }); - } -} -class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: parameters.renderForms - }); - } - render() { - const storage = this.annotationStorage; - const data = this.data; - const id = data.id; - let value = storage.getValue(id, { - value: data.exportValue === data.fieldValue - }).value; - if (typeof value === "string") { - value = value !== "Off"; - storage.setValue(id, { - value - }); - } - this.container.classList.add("buttonWidgetAnnotation", "checkBox"); - const element = document.createElement("input"); - GetElementsByNameSet.add(element); - element.setAttribute("data-element-id", id); - element.disabled = data.readOnly; - this._setRequired(element, this.data.required); - element.type = "checkbox"; - element.name = data.fieldName; - if (value) { - element.setAttribute("checked", true); - } - element.setAttribute("exportValue", data.exportValue); - element.tabIndex = DEFAULT_TAB_INDEX; - element.addEventListener("change", event => { - const { - name, - checked - } = event.target; - for (const checkbox of this._getElementsByName(name, id)) { - const curChecked = checked && checkbox.exportValue === data.exportValue; - if (checkbox.domElement) { - checkbox.domElement.checked = curChecked; - } - storage.setValue(checkbox.id, { - value: curChecked - }); - } - storage.setValue(id, { - value: checked - }); - }); - element.addEventListener("resetform", event => { - const defaultValue = data.defaultFieldValue || "Off"; - event.target.checked = defaultValue === data.exportValue; - }); - if (this.enableScripting && this.hasJSActions) { - element.addEventListener("updatefromsandbox", jsEvent => { - const actions = { - value(event) { - event.target.checked = event.detail.value !== "Off"; - storage.setValue(id, { - value: event.target.checked - }); - } - }; - this._dispatchEventFromSandbox(actions, jsEvent); - }); - this._setEventListeners(element, null, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked); - } - this._setBackgroundColor(element); - this._setDefaultPropertiesFromJS(element); - this.container.append(element); - return this.container; - } -} -class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: parameters.renderForms - }); - } - render() { - this.container.classList.add("buttonWidgetAnnotation", "radioButton"); - const storage = this.annotationStorage; - const data = this.data; - const id = data.id; - let value = storage.getValue(id, { - value: data.fieldValue === data.buttonValue - }).value; - if (typeof value === "string") { - value = value !== data.buttonValue; - storage.setValue(id, { - value - }); - } - if (value) { - for (const radio of this._getElementsByName(data.fieldName, id)) { - storage.setValue(radio.id, { - value: false - }); - } - } - const element = document.createElement("input"); - GetElementsByNameSet.add(element); - element.setAttribute("data-element-id", id); - element.disabled = data.readOnly; - this._setRequired(element, this.data.required); - element.type = "radio"; - element.name = data.fieldName; - if (value) { - element.setAttribute("checked", true); - } - element.tabIndex = DEFAULT_TAB_INDEX; - element.addEventListener("change", event => { - const { - name, - checked - } = event.target; - for (const radio of this._getElementsByName(name, id)) { - storage.setValue(radio.id, { - value: false - }); - } - storage.setValue(id, { - value: checked - }); - }); - element.addEventListener("resetform", event => { - const defaultValue = data.defaultFieldValue; - event.target.checked = defaultValue !== null && defaultValue !== undefined && defaultValue === data.buttonValue; - }); - if (this.enableScripting && this.hasJSActions) { - const pdfButtonValue = data.buttonValue; - element.addEventListener("updatefromsandbox", jsEvent => { - const actions = { - value: event => { - const checked = pdfButtonValue === event.detail.value; - for (const radio of this._getElementsByName(event.target.name)) { - const curChecked = checked && radio.id === id; - if (radio.domElement) { - radio.domElement.checked = curChecked; - } - storage.setValue(radio.id, { - value: curChecked - }); - } - } - }; - this._dispatchEventFromSandbox(actions, jsEvent); - }); - this._setEventListeners(element, null, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked); - } - this._setBackgroundColor(element); - this._setDefaultPropertiesFromJS(element); - this.container.append(element); - return this.container; - } -} -class PushButtonWidgetAnnotationElement extends LinkAnnotationElement { - constructor(parameters) { - super(parameters, { - ignoreBorder: parameters.data.hasAppearance - }); - } - render() { - const container = super.render(); - container.classList.add("buttonWidgetAnnotation", "pushButton"); - const linkElement = container.lastChild; - if (this.enableScripting && this.hasJSActions && linkElement) { - this._setDefaultPropertiesFromJS(linkElement); - linkElement.addEventListener("updatefromsandbox", jsEvent => { - this._dispatchEventFromSandbox({}, jsEvent); - }); - } - return container; - } -} -class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: parameters.renderForms - }); - } - render() { - this.container.classList.add("choiceWidgetAnnotation"); - const storage = this.annotationStorage; - const id = this.data.id; - const storedData = storage.getValue(id, { - value: this.data.fieldValue - }); - const selectElement = document.createElement("select"); - GetElementsByNameSet.add(selectElement); - selectElement.setAttribute("data-element-id", id); - selectElement.disabled = this.data.readOnly; - this._setRequired(selectElement, this.data.required); - selectElement.name = this.data.fieldName; - selectElement.tabIndex = DEFAULT_TAB_INDEX; - let addAnEmptyEntry = this.data.combo && this.data.options.length > 0; - if (!this.data.combo) { - selectElement.size = this.data.options.length; - if (this.data.multiSelect) { - selectElement.multiple = true; - } - } - selectElement.addEventListener("resetform", event => { - const defaultValue = this.data.defaultFieldValue; - for (const option of selectElement.options) { - option.selected = option.value === defaultValue; - } - }); - for (const option of this.data.options) { - const optionElement = document.createElement("option"); - optionElement.textContent = option.displayValue; - optionElement.value = option.exportValue; - if (storedData.value.includes(option.exportValue)) { - optionElement.setAttribute("selected", true); - addAnEmptyEntry = false; - } - selectElement.append(optionElement); - } - let removeEmptyEntry = null; - if (addAnEmptyEntry) { - const noneOptionElement = document.createElement("option"); - noneOptionElement.value = " "; - noneOptionElement.setAttribute("hidden", true); - noneOptionElement.setAttribute("selected", true); - selectElement.prepend(noneOptionElement); - removeEmptyEntry = () => { - noneOptionElement.remove(); - selectElement.removeEventListener("input", removeEmptyEntry); - removeEmptyEntry = null; - }; - selectElement.addEventListener("input", removeEmptyEntry); - } - const getValue = isExport => { - const name = isExport ? "value" : "textContent"; - const { - options, - multiple - } = selectElement; - if (!multiple) { - return options.selectedIndex === -1 ? null : options[options.selectedIndex][name]; - } - return Array.prototype.filter.call(options, option => option.selected).map(option => option[name]); - }; - let selectedValues = getValue(false); - const getItems = event => { - const options = event.target.options; - return Array.prototype.map.call(options, option => ({ - displayValue: option.textContent, - exportValue: option.value - })); - }; - if (this.enableScripting && this.hasJSActions) { - selectElement.addEventListener("updatefromsandbox", jsEvent => { - const actions = { - value(event) { - removeEmptyEntry?.(); - const value = event.detail.value; - const values = new Set(Array.isArray(value) ? value : [value]); - for (const option of selectElement.options) { - option.selected = values.has(option.value); - } - storage.setValue(id, { - value: getValue(true) - }); - selectedValues = getValue(false); - }, - multipleSelection(event) { - selectElement.multiple = true; - }, - remove(event) { - const options = selectElement.options; - const index = event.detail.remove; - options[index].selected = false; - selectElement.remove(index); - if (options.length > 0) { - const i = Array.prototype.findIndex.call(options, option => option.selected); - if (i === -1) { - options[0].selected = true; - } - } - storage.setValue(id, { - value: getValue(true), - items: getItems(event) - }); - selectedValues = getValue(false); - }, - clear(event) { - while (selectElement.length !== 0) { - selectElement.remove(0); - } - storage.setValue(id, { - value: null, - items: [] - }); - selectedValues = getValue(false); - }, - insert(event) { - const { - index, - displayValue, - exportValue - } = event.detail.insert; - const selectChild = selectElement.children[index]; - const optionElement = document.createElement("option"); - optionElement.textContent = displayValue; - optionElement.value = exportValue; - if (selectChild) { - selectChild.before(optionElement); - } else { - selectElement.append(optionElement); - } - storage.setValue(id, { - value: getValue(true), - items: getItems(event) - }); - selectedValues = getValue(false); - }, - items(event) { - const { - items - } = event.detail; - while (selectElement.length !== 0) { - selectElement.remove(0); - } - for (const item of items) { - const { - displayValue, - exportValue - } = item; - const optionElement = document.createElement("option"); - optionElement.textContent = displayValue; - optionElement.value = exportValue; - selectElement.append(optionElement); - } - if (selectElement.options.length > 0) { - selectElement.options[0].selected = true; - } - storage.setValue(id, { - value: getValue(true), - items: getItems(event) - }); - selectedValues = getValue(false); - }, - indices(event) { - const indices = new Set(event.detail.indices); - for (const option of event.target.options) { - option.selected = indices.has(option.index); - } - storage.setValue(id, { - value: getValue(true) - }); - selectedValues = getValue(false); - }, - editable(event) { - event.target.disabled = !event.detail.editable; - } - }; - this._dispatchEventFromSandbox(actions, jsEvent); - }); - selectElement.addEventListener("input", event => { - const exportValue = getValue(true); - const change = getValue(false); - storage.setValue(id, { - value: exportValue - }); - event.preventDefault(); - this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { - source: this, - detail: { - id, - name: "Keystroke", - value: selectedValues, - change, - changeEx: exportValue, - willCommit: false, - commitKey: 1, - keyDown: false - } - }); - }); - this._setEventListeners(selectElement, null, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"], ["input", "Action"], ["input", "Validate"]], event => event.target.value); - } else { - selectElement.addEventListener("input", function (event) { - storage.setValue(id, { - value: getValue(true) - }); - }); - } - if (this.data.combo) { - this._setTextStyle(selectElement); - } else {} - this._setBackgroundColor(selectElement); - this._setDefaultPropertiesFromJS(selectElement); - this.container.append(selectElement); - return this.container; - } -} -class PopupAnnotationElement extends AnnotationElement { - constructor(parameters) { - const { - data, - elements - } = parameters; - super(parameters, { - isRenderable: AnnotationElement._hasPopupData(data) - }); - this.elements = elements; - } - render() { - this.container.classList.add("popupAnnotation"); - const popup = new PopupElement({ - container: this.container, - color: this.data.color, - titleObj: this.data.titleObj, - modificationDate: this.data.modificationDate, - contentsObj: this.data.contentsObj, - richText: this.data.richText, - rect: this.data.rect, - parentRect: this.data.parentRect || null, - parent: this.parent, - elements: this.elements, - open: this.data.open - }); - const elementIds = []; - for (const element of this.elements) { - element.popup = popup; - elementIds.push(element.data.id); - element.addHighlightArea(); - } - this.container.setAttribute("aria-controls", elementIds.map(id => `${util.AnnotationPrefix}${id}`).join(",")); - return this.container; - } -} -class PopupElement { - #boundKeyDown = this.#keyDown.bind(this); - #boundHide = this.#hide.bind(this); - #boundShow = this.#show.bind(this); - #boundToggle = this.#toggle.bind(this); - #color = null; - #container = null; - #contentsObj = null; - #dateObj = null; - #elements = null; - #parent = null; - #parentRect = null; - #pinned = false; - #popup = null; - #rect = null; - #richText = null; - #titleObj = null; - #wasVisible = false; - constructor({ - container, - color, - elements, - titleObj, - modificationDate, - contentsObj, - richText, - parent, - rect, - parentRect, - open - }) { - this.#container = container; - this.#titleObj = titleObj; - this.#contentsObj = contentsObj; - this.#richText = richText; - this.#parent = parent; - this.#color = color; - this.#rect = rect; - this.#parentRect = parentRect; - this.#elements = elements; - this.#dateObj = display_utils.PDFDateString.toDateObject(modificationDate); - this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup()); - for (const element of this.trigger) { - element.addEventListener("click", this.#boundToggle); - element.addEventListener("mouseenter", this.#boundShow); - element.addEventListener("mouseleave", this.#boundHide); - element.classList.add("popupTriggerArea"); - } - for (const element of elements) { - element.container?.addEventListener("keydown", this.#boundKeyDown); - } - this.#container.hidden = true; - if (open) { - this.#toggle(); - } - } - render() { - if (this.#popup) { - return; - } - const { - page: { - view - }, - viewport: { - rawDims: { - pageWidth, - pageHeight, - pageX, - pageY - } - } - } = this.#parent; - const popup = this.#popup = document.createElement("div"); - popup.className = "popup"; - if (this.#color) { - const baseColor = popup.style.outlineColor = util.Util.makeHexColor(...this.#color); - if (CSS.supports("background-color", "color-mix(in srgb, red 30%, white)")) { - popup.style.backgroundColor = `color-mix(in srgb, ${baseColor} 30%, white)`; - } else { - const BACKGROUND_ENLIGHT = 0.7; - popup.style.backgroundColor = util.Util.makeHexColor(...this.#color.map(c => Math.floor(BACKGROUND_ENLIGHT * (255 - c) + c))); - } - } - const header = document.createElement("span"); - header.className = "header"; - const title = document.createElement("h1"); - header.append(title); - ({ - dir: title.dir, - str: title.textContent - } = this.#titleObj); - popup.append(header); - if (this.#dateObj) { - const modificationDate = document.createElement("span"); - modificationDate.classList.add("popupDate"); - modificationDate.setAttribute("data-l10n-id", "pdfjs-annotation-date-string"); - modificationDate.setAttribute("data-l10n-args", JSON.stringify({ - date: this.#dateObj.toLocaleDateString(), - time: this.#dateObj.toLocaleTimeString() - })); - header.append(modificationDate); - } - const contentsObj = this.#contentsObj; - const richText = this.#richText; - if (richText?.str && (!contentsObj?.str || contentsObj.str === richText.str)) { - xfa_layer.XfaLayer.render({ - xfaHtml: richText.html, - intent: "richText", - div: popup - }); - popup.lastChild.classList.add("richText", "popupContent"); - } else { - const contents = this._formatContents(contentsObj); - popup.append(contents); - } - let useParentRect = !!this.#parentRect; - let rect = useParentRect ? this.#parentRect : this.#rect; - for (const element of this.#elements) { - if (!rect || util.Util.intersect(element.data.rect, rect) !== null) { - rect = element.data.rect; - useParentRect = true; - break; - } - } - const normalizedRect = util.Util.normalizeRect([rect[0], view[3] - rect[1] + view[1], rect[2], view[3] - rect[3] + view[1]]); - const HORIZONTAL_SPACE_AFTER_ANNOTATION = 5; - const parentWidth = useParentRect ? rect[2] - rect[0] + HORIZONTAL_SPACE_AFTER_ANNOTATION : 0; - const popupLeft = normalizedRect[0] + parentWidth; - const popupTop = normalizedRect[1]; - const { - style - } = this.#container; - style.left = `${100 * (popupLeft - pageX) / pageWidth}%`; - style.top = `${100 * (popupTop - pageY) / pageHeight}%`; - this.#container.append(popup); - } - _formatContents({ - str, - dir - }) { - const p = document.createElement("p"); - p.classList.add("popupContent"); - p.dir = dir; - const lines = str.split(/(?:\r\n?|\n)/); - for (let i = 0, ii = lines.length; i < ii; ++i) { - const line = lines[i]; - p.append(document.createTextNode(line)); - if (i < ii - 1) { - p.append(document.createElement("br")); - } - } - return p; - } - #keyDown(event) { - if (event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) { - return; - } - if (event.key === "Enter" || event.key === "Escape" && this.#pinned) { - this.#toggle(); - } - } - #toggle() { - this.#pinned = !this.#pinned; - if (this.#pinned) { - this.#show(); - this.#container.addEventListener("click", this.#boundToggle); - this.#container.addEventListener("keydown", this.#boundKeyDown); - } else { - this.#hide(); - this.#container.removeEventListener("click", this.#boundToggle); - this.#container.removeEventListener("keydown", this.#boundKeyDown); - } - } - #show() { - if (!this.#popup) { - this.render(); - } - if (!this.isVisible) { - this.#container.hidden = false; - this.#container.style.zIndex = parseInt(this.#container.style.zIndex) + 1000; - } else if (this.#pinned) { - this.#container.classList.add("focused"); - } - } - #hide() { - this.#container.classList.remove("focused"); - if (this.#pinned || !this.isVisible) { - return; - } - this.#container.hidden = true; - this.#container.style.zIndex = parseInt(this.#container.style.zIndex) - 1000; - } - forceHide() { - this.#wasVisible = this.isVisible; - if (!this.#wasVisible) { - return; - } - this.#container.hidden = true; - } - maybeShow() { - if (!this.#wasVisible) { - return; - } - this.#wasVisible = false; - this.#container.hidden = false; - } - get isVisible() { - return this.#container.hidden === false; - } -} -class FreeTextAnnotationElement extends AnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true - }); - this.textContent = parameters.data.textContent; - this.textPosition = parameters.data.textPosition; - this.annotationEditorType = util.AnnotationEditorType.FREETEXT; - } - render() { - this.container.classList.add("freeTextAnnotation"); - if (this.textContent) { - const content = document.createElement("div"); - content.classList.add("annotationTextContent"); - content.setAttribute("role", "comment"); - for (const line of this.textContent) { - const lineSpan = document.createElement("span"); - lineSpan.textContent = line; - content.append(lineSpan); - } - this.container.append(content); - } - if (!this.data.popupRef && this.hasPopupData) { - this._createPopup(); - } - this._editOnDoubleClick(); - return this.container; - } - get _isEditable() { - return this.data.hasOwnCanvas; - } -} -class LineAnnotationElement extends AnnotationElement { - #line = null; - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true - }); - } - render() { - this.container.classList.add("lineAnnotation"); - const data = this.data; - const { - width, - height - } = getRectDims(data.rect); - const svg = this.svgFactory.create(width, height, true); - const line = this.#line = this.svgFactory.createElement("svg:line"); - line.setAttribute("x1", data.rect[2] - data.lineCoordinates[0]); - line.setAttribute("y1", data.rect[3] - data.lineCoordinates[1]); - line.setAttribute("x2", data.rect[2] - data.lineCoordinates[2]); - line.setAttribute("y2", data.rect[3] - data.lineCoordinates[3]); - line.setAttribute("stroke-width", data.borderStyle.width || 1); - line.setAttribute("stroke", "transparent"); - line.setAttribute("fill", "transparent"); - svg.append(line); - this.container.append(svg); - if (!data.popupRef && this.hasPopupData) { - this._createPopup(); - } - return this.container; - } - getElementsToTriggerPopup() { - return this.#line; - } - addHighlightArea() { - this.container.classList.add("highlightArea"); - } -} -class SquareAnnotationElement extends AnnotationElement { - #square = null; - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true - }); - } - render() { - this.container.classList.add("squareAnnotation"); - const data = this.data; - const { - width, - height - } = getRectDims(data.rect); - const svg = this.svgFactory.create(width, height, true); - const borderWidth = data.borderStyle.width; - const square = this.#square = this.svgFactory.createElement("svg:rect"); - square.setAttribute("x", borderWidth / 2); - square.setAttribute("y", borderWidth / 2); - square.setAttribute("width", width - borderWidth); - square.setAttribute("height", height - borderWidth); - square.setAttribute("stroke-width", borderWidth || 1); - square.setAttribute("stroke", "transparent"); - square.setAttribute("fill", "transparent"); - svg.append(square); - this.container.append(svg); - if (!data.popupRef && this.hasPopupData) { - this._createPopup(); - } - return this.container; - } - getElementsToTriggerPopup() { - return this.#square; - } - addHighlightArea() { - this.container.classList.add("highlightArea"); - } -} -class CircleAnnotationElement extends AnnotationElement { - #circle = null; - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true - }); - } - render() { - this.container.classList.add("circleAnnotation"); - const data = this.data; - const { - width, - height - } = getRectDims(data.rect); - const svg = this.svgFactory.create(width, height, true); - const borderWidth = data.borderStyle.width; - const circle = this.#circle = this.svgFactory.createElement("svg:ellipse"); - circle.setAttribute("cx", width / 2); - circle.setAttribute("cy", height / 2); - circle.setAttribute("rx", width / 2 - borderWidth / 2); - circle.setAttribute("ry", height / 2 - borderWidth / 2); - circle.setAttribute("stroke-width", borderWidth || 1); - circle.setAttribute("stroke", "transparent"); - circle.setAttribute("fill", "transparent"); - svg.append(circle); - this.container.append(svg); - if (!data.popupRef && this.hasPopupData) { - this._createPopup(); - } - return this.container; - } - getElementsToTriggerPopup() { - return this.#circle; - } - addHighlightArea() { - this.container.classList.add("highlightArea"); - } -} -class PolylineAnnotationElement extends AnnotationElement { - #polyline = null; - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true - }); - this.containerClassName = "polylineAnnotation"; - this.svgElementName = "svg:polyline"; - } - render() { - this.container.classList.add(this.containerClassName); - const data = this.data; - const { - width, - height - } = getRectDims(data.rect); - const svg = this.svgFactory.create(width, height, true); - let points = []; - for (const coordinate of data.vertices) { - const x = coordinate.x - data.rect[0]; - const y = data.rect[3] - coordinate.y; - points.push(x + "," + y); - } - points = points.join(" "); - const polyline = this.#polyline = this.svgFactory.createElement(this.svgElementName); - polyline.setAttribute("points", points); - polyline.setAttribute("stroke-width", data.borderStyle.width || 1); - polyline.setAttribute("stroke", "transparent"); - polyline.setAttribute("fill", "transparent"); - svg.append(polyline); - this.container.append(svg); - if (!data.popupRef && this.hasPopupData) { - this._createPopup(); - } - return this.container; - } - getElementsToTriggerPopup() { - return this.#polyline; - } - addHighlightArea() { - this.container.classList.add("highlightArea"); - } -} -class PolygonAnnotationElement extends PolylineAnnotationElement { - constructor(parameters) { - super(parameters); - this.containerClassName = "polygonAnnotation"; - this.svgElementName = "svg:polygon"; - } -} -class CaretAnnotationElement extends AnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true - }); - } - render() { - this.container.classList.add("caretAnnotation"); - if (!this.data.popupRef && this.hasPopupData) { - this._createPopup(); - } - return this.container; - } -} -class InkAnnotationElement extends AnnotationElement { - #polylines = []; - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true - }); - this.containerClassName = "inkAnnotation"; - this.svgElementName = "svg:polyline"; - this.annotationEditorType = util.AnnotationEditorType.INK; - } - render() { - this.container.classList.add(this.containerClassName); - const data = this.data; - const { - width, - height - } = getRectDims(data.rect); - const svg = this.svgFactory.create(width, height, true); - for (const inkList of data.inkLists) { - let points = []; - for (const coordinate of inkList) { - const x = coordinate.x - data.rect[0]; - const y = data.rect[3] - coordinate.y; - points.push(`${x},${y}`); - } - points = points.join(" "); - const polyline = this.svgFactory.createElement(this.svgElementName); - this.#polylines.push(polyline); - polyline.setAttribute("points", points); - polyline.setAttribute("stroke-width", data.borderStyle.width || 1); - polyline.setAttribute("stroke", "transparent"); - polyline.setAttribute("fill", "transparent"); - if (!data.popupRef && this.hasPopupData) { - this._createPopup(); - } - svg.append(polyline); - } - this.container.append(svg); - return this.container; - } - getElementsToTriggerPopup() { - return this.#polylines; - } - addHighlightArea() { - this.container.classList.add("highlightArea"); - } -} -class HighlightAnnotationElement extends AnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true, - createQuadrilaterals: true - }); - } - render() { - if (!this.data.popupRef && this.hasPopupData) { - this._createPopup(); - } - this.container.classList.add("highlightAnnotation"); - return this.container; - } -} -class UnderlineAnnotationElement extends AnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true, - createQuadrilaterals: true - }); - } - render() { - if (!this.data.popupRef && this.hasPopupData) { - this._createPopup(); - } - this.container.classList.add("underlineAnnotation"); - return this.container; - } -} -class SquigglyAnnotationElement extends AnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true, - createQuadrilaterals: true - }); - } - render() { - if (!this.data.popupRef && this.hasPopupData) { - this._createPopup(); - } - this.container.classList.add("squigglyAnnotation"); - return this.container; - } -} -class StrikeOutAnnotationElement extends AnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true, - createQuadrilaterals: true - }); - } - render() { - if (!this.data.popupRef && this.hasPopupData) { - this._createPopup(); - } - this.container.classList.add("strikeoutAnnotation"); - return this.container; - } -} -class StampAnnotationElement extends AnnotationElement { - constructor(parameters) { - super(parameters, { - isRenderable: true, - ignoreBorder: true - }); - } - render() { - this.container.classList.add("stampAnnotation"); - if (!this.data.popupRef && this.hasPopupData) { - this._createPopup(); - } - return this.container; - } -} -class FileAttachmentAnnotationElement extends AnnotationElement { - #trigger = null; - constructor(parameters) { - super(parameters, { - isRenderable: true - }); - const { - filename, - content - } = this.data.file; - this.filename = (0,display_utils.getFilenameFromUrl)(filename, true); - this.content = content; - this.linkService.eventBus?.dispatch("fileattachmentannotation", { - source: this, - filename, - content - }); - } - render() { - this.container.classList.add("fileAttachmentAnnotation"); - const { - container, - data - } = this; - let trigger; - if (data.hasAppearance || data.fillAlpha === 0) { - trigger = document.createElement("div"); - } else { - trigger = document.createElement("img"); - trigger.src = `${this.imageResourcesPath}annotation-${/paperclip/i.test(data.name) ? "paperclip" : "pushpin"}.svg`; - if (data.fillAlpha && data.fillAlpha < 1) { - trigger.style = `filter: opacity(${Math.round(data.fillAlpha * 100)}%);`; - } - } - trigger.addEventListener("dblclick", this.#download.bind(this)); - this.#trigger = trigger; - const { - isMac - } = util.FeatureTest.platform; - container.addEventListener("keydown", evt => { - if (evt.key === "Enter" && (isMac ? evt.metaKey : evt.ctrlKey)) { - this.#download(); - } - }); - if (!data.popupRef && this.hasPopupData) { - this._createPopup(); - } else { - trigger.classList.add("popupTriggerArea"); - } - container.append(trigger); - return container; - } - getElementsToTriggerPopup() { - return this.#trigger; - } - addHighlightArea() { - this.container.classList.add("highlightArea"); - } - #download() { - this.downloadManager?.openOrDownloadData(this.content, this.filename); - } -} -class AnnotationLayer { - #accessibilityManager = null; - #annotationCanvasMap = null; - #editableAnnotations = new Map(); - constructor({ - div, - accessibilityManager, - annotationCanvasMap, - annotationEditorUIManager, - page, - viewport - }) { - this.div = div; - this.#accessibilityManager = accessibilityManager; - this.#annotationCanvasMap = annotationCanvasMap; - this.page = page; - this.viewport = viewport; - this.zIndex = 0; - this._annotationEditorUIManager = annotationEditorUIManager; - } - #appendElement(element, id) { - const contentElement = element.firstChild || element; - contentElement.id = `${util.AnnotationPrefix}${id}`; - this.div.append(element); - this.#accessibilityManager?.moveElementInDOM(this.div, element, contentElement, false); - } - async render(params) { - const { - annotations - } = params; - const layer = this.div; - (0,display_utils.setLayerDimensions)(layer, this.viewport); - const popupToElements = new Map(); - const elementParams = { - data: null, - layer, - linkService: params.linkService, - downloadManager: params.downloadManager, - imageResourcesPath: params.imageResourcesPath || "", - renderForms: params.renderForms !== false, - svgFactory: new display_utils.DOMSVGFactory(), - annotationStorage: params.annotationStorage || new annotation_storage.AnnotationStorage(), - enableScripting: params.enableScripting === true, - hasJSActions: params.hasJSActions, - fieldObjects: params.fieldObjects, - parent: this, - elements: null - }; - for (const data of annotations) { - if (data.noHTML) { - continue; - } - const isPopupAnnotation = data.annotationType === util.AnnotationType.POPUP; - if (!isPopupAnnotation) { - const { - width, - height - } = getRectDims(data.rect); - if (width <= 0 || height <= 0) { - continue; - } - } else { - const elements = popupToElements.get(data.id); - if (!elements) { - continue; - } - elementParams.elements = elements; - } - elementParams.data = data; - const element = AnnotationElementFactory.create(elementParams); - if (!element.isRenderable) { - continue; - } - if (!isPopupAnnotation && data.popupRef) { - const elements = popupToElements.get(data.popupRef); - if (!elements) { - popupToElements.set(data.popupRef, [element]); - } else { - elements.push(element); - } - } - const rendered = element.render(); - if (data.hidden) { - rendered.style.visibility = "hidden"; - } - this.#appendElement(rendered, data.id); - if (element.annotationEditorType > 0) { - this.#editableAnnotations.set(element.data.id, element); - this._annotationEditorUIManager?.renderAnnotationElement(element); - } - } - this.#setAnnotationCanvasMap(); - } - update({ - viewport - }) { - const layer = this.div; - this.viewport = viewport; - (0,display_utils.setLayerDimensions)(layer, { - rotation: viewport.rotation - }); - this.#setAnnotationCanvasMap(); - layer.hidden = false; - } - #setAnnotationCanvasMap() { - if (!this.#annotationCanvasMap) { - return; - } - const layer = this.div; - for (const [id, canvas] of this.#annotationCanvasMap) { - const element = layer.querySelector(`[data-annotation-id="${id}"]`); - if (!element) { - continue; - } - canvas.className = "annotationContent"; - const { - firstChild - } = element; - if (!firstChild) { - element.append(canvas); - } else if (firstChild.nodeName === "CANVAS") { - firstChild.replaceWith(canvas); - } else if (!firstChild.classList.contains("annotationContent")) { - firstChild.before(canvas); - } else { - firstChild.after(canvas); - } - } - this.#annotationCanvasMap.clear(); - } - getEditableAnnotations() { - return Array.from(this.#editableAnnotations.values()); - } - getEditableAnnotation(id) { - return this.#editableAnnotations.get(id); - } -} - - -/***/ }), - -/***/ 792: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AnnotationStorage: () => (/* binding */ AnnotationStorage), -/* harmony export */ PrintAnnotationStorage: () => (/* binding */ PrintAnnotationStorage), -/* harmony export */ SerializableEmpty: () => (/* binding */ SerializableEmpty) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _editor_editor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(310); -/* harmony import */ var _shared_murmurhash3_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(651); - - - -const SerializableEmpty = Object.freeze({ - map: null, - hash: "", - transfer: undefined -}); -class AnnotationStorage { - #modified = false; - #storage = new Map(); - constructor() { - this.onSetModified = null; - this.onResetModified = null; - this.onAnnotationEditor = null; - } - getValue(key, defaultValue) { - const value = this.#storage.get(key); - if (value === undefined) { - return defaultValue; - } - return Object.assign(defaultValue, value); - } - getRawValue(key) { - return this.#storage.get(key); - } - remove(key) { - this.#storage.delete(key); - if (this.#storage.size === 0) { - this.resetModified(); - } - if (typeof this.onAnnotationEditor === "function") { - for (const value of this.#storage.values()) { - if (value instanceof _editor_editor_js__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditor) { - return; - } - } - this.onAnnotationEditor(null); - } - } - setValue(key, value) { - const obj = this.#storage.get(key); - let modified = false; - if (obj !== undefined) { - for (const [entry, val] of Object.entries(value)) { - if (obj[entry] !== val) { - modified = true; - obj[entry] = val; - } - } - } else { - modified = true; - this.#storage.set(key, value); - } - if (modified) { - this.#setModified(); - } - if (value instanceof _editor_editor_js__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditor && typeof this.onAnnotationEditor === "function") { - this.onAnnotationEditor(value.constructor._type); - } - } - has(key) { - return this.#storage.has(key); - } - getAll() { - return this.#storage.size > 0 ? (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.objectFromMap)(this.#storage) : null; - } - setAll(obj) { - for (const [key, val] of Object.entries(obj)) { - this.setValue(key, val); - } - } - get size() { - return this.#storage.size; - } - #setModified() { - if (!this.#modified) { - this.#modified = true; - if (typeof this.onSetModified === "function") { - this.onSetModified(); - } - } - } - resetModified() { - if (this.#modified) { - this.#modified = false; - if (typeof this.onResetModified === "function") { - this.onResetModified(); - } - } - } - get print() { - return new PrintAnnotationStorage(this); - } - get serializable() { - if (this.#storage.size === 0) { - return SerializableEmpty; - } - const map = new Map(), - hash = new _shared_murmurhash3_js__WEBPACK_IMPORTED_MODULE_2__.MurmurHash3_64(), - transfer = []; - const context = Object.create(null); - let hasBitmap = false; - for (const [key, val] of this.#storage) { - const serialized = val instanceof _editor_editor_js__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditor ? val.serialize(false, context) : val; - if (serialized) { - map.set(key, serialized); - hash.update(`${key}:${JSON.stringify(serialized)}`); - hasBitmap ||= !!serialized.bitmap; - } - } - if (hasBitmap) { - for (const value of map.values()) { - if (value.bitmap) { - transfer.push(value.bitmap); - } - } - } - return map.size > 0 ? { - map, - hash: hash.hexdigest(), - transfer - } : SerializableEmpty; - } - get editorStats() { - let stats = null; - const typeToEditor = new Map(); - for (const value of this.#storage.values()) { - if (!(value instanceof _editor_editor_js__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditor)) { - continue; - } - const editorStats = value.telemetryFinalData; - if (!editorStats) { - continue; - } - const { - type - } = editorStats; - if (!typeToEditor.has(type)) { - typeToEditor.set(type, Object.getPrototypeOf(value).constructor); - } - stats ||= Object.create(null); - const map = stats[type] ||= new Map(); - for (const [key, val] of Object.entries(editorStats)) { - if (key === "type") { - continue; - } - let counters = map.get(key); - if (!counters) { - counters = new Map(); - map.set(key, counters); - } - const count = counters.get(val) ?? 0; - counters.set(val, count + 1); - } - } - for (const [type, editor] of typeToEditor) { - stats[type] = editor.computeTelemetryFinalData(stats[type]); - } - return stats; - } -} -class PrintAnnotationStorage extends AnnotationStorage { - #serializable; - constructor(parent) { - super(); - const { - map, - hash, - transfer - } = parent.serializable; - const clone = structuredClone(map, transfer ? { - transfer - } : null); - this.#serializable = { - map: clone, - hash, - transfer - }; - } - get print() { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Should not call PrintAnnotationStorage.print"); - } - get serializable() { - return this.#serializable; - } -} - - -/***/ }), - -/***/ 831: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFDataRangeTransport: () => (/* binding */ PDFDataRangeTransport), -/* harmony export */ PDFWorker: () => (/* binding */ PDFWorker), -/* harmony export */ build: () => (/* binding */ build), -/* harmony export */ getDocument: () => (/* binding */ getDocument), -/* harmony export */ version: () => (/* binding */ version) -/* harmony export */ }); -/* unused harmony exports DefaultCanvasFactory, DefaultCMapReaderFactory, DefaultFilterFactory, DefaultStandardFontDataFactory, LoopbackPort, PDFDocumentLoadingTask, PDFDocumentProxy, PDFPageProxy, PDFWorkerUtil, RenderTask */ -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _annotation_storage_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(792); -/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(419); -/* harmony import */ var _font_loader_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10); -/* harmony import */ var display_node_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(573); -/* harmony import */ var _canvas_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(923); -/* harmony import */ var _text_layer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(814); -/* harmony import */ var _worker_options_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(164); -/* harmony import */ var _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(178); -/* harmony import */ var _metadata_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(62); -/* harmony import */ var _optional_content_config_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(626); -/* harmony import */ var _transport_stream_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(585); -/* harmony import */ var display_fetch_stream__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(94); -/* harmony import */ var display_network__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(457); -/* harmony import */ var display_node_stream__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(786); -/* harmony import */ var _xfa_text_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(50); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([display_node_utils__WEBPACK_IMPORTED_MODULE_4__, display_node_stream__WEBPACK_IMPORTED_MODULE_13__]); -([display_node_utils__WEBPACK_IMPORTED_MODULE_4__, display_node_stream__WEBPACK_IMPORTED_MODULE_13__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__); - - - - - - - - - - - - - - - - -const DEFAULT_RANGE_CHUNK_SIZE = 65536; -const RENDERING_CANCELLED_TIMEOUT = 100; -const DELAYED_CLEANUP_TIMEOUT = 5000; -const DefaultCanvasFactory = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS ? display_node_utils__WEBPACK_IMPORTED_MODULE_4__.NodeCanvasFactory : _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMCanvasFactory; -const DefaultCMapReaderFactory = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS ? display_node_utils__WEBPACK_IMPORTED_MODULE_4__.NodeCMapReaderFactory : _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMCMapReaderFactory; -const DefaultFilterFactory = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS ? display_node_utils__WEBPACK_IMPORTED_MODULE_4__.NodeFilterFactory : _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMFilterFactory; -const DefaultStandardFontDataFactory = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS ? display_node_utils__WEBPACK_IMPORTED_MODULE_4__.NodeStandardFontDataFactory : _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMStandardFontDataFactory; -function getDocument(src) { - if (typeof src === "string" || src instanceof URL) { - src = { - url: src - }; - } else if (src instanceof ArrayBuffer || ArrayBuffer.isView(src)) { - src = { - data: src - }; - } - if (typeof src !== "object") { - throw new Error("Invalid parameter in getDocument, need parameter object."); - } - if (!src.url && !src.data && !src.range) { - throw new Error("Invalid parameter object: need either .data, .range or .url"); - } - const task = new PDFDocumentLoadingTask(); - const { - docId - } = task; - const url = src.url ? getUrlProp(src.url) : null; - const data = src.data ? getDataProp(src.data) : null; - const httpHeaders = src.httpHeaders || null; - const withCredentials = src.withCredentials === true; - const password = src.password ?? null; - const rangeTransport = src.range instanceof PDFDataRangeTransport ? src.range : null; - const rangeChunkSize = Number.isInteger(src.rangeChunkSize) && src.rangeChunkSize > 0 ? src.rangeChunkSize : DEFAULT_RANGE_CHUNK_SIZE; - let worker = src.worker instanceof PDFWorker ? src.worker : null; - const verbosity = src.verbosity; - const docBaseUrl = typeof src.docBaseUrl === "string" && !(0,_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isDataScheme)(src.docBaseUrl) ? src.docBaseUrl : null; - const cMapUrl = typeof src.cMapUrl === "string" ? src.cMapUrl : null; - const cMapPacked = src.cMapPacked !== false; - const CMapReaderFactory = src.CMapReaderFactory || DefaultCMapReaderFactory; - const standardFontDataUrl = typeof src.standardFontDataUrl === "string" ? src.standardFontDataUrl : null; - const StandardFontDataFactory = src.StandardFontDataFactory || DefaultStandardFontDataFactory; - const ignoreErrors = src.stopAtErrors !== true; - const maxImageSize = Number.isInteger(src.maxImageSize) && src.maxImageSize > -1 ? src.maxImageSize : -1; - const isEvalSupported = src.isEvalSupported !== false; - const isOffscreenCanvasSupported = typeof src.isOffscreenCanvasSupported === "boolean" ? src.isOffscreenCanvasSupported : !_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS; - const canvasMaxAreaInBytes = Number.isInteger(src.canvasMaxAreaInBytes) ? src.canvasMaxAreaInBytes : -1; - const disableFontFace = typeof src.disableFontFace === "boolean" ? src.disableFontFace : _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS; - const fontExtraProperties = src.fontExtraProperties === true; - const enableXfa = src.enableXfa === true; - const ownerDocument = src.ownerDocument || globalThis.document; - const disableRange = src.disableRange === true; - const disableStream = src.disableStream === true; - const disableAutoFetch = src.disableAutoFetch === true; - const pdfBug = src.pdfBug === true; - const length = rangeTransport ? rangeTransport.length : src.length ?? NaN; - const useSystemFonts = typeof src.useSystemFonts === "boolean" ? src.useSystemFonts : !_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS && !disableFontFace; - const useWorkerFetch = typeof src.useWorkerFetch === "boolean" ? src.useWorkerFetch : CMapReaderFactory === _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMCMapReaderFactory && StandardFontDataFactory === _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMStandardFontDataFactory && cMapUrl && standardFontDataUrl && (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isValidFetchUrl)(cMapUrl, document.baseURI) && (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isValidFetchUrl)(standardFontDataUrl, document.baseURI); - const canvasFactory = src.canvasFactory || new DefaultCanvasFactory({ - ownerDocument - }); - const filterFactory = src.filterFactory || new DefaultFilterFactory({ - docId, - ownerDocument - }); - const styleElement = null; - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.setVerbosityLevel)(verbosity); - const transportFactory = { - canvasFactory, - filterFactory - }; - if (!useWorkerFetch) { - transportFactory.cMapReaderFactory = new CMapReaderFactory({ - baseUrl: cMapUrl, - isCompressed: cMapPacked - }); - transportFactory.standardFontDataFactory = new StandardFontDataFactory({ - baseUrl: standardFontDataUrl - }); - } - if (!worker) { - const workerParams = { - verbosity, - port: _worker_options_js__WEBPACK_IMPORTED_MODULE_14__.GlobalWorkerOptions.workerPort - }; - worker = workerParams.port ? PDFWorker.fromPort(workerParams) : new PDFWorker(workerParams); - task._worker = worker; - } - const fetchDocParams = { - docId, - apiVersion: "4.2.67", - data, - password, - disableAutoFetch, - rangeChunkSize, - length, - docBaseUrl, - enableXfa, - evaluatorOptions: { - maxImageSize, - disableFontFace, - ignoreErrors, - isEvalSupported, - isOffscreenCanvasSupported, - canvasMaxAreaInBytes, - fontExtraProperties, - useSystemFonts, - cMapUrl: useWorkerFetch ? cMapUrl : null, - standardFontDataUrl: useWorkerFetch ? standardFontDataUrl : null - } - }; - const transportParams = { - ignoreErrors, - disableFontFace, - fontExtraProperties, - enableXfa, - ownerDocument, - disableAutoFetch, - pdfBug, - styleElement - }; - worker.promise.then(function () { - if (task.destroyed) { - throw new Error("Loading aborted"); - } - const workerIdPromise = _fetchDocument(worker, fetchDocParams); - const networkStreamPromise = new Promise(function (resolve) { - let networkStream; - if (rangeTransport) { - networkStream = new _transport_stream_js__WEBPACK_IMPORTED_MODULE_10__.PDFDataTransportStream(rangeTransport, { - disableRange, - disableStream - }); - } else if (!data) { - const createPDFNetworkStream = params => { - if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS) { - const isFetchSupported = function () { - return typeof fetch !== "undefined" && typeof Response !== "undefined" && "body" in Response.prototype; - }; - return isFetchSupported() && (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isValidFetchUrl)(params.url) ? new display_fetch_stream__WEBPACK_IMPORTED_MODULE_11__.PDFFetchStream(params) : new display_node_stream__WEBPACK_IMPORTED_MODULE_13__.PDFNodeStream(params); - } - return (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isValidFetchUrl)(params.url) ? new display_fetch_stream__WEBPACK_IMPORTED_MODULE_11__.PDFFetchStream(params) : new display_network__WEBPACK_IMPORTED_MODULE_12__.PDFNetworkStream(params); - }; - networkStream = createPDFNetworkStream({ - url, - length, - httpHeaders, - withCredentials, - rangeChunkSize, - disableRange, - disableStream - }); - } - resolve(networkStream); - }); - return Promise.all([workerIdPromise, networkStreamPromise]).then(function ([workerId, networkStream]) { - if (task.destroyed) { - throw new Error("Loading aborted"); - } - const messageHandler = new _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__.MessageHandler(docId, workerId, worker.port); - const transport = new WorkerTransport(messageHandler, task, networkStream, transportParams, transportFactory); - task._transport = transport; - messageHandler.send("Ready", null); - }); - }).catch(task._capability.reject); - return task; -} -async function _fetchDocument(worker, source) { - if (worker.destroyed) { - throw new Error("Worker was destroyed"); - } - const workerId = await worker.messageHandler.sendWithPromise("GetDocRequest", source, source.data ? [source.data.buffer] : null); - if (worker.destroyed) { - throw new Error("Worker was destroyed"); - } - return workerId; -} -function getUrlProp(val) { - if (val instanceof URL) { - return val.href; - } - try { - return new URL(val, window.location).href; - } catch { - if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS && typeof val === "string") { - return val; - } - } - throw new Error("Invalid PDF url data: " + "either string or URL-object is expected in the url property."); -} -function getDataProp(val) { - if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS && typeof Buffer !== "undefined" && val instanceof Buffer) { - throw new Error("Please provide binary data as `Uint8Array`, rather than `Buffer`."); - } - if (val instanceof Uint8Array && val.byteLength === val.buffer.byteLength) { - return val; - } - if (typeof val === "string") { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.stringToBytes)(val); - } - if (val instanceof ArrayBuffer || ArrayBuffer.isView(val) || typeof val === "object" && !isNaN(val?.length)) { - return new Uint8Array(val); - } - throw new Error("Invalid PDF binary data: either TypedArray, " + "string, or array-like object is expected in the data property."); -} -function isRefProxy(ref) { - return typeof ref === "object" && Number.isInteger(ref?.num) && ref.num >= 0 && Number.isInteger(ref?.gen) && ref.gen >= 0; -} -class PDFDocumentLoadingTask { - static #docId = 0; - constructor() { - this._capability = Promise.withResolvers(); - this._transport = null; - this._worker = null; - this.docId = `d${PDFDocumentLoadingTask.#docId++}`; - this.destroyed = false; - this.onPassword = null; - this.onProgress = null; - } - get promise() { - return this._capability.promise; - } - async destroy() { - this.destroyed = true; - try { - if (this._worker?.port) { - this._worker._pendingDestroy = true; - } - await this._transport?.destroy(); - } catch (ex) { - if (this._worker?.port) { - delete this._worker._pendingDestroy; - } - throw ex; - } - this._transport = null; - if (this._worker) { - this._worker.destroy(); - this._worker = null; - } - } -} -class PDFDataRangeTransport { - constructor(length, initialData, progressiveDone = false, contentDispositionFilename = null) { - this.length = length; - this.initialData = initialData; - this.progressiveDone = progressiveDone; - this.contentDispositionFilename = contentDispositionFilename; - this._rangeListeners = []; - this._progressListeners = []; - this._progressiveReadListeners = []; - this._progressiveDoneListeners = []; - this._readyCapability = Promise.withResolvers(); - } - addRangeListener(listener) { - this._rangeListeners.push(listener); - } - addProgressListener(listener) { - this._progressListeners.push(listener); - } - addProgressiveReadListener(listener) { - this._progressiveReadListeners.push(listener); - } - addProgressiveDoneListener(listener) { - this._progressiveDoneListeners.push(listener); - } - onDataRange(begin, chunk) { - for (const listener of this._rangeListeners) { - listener(begin, chunk); - } - } - onDataProgress(loaded, total) { - this._readyCapability.promise.then(() => { - for (const listener of this._progressListeners) { - listener(loaded, total); - } - }); - } - onDataProgressiveRead(chunk) { - this._readyCapability.promise.then(() => { - for (const listener of this._progressiveReadListeners) { - listener(chunk); - } - }); - } - onDataProgressiveDone() { - this._readyCapability.promise.then(() => { - for (const listener of this._progressiveDoneListeners) { - listener(); - } - }); - } - transportReady() { - this._readyCapability.resolve(); - } - requestDataRange(begin, end) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Abstract method PDFDataRangeTransport.requestDataRange"); - } - abort() {} -} -class PDFDocumentProxy { - constructor(pdfInfo, transport) { - this._pdfInfo = pdfInfo; - this._transport = transport; - } - get annotationStorage() { - return this._transport.annotationStorage; - } - get filterFactory() { - return this._transport.filterFactory; - } - get numPages() { - return this._pdfInfo.numPages; - } - get fingerprints() { - return this._pdfInfo.fingerprints; - } - get isPureXfa() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "isPureXfa", !!this._transport._htmlForXfa); - } - get allXfaHtml() { - return this._transport._htmlForXfa; - } - getPage(pageNumber) { - return this._transport.getPage(pageNumber); - } - getPageIndex(ref) { - return this._transport.getPageIndex(ref); - } - getDestinations() { - return this._transport.getDestinations(); - } - getDestination(id) { - return this._transport.getDestination(id); - } - getPageLabels() { - return this._transport.getPageLabels(); - } - getPageLayout() { - return this._transport.getPageLayout(); - } - getPageMode() { - return this._transport.getPageMode(); - } - getViewerPreferences() { - return this._transport.getViewerPreferences(); - } - getOpenAction() { - return this._transport.getOpenAction(); - } - getAttachments() { - return this._transport.getAttachments(); - } - getJSActions() { - return this._transport.getDocJSActions(); - } - getOutline() { - return this._transport.getOutline(); - } - getOptionalContentConfig({ - intent = "display" - } = {}) { - const { - renderingIntent - } = this._transport.getRenderingIntent(intent); - return this._transport.getOptionalContentConfig(renderingIntent); - } - getPermissions() { - return this._transport.getPermissions(); - } - getMetadata() { - return this._transport.getMetadata(); - } - getMarkInfo() { - return this._transport.getMarkInfo(); - } - getData() { - return this._transport.getData(); - } - saveDocument() { - return this._transport.saveDocument(); - } - getDownloadInfo() { - return this._transport.downloadInfoCapability.promise; - } - cleanup(keepLoadedFonts = false) { - return this._transport.startCleanup(keepLoadedFonts || this.isPureXfa); - } - destroy() { - return this.loadingTask.destroy(); - } - cachedPageNumber(ref) { - return this._transport.cachedPageNumber(ref); - } - get loadingParams() { - return this._transport.loadingParams; - } - get loadingTask() { - return this._transport.loadingTask; - } - getFieldObjects() { - return this._transport.getFieldObjects(); - } - hasJSActions() { - return this._transport.hasJSActions(); - } - getCalculationOrderIds() { - return this._transport.getCalculationOrderIds(); - } -} -class PDFPageProxy { - #delayedCleanupTimeout = null; - #pendingCleanup = false; - constructor(pageIndex, pageInfo, transport, pdfBug = false) { - this._pageIndex = pageIndex; - this._pageInfo = pageInfo; - this._transport = transport; - this._stats = pdfBug ? new _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.StatTimer() : null; - this._pdfBug = pdfBug; - this.commonObjs = transport.commonObjs; - this.objs = new PDFObjects(); - this._maybeCleanupAfterRender = false; - this._intentStates = new Map(); - this.destroyed = false; - } - get pageNumber() { - return this._pageIndex + 1; - } - get rotate() { - return this._pageInfo.rotate; - } - get ref() { - return this._pageInfo.ref; - } - get userUnit() { - return this._pageInfo.userUnit; - } - get view() { - return this._pageInfo.view; - } - getViewport({ - scale, - rotation = this.rotate, - offsetX = 0, - offsetY = 0, - dontFlip = false - } = {}) { - return new _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.PageViewport({ - viewBox: this.view, - scale, - rotation, - offsetX, - offsetY, - dontFlip - }); - } - getAnnotations({ - intent = "display" - } = {}) { - const { - renderingIntent - } = this._transport.getRenderingIntent(intent); - return this._transport.getAnnotations(this._pageIndex, renderingIntent); - } - getJSActions() { - return this._transport.getPageJSActions(this._pageIndex); - } - get filterFactory() { - return this._transport.filterFactory; - } - get isPureXfa() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "isPureXfa", !!this._transport._htmlForXfa); - } - async getXfa() { - return this._transport._htmlForXfa?.children[this._pageIndex] || null; - } - render({ - canvasContext, - viewport, - intent = "display", - annotationMode = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE, - transform = null, - background = null, - optionalContentConfigPromise = null, - annotationCanvasMap = null, - pageColors = null, - printAnnotationStorage = null - }) { - this._stats?.time("Overall"); - const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage); - const { - renderingIntent, - cacheKey - } = intentArgs; - this.#pendingCleanup = false; - this.#abortDelayedCleanup(); - optionalContentConfigPromise ||= this._transport.getOptionalContentConfig(renderingIntent); - let intentState = this._intentStates.get(cacheKey); - if (!intentState) { - intentState = Object.create(null); - this._intentStates.set(cacheKey, intentState); - } - if (intentState.streamReaderCancelTimeout) { - clearTimeout(intentState.streamReaderCancelTimeout); - intentState.streamReaderCancelTimeout = null; - } - const intentPrint = !!(renderingIntent & _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.PRINT); - if (!intentState.displayReadyCapability) { - intentState.displayReadyCapability = Promise.withResolvers(); - intentState.operatorList = { - fnArray: [], - argsArray: [], - lastChunk: false, - separateAnnots: null - }; - this._stats?.time("Page Request"); - this._pumpOperatorList(intentArgs); - } - const complete = error => { - intentState.renderTasks.delete(internalRenderTask); - if (this._maybeCleanupAfterRender || intentPrint) { - this.#pendingCleanup = true; - } - this.#tryCleanup(!intentPrint); - if (error) { - internalRenderTask.capability.reject(error); - this._abortOperatorList({ - intentState, - reason: error instanceof Error ? error : new Error(error) - }); - } else { - internalRenderTask.capability.resolve(); - } - this._stats?.timeEnd("Rendering"); - this._stats?.timeEnd("Overall"); - }; - const internalRenderTask = new InternalRenderTask({ - callback: complete, - params: { - canvasContext, - viewport, - transform, - background - }, - objs: this.objs, - commonObjs: this.commonObjs, - annotationCanvasMap, - operatorList: intentState.operatorList, - pageIndex: this._pageIndex, - canvasFactory: this._transport.canvasFactory, - filterFactory: this._transport.filterFactory, - useRequestAnimationFrame: !intentPrint, - pdfBug: this._pdfBug, - pageColors - }); - (intentState.renderTasks ||= new Set()).add(internalRenderTask); - const renderTask = internalRenderTask.task; - Promise.all([intentState.displayReadyCapability.promise, optionalContentConfigPromise]).then(([transparency, optionalContentConfig]) => { - if (this.destroyed) { - complete(); - return; - } - this._stats?.time("Rendering"); - if (!(optionalContentConfig.renderingIntent & renderingIntent)) { - throw new Error("Must use the same `intent`-argument when calling the `PDFPageProxy.render` " + "and `PDFDocumentProxy.getOptionalContentConfig` methods."); - } - internalRenderTask.initializeGraphics({ - transparency, - optionalContentConfig - }); - internalRenderTask.operatorListChanged(); - }).catch(complete); - return renderTask; - } - getOperatorList({ - intent = "display", - annotationMode = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE, - printAnnotationStorage = null - } = {}) { - function operatorListChanged() { - if (intentState.operatorList.lastChunk) { - intentState.opListReadCapability.resolve(intentState.operatorList); - intentState.renderTasks.delete(opListTask); - } - } - const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, true); - let intentState = this._intentStates.get(intentArgs.cacheKey); - if (!intentState) { - intentState = Object.create(null); - this._intentStates.set(intentArgs.cacheKey, intentState); - } - let opListTask; - if (!intentState.opListReadCapability) { - opListTask = Object.create(null); - opListTask.operatorListChanged = operatorListChanged; - intentState.opListReadCapability = Promise.withResolvers(); - (intentState.renderTasks ||= new Set()).add(opListTask); - intentState.operatorList = { - fnArray: [], - argsArray: [], - lastChunk: false, - separateAnnots: null - }; - this._stats?.time("Page Request"); - this._pumpOperatorList(intentArgs); - } - return intentState.opListReadCapability.promise; - } - streamTextContent({ - includeMarkedContent = false, - disableNormalization = false - } = {}) { - const TEXT_CONTENT_CHUNK_SIZE = 100; - return this._transport.messageHandler.sendWithStream("GetTextContent", { - pageIndex: this._pageIndex, - includeMarkedContent: includeMarkedContent === true, - disableNormalization: disableNormalization === true - }, { - highWaterMark: TEXT_CONTENT_CHUNK_SIZE, - size(textContent) { - return textContent.items.length; - } - }); - } - getTextContent(params = {}) { - if (this._transport._htmlForXfa) { - return this.getXfa().then(xfa => _xfa_text_js__WEBPACK_IMPORTED_MODULE_15__.XfaText.textContent(xfa)); - } - const readableStream = this.streamTextContent(params); - return new Promise(function (resolve, reject) { - function pump() { - reader.read().then(function ({ - value, - done - }) { - if (done) { - resolve(textContent); - return; - } - Object.assign(textContent.styles, value.styles); - textContent.items.push(...value.items); - pump(); - }, reject); - } - const reader = readableStream.getReader(); - const textContent = { - items: [], - styles: Object.create(null) - }; - pump(); - }); - } - getStructTree() { - return this._transport.getStructTree(this._pageIndex); - } - _destroy() { - this.destroyed = true; - const waitOn = []; - for (const intentState of this._intentStates.values()) { - this._abortOperatorList({ - intentState, - reason: new Error("Page was destroyed."), - force: true - }); - if (intentState.opListReadCapability) { - continue; - } - for (const internalRenderTask of intentState.renderTasks) { - waitOn.push(internalRenderTask.completed); - internalRenderTask.cancel(); - } - } - this.objs.clear(); - this.#pendingCleanup = false; - this.#abortDelayedCleanup(); - return Promise.all(waitOn); - } - cleanup(resetStats = false) { - this.#pendingCleanup = true; - const success = this.#tryCleanup(false); - if (resetStats && success) { - this._stats &&= new _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.StatTimer(); - } - return success; - } - #tryCleanup(delayed = false) { - this.#abortDelayedCleanup(); - if (!this.#pendingCleanup || this.destroyed) { - return false; - } - if (delayed) { - this.#delayedCleanupTimeout = setTimeout(() => { - this.#delayedCleanupTimeout = null; - this.#tryCleanup(false); - }, DELAYED_CLEANUP_TIMEOUT); - return false; - } - for (const { - renderTasks, - operatorList - } of this._intentStates.values()) { - if (renderTasks.size > 0 || !operatorList.lastChunk) { - return false; - } - } - this._intentStates.clear(); - this.objs.clear(); - this.#pendingCleanup = false; - return true; - } - #abortDelayedCleanup() { - if (this.#delayedCleanupTimeout) { - clearTimeout(this.#delayedCleanupTimeout); - this.#delayedCleanupTimeout = null; - } - } - _startRenderPage(transparency, cacheKey) { - const intentState = this._intentStates.get(cacheKey); - if (!intentState) { - return; - } - this._stats?.timeEnd("Page Request"); - intentState.displayReadyCapability?.resolve(transparency); - } - _renderPageChunk(operatorListChunk, intentState) { - for (let i = 0, ii = operatorListChunk.length; i < ii; i++) { - intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]); - intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]); - } - intentState.operatorList.lastChunk = operatorListChunk.lastChunk; - intentState.operatorList.separateAnnots = operatorListChunk.separateAnnots; - for (const internalRenderTask of intentState.renderTasks) { - internalRenderTask.operatorListChanged(); - } - if (operatorListChunk.lastChunk) { - this.#tryCleanup(true); - } - } - _pumpOperatorList({ - renderingIntent, - cacheKey, - annotationStorageSerializable - }) { - const { - map, - transfer - } = annotationStorageSerializable; - const readableStream = this._transport.messageHandler.sendWithStream("GetOperatorList", { - pageIndex: this._pageIndex, - intent: renderingIntent, - cacheKey, - annotationStorage: map - }, transfer); - const reader = readableStream.getReader(); - const intentState = this._intentStates.get(cacheKey); - intentState.streamReader = reader; - const pump = () => { - reader.read().then(({ - value, - done - }) => { - if (done) { - intentState.streamReader = null; - return; - } - if (this._transport.destroyed) { - return; - } - this._renderPageChunk(value, intentState); - pump(); - }, reason => { - intentState.streamReader = null; - if (this._transport.destroyed) { - return; - } - if (intentState.operatorList) { - intentState.operatorList.lastChunk = true; - for (const internalRenderTask of intentState.renderTasks) { - internalRenderTask.operatorListChanged(); - } - this.#tryCleanup(true); - } - if (intentState.displayReadyCapability) { - intentState.displayReadyCapability.reject(reason); - } else if (intentState.opListReadCapability) { - intentState.opListReadCapability.reject(reason); - } else { - throw reason; - } - }); - }; - pump(); - } - _abortOperatorList({ - intentState, - reason, - force = false - }) { - if (!intentState.streamReader) { - return; - } - if (intentState.streamReaderCancelTimeout) { - clearTimeout(intentState.streamReaderCancelTimeout); - intentState.streamReaderCancelTimeout = null; - } - if (!force) { - if (intentState.renderTasks.size > 0) { - return; - } - if (reason instanceof _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.RenderingCancelledException) { - let delay = RENDERING_CANCELLED_TIMEOUT; - if (reason.extraDelay > 0 && reason.extraDelay < 1000) { - delay += reason.extraDelay; - } - intentState.streamReaderCancelTimeout = setTimeout(() => { - intentState.streamReaderCancelTimeout = null; - this._abortOperatorList({ - intentState, - reason, - force: true - }); - }, delay); - return; - } - } - intentState.streamReader.cancel(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException(reason.message)).catch(() => {}); - intentState.streamReader = null; - if (this._transport.destroyed) { - return; - } - for (const [curCacheKey, curIntentState] of this._intentStates) { - if (curIntentState === intentState) { - this._intentStates.delete(curCacheKey); - break; - } - } - this.cleanup(); - } - get stats() { - return this._stats; - } -} -class LoopbackPort { - #listeners = new Set(); - #deferred = Promise.resolve(); - postMessage(obj, transfer) { - const event = { - data: structuredClone(obj, transfer ? { - transfer - } : null) - }; - this.#deferred.then(() => { - for (const listener of this.#listeners) { - listener.call(this, event); - } - }); - } - addEventListener(name, listener) { - this.#listeners.add(listener); - } - removeEventListener(name, listener) { - this.#listeners.delete(listener); - } - terminate() { - this.#listeners.clear(); - } -} -const PDFWorkerUtil = { - isWorkerDisabled: false, - fakeWorkerId: 0 -}; -{ - if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS) { - PDFWorkerUtil.isWorkerDisabled = true; - _worker_options_js__WEBPACK_IMPORTED_MODULE_14__.GlobalWorkerOptions.workerSrc ||= "./pdf.worker.mjs"; - } - PDFWorkerUtil.isSameOrigin = function (baseUrl, otherUrl) { - let base; - try { - base = new URL(baseUrl); - if (!base.origin || base.origin === "null") { - return false; - } - } catch { - return false; - } - const other = new URL(otherUrl, base); - return base.origin === other.origin; - }; - PDFWorkerUtil.createCDNWrapper = function (url) { - const wrapper = `await import("${url}");`; - return URL.createObjectURL(new Blob([wrapper], { - type: "text/javascript" - })); - }; -} -class PDFWorker { - static #workerPorts; - constructor({ - name = null, - port = null, - verbosity = (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.getVerbosityLevel)() - } = {}) { - this.name = name; - this.destroyed = false; - this.verbosity = verbosity; - this._readyCapability = Promise.withResolvers(); - this._port = null; - this._webWorker = null; - this._messageHandler = null; - if (port) { - if (PDFWorker.#workerPorts?.has(port)) { - throw new Error("Cannot use more than one PDFWorker per port."); - } - (PDFWorker.#workerPorts ||= new WeakMap()).set(port, this); - this._initializeFromPort(port); - return; - } - this._initialize(); - } - get promise() { - return this._readyCapability.promise; - } - get port() { - return this._port; - } - get messageHandler() { - return this._messageHandler; - } - _initializeFromPort(port) { - this._port = port; - this._messageHandler = new _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__.MessageHandler("main", "worker", port); - this._messageHandler.on("ready", function () {}); - this._readyCapability.resolve(); - this._messageHandler.send("configure", { - verbosity: this.verbosity - }); - } - _initialize() { - if (!PDFWorkerUtil.isWorkerDisabled && !PDFWorker.#mainThreadWorkerMessageHandler) { - let { - workerSrc - } = PDFWorker; - try { - if (!PDFWorkerUtil.isSameOrigin(window.location.href, workerSrc)) { - workerSrc = PDFWorkerUtil.createCDNWrapper(new URL(workerSrc, window.location).href); - } - const worker = new Worker(workerSrc, { - type: "module" - }); - const messageHandler = new _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__.MessageHandler("main", "worker", worker); - const terminateEarly = () => { - worker.removeEventListener("error", onWorkerError); - messageHandler.destroy(); - worker.terminate(); - if (this.destroyed) { - this._readyCapability.reject(new Error("Worker was destroyed")); - } else { - this._setupFakeWorker(); - } - }; - const onWorkerError = () => { - if (!this._webWorker) { - terminateEarly(); - } - }; - worker.addEventListener("error", onWorkerError); - messageHandler.on("test", data => { - worker.removeEventListener("error", onWorkerError); - if (this.destroyed) { - terminateEarly(); - return; - } - if (data) { - this._messageHandler = messageHandler; - this._port = worker; - this._webWorker = worker; - this._readyCapability.resolve(); - messageHandler.send("configure", { - verbosity: this.verbosity - }); - } else { - this._setupFakeWorker(); - messageHandler.destroy(); - worker.terminate(); - } - }); - messageHandler.on("ready", data => { - worker.removeEventListener("error", onWorkerError); - if (this.destroyed) { - terminateEarly(); - return; - } - try { - sendTest(); - } catch { - this._setupFakeWorker(); - } - }); - const sendTest = () => { - const testObj = new Uint8Array(); - messageHandler.send("test", testObj, [testObj.buffer]); - }; - sendTest(); - return; - } catch { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.info)("The worker has been disabled."); - } - } - this._setupFakeWorker(); - } - _setupFakeWorker() { - if (!PDFWorkerUtil.isWorkerDisabled) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)("Setting up fake worker."); - PDFWorkerUtil.isWorkerDisabled = true; - } - PDFWorker._setupFakeWorkerGlobal.then(WorkerMessageHandler => { - if (this.destroyed) { - this._readyCapability.reject(new Error("Worker was destroyed")); - return; - } - const port = new LoopbackPort(); - this._port = port; - const id = `fake${PDFWorkerUtil.fakeWorkerId++}`; - const workerHandler = new _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__.MessageHandler(id + "_worker", id, port); - WorkerMessageHandler.setup(workerHandler, port); - const messageHandler = new _shared_message_handler_js__WEBPACK_IMPORTED_MODULE_7__.MessageHandler(id, id + "_worker", port); - this._messageHandler = messageHandler; - this._readyCapability.resolve(); - messageHandler.send("configure", { - verbosity: this.verbosity - }); - }).catch(reason => { - this._readyCapability.reject(new Error(`Setting up fake worker failed: "${reason.message}".`)); - }); - } - destroy() { - this.destroyed = true; - if (this._webWorker) { - this._webWorker.terminate(); - this._webWorker = null; - } - PDFWorker.#workerPorts?.delete(this._port); - this._port = null; - if (this._messageHandler) { - this._messageHandler.destroy(); - this._messageHandler = null; - } - } - static fromPort(params) { - if (!params?.port) { - throw new Error("PDFWorker.fromPort - invalid method signature."); - } - const cachedPort = this.#workerPorts?.get(params.port); - if (cachedPort) { - if (cachedPort._pendingDestroy) { - throw new Error("PDFWorker.fromPort - the worker is being destroyed.\n" + "Please remember to await `PDFDocumentLoadingTask.destroy()`-calls."); - } - return cachedPort; - } - return new PDFWorker(params); - } - static get workerSrc() { - if (_worker_options_js__WEBPACK_IMPORTED_MODULE_14__.GlobalWorkerOptions.workerSrc) { - return _worker_options_js__WEBPACK_IMPORTED_MODULE_14__.GlobalWorkerOptions.workerSrc; - } - throw new Error('No "GlobalWorkerOptions.workerSrc" specified.'); - } - static get #mainThreadWorkerMessageHandler() { - try { - return globalThis.pdfjsWorker?.WorkerMessageHandler || null; - } catch { - return null; - } - } - static get _setupFakeWorkerGlobal() { - const loader = async () => { - if (this.#mainThreadWorkerMessageHandler) { - return this.#mainThreadWorkerMessageHandler; - } - const worker = await import( /*webpackIgnore: true*/this.workerSrc); - return worker.WorkerMessageHandler; - }; - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "_setupFakeWorkerGlobal", loader()); - } -} -class WorkerTransport { - #methodPromises = new Map(); - #pageCache = new Map(); - #pagePromises = new Map(); - #pageRefCache = new Map(); - #passwordCapability = null; - constructor(messageHandler, loadingTask, networkStream, params, factory) { - this.messageHandler = messageHandler; - this.loadingTask = loadingTask; - this.commonObjs = new PDFObjects(); - this.fontLoader = new _font_loader_js__WEBPACK_IMPORTED_MODULE_3__.FontLoader({ - ownerDocument: params.ownerDocument, - styleElement: params.styleElement - }); - this._params = params; - this.canvasFactory = factory.canvasFactory; - this.filterFactory = factory.filterFactory; - this.cMapReaderFactory = factory.cMapReaderFactory; - this.standardFontDataFactory = factory.standardFontDataFactory; - this.destroyed = false; - this.destroyCapability = null; - this._networkStream = networkStream; - this._fullReader = null; - this._lastProgress = null; - this.downloadInfoCapability = Promise.withResolvers(); - this.setupMessageHandler(); - } - #cacheSimpleMethod(name, data = null) { - const cachedPromise = this.#methodPromises.get(name); - if (cachedPromise) { - return cachedPromise; - } - const promise = this.messageHandler.sendWithPromise(name, data); - this.#methodPromises.set(name, promise); - return promise; - } - get annotationStorage() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "annotationStorage", new _annotation_storage_js__WEBPACK_IMPORTED_MODULE_1__.AnnotationStorage()); - } - getRenderingIntent(intent, annotationMode = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE, printAnnotationStorage = null, isOpList = false) { - let renderingIntent = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.DISPLAY; - let annotationStorageSerializable = _annotation_storage_js__WEBPACK_IMPORTED_MODULE_1__.SerializableEmpty; - switch (intent) { - case "any": - renderingIntent = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.ANY; - break; - case "display": - break; - case "print": - renderingIntent = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.PRINT; - break; - default: - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`getRenderingIntent - invalid intent: ${intent}`); - } - switch (annotationMode) { - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.DISABLE: - renderingIntent += _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.ANNOTATIONS_DISABLE; - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE: - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS: - renderingIntent += _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.ANNOTATIONS_FORMS; - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_STORAGE: - renderingIntent += _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.ANNOTATIONS_STORAGE; - const annotationStorage = renderingIntent & _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.PRINT && printAnnotationStorage instanceof _annotation_storage_js__WEBPACK_IMPORTED_MODULE_1__.PrintAnnotationStorage ? printAnnotationStorage : this.annotationStorage; - annotationStorageSerializable = annotationStorage.serializable; - break; - default: - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`getRenderingIntent - invalid annotationMode: ${annotationMode}`); - } - if (isOpList) { - renderingIntent += _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.OPLIST; - } - return { - renderingIntent, - cacheKey: `${renderingIntent}_${annotationStorageSerializable.hash}`, - annotationStorageSerializable - }; - } - destroy() { - if (this.destroyCapability) { - return this.destroyCapability.promise; - } - this.destroyed = true; - this.destroyCapability = Promise.withResolvers(); - this.#passwordCapability?.reject(new Error("Worker was destroyed during onPassword callback")); - const waitOn = []; - for (const page of this.#pageCache.values()) { - waitOn.push(page._destroy()); - } - this.#pageCache.clear(); - this.#pagePromises.clear(); - this.#pageRefCache.clear(); - if (this.hasOwnProperty("annotationStorage")) { - this.annotationStorage.resetModified(); - } - const terminated = this.messageHandler.sendWithPromise("Terminate", null); - waitOn.push(terminated); - Promise.all(waitOn).then(() => { - this.commonObjs.clear(); - this.fontLoader.clear(); - this.#methodPromises.clear(); - this.filterFactory.destroy(); - (0,_text_layer_js__WEBPACK_IMPORTED_MODULE_6__.cleanupTextLayer)(); - this._networkStream?.cancelAllRequests(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException("Worker was terminated.")); - if (this.messageHandler) { - this.messageHandler.destroy(); - this.messageHandler = null; - } - this.destroyCapability.resolve(); - }, this.destroyCapability.reject); - return this.destroyCapability.promise; - } - setupMessageHandler() { - const { - messageHandler, - loadingTask - } = this; - messageHandler.on("GetReader", (data, sink) => { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(this._networkStream, "GetReader - no `IPDFStream` instance available."); - this._fullReader = this._networkStream.getFullReader(); - this._fullReader.onProgress = evt => { - this._lastProgress = { - loaded: evt.loaded, - total: evt.total - }; - }; - sink.onPull = () => { - this._fullReader.read().then(function ({ - value, - done - }) { - if (done) { - sink.close(); - return; - } - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(value instanceof ArrayBuffer, "GetReader - expected an ArrayBuffer."); - sink.enqueue(new Uint8Array(value), 1, [value]); - }).catch(reason => { - sink.error(reason); - }); - }; - sink.onCancel = reason => { - this._fullReader.cancel(reason); - sink.ready.catch(readyReason => { - if (this.destroyed) { - return; - } - throw readyReason; - }); - }; - }); - messageHandler.on("ReaderHeadersReady", data => { - const headersCapability = Promise.withResolvers(); - const fullReader = this._fullReader; - fullReader.headersReady.then(() => { - if (!fullReader.isStreamingSupported || !fullReader.isRangeSupported) { - if (this._lastProgress) { - loadingTask.onProgress?.(this._lastProgress); - } - fullReader.onProgress = evt => { - loadingTask.onProgress?.({ - loaded: evt.loaded, - total: evt.total - }); - }; - } - headersCapability.resolve({ - isStreamingSupported: fullReader.isStreamingSupported, - isRangeSupported: fullReader.isRangeSupported, - contentLength: fullReader.contentLength - }); - }, headersCapability.reject); - return headersCapability.promise; - }); - messageHandler.on("GetRangeReader", (data, sink) => { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(this._networkStream, "GetRangeReader - no `IPDFStream` instance available."); - const rangeReader = this._networkStream.getRangeReader(data.begin, data.end); - if (!rangeReader) { - sink.close(); - return; - } - sink.onPull = () => { - rangeReader.read().then(function ({ - value, - done - }) { - if (done) { - sink.close(); - return; - } - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(value instanceof ArrayBuffer, "GetRangeReader - expected an ArrayBuffer."); - sink.enqueue(new Uint8Array(value), 1, [value]); - }).catch(reason => { - sink.error(reason); - }); - }; - sink.onCancel = reason => { - rangeReader.cancel(reason); - sink.ready.catch(readyReason => { - if (this.destroyed) { - return; - } - throw readyReason; - }); - }; - }); - messageHandler.on("GetDoc", ({ - pdfInfo - }) => { - this._numPages = pdfInfo.numPages; - this._htmlForXfa = pdfInfo.htmlForXfa; - delete pdfInfo.htmlForXfa; - loadingTask._capability.resolve(new PDFDocumentProxy(pdfInfo, this)); - }); - messageHandler.on("DocException", function (ex) { - let reason; - switch (ex.name) { - case "PasswordException": - reason = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.PasswordException(ex.message, ex.code); - break; - case "InvalidPDFException": - reason = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.InvalidPDFException(ex.message); - break; - case "MissingPDFException": - reason = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException(ex.message); - break; - case "UnexpectedResponseException": - reason = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.UnexpectedResponseException(ex.message, ex.status); - break; - case "UnknownErrorException": - reason = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.UnknownErrorException(ex.message, ex.details); - break; - default: - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("DocException - expected a valid Error."); - } - loadingTask._capability.reject(reason); - }); - messageHandler.on("PasswordRequest", exception => { - this.#passwordCapability = Promise.withResolvers(); - if (loadingTask.onPassword) { - const updatePassword = password => { - if (password instanceof Error) { - this.#passwordCapability.reject(password); - } else { - this.#passwordCapability.resolve({ - password - }); - } - }; - try { - loadingTask.onPassword(updatePassword, exception.code); - } catch (ex) { - this.#passwordCapability.reject(ex); - } - } else { - this.#passwordCapability.reject(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.PasswordException(exception.message, exception.code)); - } - return this.#passwordCapability.promise; - }); - messageHandler.on("DataLoaded", data => { - loadingTask.onProgress?.({ - loaded: data.length, - total: data.length - }); - this.downloadInfoCapability.resolve(data); - }); - messageHandler.on("StartRenderPage", data => { - if (this.destroyed) { - return; - } - const page = this.#pageCache.get(data.pageIndex); - page._startRenderPage(data.transparency, data.cacheKey); - }); - messageHandler.on("commonobj", ([id, type, exportedData]) => { - if (this.destroyed) { - return null; - } - if (this.commonObjs.has(id)) { - return null; - } - switch (type) { - case "Font": - const params = this._params; - if ("error" in exportedData) { - const exportedError = exportedData.error; - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Error during font loading: ${exportedError}`); - this.commonObjs.resolve(id, exportedError); - break; - } - const inspectFont = params.pdfBug && globalThis.FontInspector?.enabled ? (font, url) => globalThis.FontInspector.fontAdded(font, url) : null; - const font = new _font_loader_js__WEBPACK_IMPORTED_MODULE_3__.FontFaceObject(exportedData, { - disableFontFace: params.disableFontFace, - ignoreErrors: params.ignoreErrors, - inspectFont - }); - this.fontLoader.bind(font).catch(() => messageHandler.sendWithPromise("FontFallback", { - id - })).finally(() => { - if (!params.fontExtraProperties && font.data) { - font.data = null; - } - this.commonObjs.resolve(id, font); - }); - break; - case "CopyLocalImage": - const { - imageRef - } = exportedData; - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(imageRef, "The imageRef must be defined."); - for (const pageProxy of this.#pageCache.values()) { - for (const [, data] of pageProxy.objs) { - if (data.ref !== imageRef) { - continue; - } - if (!data.dataLen) { - return null; - } - this.commonObjs.resolve(id, structuredClone(data)); - return data.dataLen; - } - } - break; - case "FontPath": - case "Image": - case "Pattern": - this.commonObjs.resolve(id, exportedData); - break; - default: - throw new Error(`Got unknown common object type ${type}`); - } - return null; - }); - messageHandler.on("obj", ([id, pageIndex, type, imageData]) => { - if (this.destroyed) { - return; - } - const pageProxy = this.#pageCache.get(pageIndex); - if (pageProxy.objs.has(id)) { - return; - } - if (pageProxy._intentStates.size === 0) { - imageData?.bitmap?.close(); - return; - } - switch (type) { - case "Image": - pageProxy.objs.resolve(id, imageData); - if (imageData?.dataLen > _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MAX_IMAGE_SIZE_TO_CACHE) { - pageProxy._maybeCleanupAfterRender = true; - } - break; - case "Pattern": - pageProxy.objs.resolve(id, imageData); - break; - default: - throw new Error(`Got unknown object type ${type}`); - } - }); - messageHandler.on("DocProgress", data => { - if (this.destroyed) { - return; - } - loadingTask.onProgress?.({ - loaded: data.loaded, - total: data.total - }); - }); - messageHandler.on("FetchBuiltInCMap", data => { - if (this.destroyed) { - return Promise.reject(new Error("Worker was destroyed.")); - } - if (!this.cMapReaderFactory) { - return Promise.reject(new Error("CMapReaderFactory not initialized, see the `useWorkerFetch` parameter.")); - } - return this.cMapReaderFactory.fetch(data); - }); - messageHandler.on("FetchStandardFontData", data => { - if (this.destroyed) { - return Promise.reject(new Error("Worker was destroyed.")); - } - if (!this.standardFontDataFactory) { - return Promise.reject(new Error("StandardFontDataFactory not initialized, see the `useWorkerFetch` parameter.")); - } - return this.standardFontDataFactory.fetch(data); - }); - } - getData() { - return this.messageHandler.sendWithPromise("GetData", null); - } - saveDocument() { - if (this.annotationStorage.size <= 0) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)("saveDocument called while `annotationStorage` is empty, " + "please use the getData-method instead."); - } - const { - map, - transfer - } = this.annotationStorage.serializable; - return this.messageHandler.sendWithPromise("SaveDocument", { - isPureXfa: !!this._htmlForXfa, - numPages: this._numPages, - annotationStorage: map, - filename: this._fullReader?.filename ?? null - }, transfer).finally(() => { - this.annotationStorage.resetModified(); - }); - } - getPage(pageNumber) { - if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this._numPages) { - return Promise.reject(new Error("Invalid page request.")); - } - const pageIndex = pageNumber - 1, - cachedPromise = this.#pagePromises.get(pageIndex); - if (cachedPromise) { - return cachedPromise; - } - const promise = this.messageHandler.sendWithPromise("GetPage", { - pageIndex - }).then(pageInfo => { - if (this.destroyed) { - throw new Error("Transport destroyed"); - } - if (pageInfo.refStr) { - this.#pageRefCache.set(pageInfo.refStr, pageNumber); - } - const page = new PDFPageProxy(pageIndex, pageInfo, this, this._params.pdfBug); - this.#pageCache.set(pageIndex, page); - return page; - }); - this.#pagePromises.set(pageIndex, promise); - return promise; - } - getPageIndex(ref) { - if (!isRefProxy(ref)) { - return Promise.reject(new Error("Invalid pageIndex request.")); - } - return this.messageHandler.sendWithPromise("GetPageIndex", { - num: ref.num, - gen: ref.gen - }); - } - getAnnotations(pageIndex, intent) { - return this.messageHandler.sendWithPromise("GetAnnotations", { - pageIndex, - intent - }); - } - getFieldObjects() { - return this.#cacheSimpleMethod("GetFieldObjects"); - } - hasJSActions() { - return this.#cacheSimpleMethod("HasJSActions"); - } - getCalculationOrderIds() { - return this.messageHandler.sendWithPromise("GetCalculationOrderIds", null); - } - getDestinations() { - return this.messageHandler.sendWithPromise("GetDestinations", null); - } - getDestination(id) { - if (typeof id !== "string") { - return Promise.reject(new Error("Invalid destination request.")); - } - return this.messageHandler.sendWithPromise("GetDestination", { - id - }); - } - getPageLabels() { - return this.messageHandler.sendWithPromise("GetPageLabels", null); - } - getPageLayout() { - return this.messageHandler.sendWithPromise("GetPageLayout", null); - } - getPageMode() { - return this.messageHandler.sendWithPromise("GetPageMode", null); - } - getViewerPreferences() { - return this.messageHandler.sendWithPromise("GetViewerPreferences", null); - } - getOpenAction() { - return this.messageHandler.sendWithPromise("GetOpenAction", null); - } - getAttachments() { - return this.messageHandler.sendWithPromise("GetAttachments", null); - } - getDocJSActions() { - return this.#cacheSimpleMethod("GetDocJSActions"); - } - getPageJSActions(pageIndex) { - return this.messageHandler.sendWithPromise("GetPageJSActions", { - pageIndex - }); - } - getStructTree(pageIndex) { - return this.messageHandler.sendWithPromise("GetStructTree", { - pageIndex - }); - } - getOutline() { - return this.messageHandler.sendWithPromise("GetOutline", null); - } - getOptionalContentConfig(renderingIntent) { - return this.#cacheSimpleMethod("GetOptionalContentConfig").then(data => new _optional_content_config_js__WEBPACK_IMPORTED_MODULE_9__.OptionalContentConfig(data, renderingIntent)); - } - getPermissions() { - return this.messageHandler.sendWithPromise("GetPermissions", null); - } - getMetadata() { - const name = "GetMetadata", - cachedPromise = this.#methodPromises.get(name); - if (cachedPromise) { - return cachedPromise; - } - const promise = this.messageHandler.sendWithPromise(name, null).then(results => ({ - info: results[0], - metadata: results[1] ? new _metadata_js__WEBPACK_IMPORTED_MODULE_8__.Metadata(results[1]) : null, - contentDispositionFilename: this._fullReader?.filename ?? null, - contentLength: this._fullReader?.contentLength ?? null - })); - this.#methodPromises.set(name, promise); - return promise; - } - getMarkInfo() { - return this.messageHandler.sendWithPromise("GetMarkInfo", null); - } - async startCleanup(keepLoadedFonts = false) { - if (this.destroyed) { - return; - } - await this.messageHandler.sendWithPromise("Cleanup", null); - for (const page of this.#pageCache.values()) { - const cleanupSuccessful = page.cleanup(); - if (!cleanupSuccessful) { - throw new Error(`startCleanup: Page ${page.pageNumber} is currently rendering.`); - } - } - this.commonObjs.clear(); - if (!keepLoadedFonts) { - this.fontLoader.clear(); - } - this.#methodPromises.clear(); - this.filterFactory.destroy(true); - (0,_text_layer_js__WEBPACK_IMPORTED_MODULE_6__.cleanupTextLayer)(); - } - cachedPageNumber(ref) { - if (!isRefProxy(ref)) { - return null; - } - const refStr = ref.gen === 0 ? `${ref.num}R` : `${ref.num}R${ref.gen}`; - return this.#pageRefCache.get(refStr) ?? null; - } - get loadingParams() { - const { - disableAutoFetch, - enableXfa - } = this._params; - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "loadingParams", { - disableAutoFetch, - enableXfa - }); - } -} -const INITIAL_DATA = Symbol("INITIAL_DATA"); -class PDFObjects { - #objs = Object.create(null); - #ensureObj(objId) { - return this.#objs[objId] ||= { - ...Promise.withResolvers(), - data: INITIAL_DATA - }; - } - get(objId, callback = null) { - if (callback) { - const obj = this.#ensureObj(objId); - obj.promise.then(() => callback(obj.data)); - return null; - } - const obj = this.#objs[objId]; - if (!obj || obj.data === INITIAL_DATA) { - throw new Error(`Requesting object that isn't resolved yet ${objId}.`); - } - return obj.data; - } - has(objId) { - const obj = this.#objs[objId]; - return !!obj && obj.data !== INITIAL_DATA; - } - resolve(objId, data = null) { - const obj = this.#ensureObj(objId); - obj.data = data; - obj.resolve(); - } - clear() { - for (const objId in this.#objs) { - const { - data - } = this.#objs[objId]; - data?.bitmap?.close(); - } - this.#objs = Object.create(null); - } - *[Symbol.iterator]() { - for (const objId in this.#objs) { - const { - data - } = this.#objs[objId]; - if (data === INITIAL_DATA) { - continue; - } - yield [objId, data]; - } - } -} -class RenderTask { - #internalRenderTask = null; - constructor(internalRenderTask) { - this.#internalRenderTask = internalRenderTask; - this.onContinue = null; - } - get promise() { - return this.#internalRenderTask.capability.promise; - } - cancel(extraDelay = 0) { - this.#internalRenderTask.cancel(null, extraDelay); - } - get separateAnnots() { - const { - separateAnnots - } = this.#internalRenderTask.operatorList; - if (!separateAnnots) { - return false; - } - const { - annotationCanvasMap - } = this.#internalRenderTask; - return separateAnnots.form || separateAnnots.canvas && annotationCanvasMap?.size > 0; - } -} -class InternalRenderTask { - static #canvasInUse = new WeakSet(); - constructor({ - callback, - params, - objs, - commonObjs, - annotationCanvasMap, - operatorList, - pageIndex, - canvasFactory, - filterFactory, - useRequestAnimationFrame = false, - pdfBug = false, - pageColors = null - }) { - this.callback = callback; - this.params = params; - this.objs = objs; - this.commonObjs = commonObjs; - this.annotationCanvasMap = annotationCanvasMap; - this.operatorListIdx = null; - this.operatorList = operatorList; - this._pageIndex = pageIndex; - this.canvasFactory = canvasFactory; - this.filterFactory = filterFactory; - this._pdfBug = pdfBug; - this.pageColors = pageColors; - this.running = false; - this.graphicsReadyCallback = null; - this.graphicsReady = false; - this._useRequestAnimationFrame = useRequestAnimationFrame === true && typeof window !== "undefined"; - this.cancelled = false; - this.capability = Promise.withResolvers(); - this.task = new RenderTask(this); - this._cancelBound = this.cancel.bind(this); - this._continueBound = this._continue.bind(this); - this._scheduleNextBound = this._scheduleNext.bind(this); - this._nextBound = this._next.bind(this); - this._canvas = params.canvasContext.canvas; - } - get completed() { - return this.capability.promise.catch(function () {}); - } - initializeGraphics({ - transparency = false, - optionalContentConfig - }) { - if (this.cancelled) { - return; - } - if (this._canvas) { - if (InternalRenderTask.#canvasInUse.has(this._canvas)) { - throw new Error("Cannot use the same canvas during multiple render() operations. " + "Use different canvas or ensure previous operations were " + "cancelled or completed."); - } - InternalRenderTask.#canvasInUse.add(this._canvas); - } - if (this._pdfBug && globalThis.StepperManager?.enabled) { - this.stepper = globalThis.StepperManager.create(this._pageIndex); - this.stepper.init(this.operatorList); - this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint(); - } - const { - canvasContext, - viewport, - transform, - background - } = this.params; - this.gfx = new _canvas_js__WEBPACK_IMPORTED_MODULE_5__.CanvasGraphics(canvasContext, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, { - optionalContentConfig - }, this.annotationCanvasMap, this.pageColors); - this.gfx.beginDrawing({ - transform, - viewport, - transparency, - background - }); - this.operatorListIdx = 0; - this.graphicsReady = true; - this.graphicsReadyCallback?.(); - } - cancel(error = null, extraDelay = 0) { - this.running = false; - this.cancelled = true; - this.gfx?.endDrawing(); - InternalRenderTask.#canvasInUse.delete(this._canvas); - this.callback(error || new _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.RenderingCancelledException(`Rendering cancelled, page ${this._pageIndex + 1}`, extraDelay)); - } - operatorListChanged() { - if (!this.graphicsReady) { - this.graphicsReadyCallback ||= this._continueBound; - return; - } - this.stepper?.updateOperatorList(this.operatorList); - if (this.running) { - return; - } - this._continue(); - } - _continue() { - this.running = true; - if (this.cancelled) { - return; - } - if (this.task.onContinue) { - this.task.onContinue(this._scheduleNextBound); - } else { - this._scheduleNext(); - } - } - _scheduleNext() { - if (this._useRequestAnimationFrame) { - window.requestAnimationFrame(() => { - this._nextBound().catch(this._cancelBound); - }); - } else { - Promise.resolve().then(this._nextBound).catch(this._cancelBound); - } - } - async _next() { - if (this.cancelled) { - return; - } - this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, this.operatorListIdx, this._continueBound, this.stepper); - if (this.operatorListIdx === this.operatorList.argsArray.length) { - this.running = false; - if (this.operatorList.lastChunk) { - this.gfx.endDrawing(); - InternalRenderTask.#canvasInUse.delete(this._canvas); - this.callback(); - } - } - } -} -const version = "4.2.67"; -const build = "49b388101"; - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 583: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ BaseCMapReaderFactory: () => (/* binding */ BaseCMapReaderFactory), -/* harmony export */ BaseCanvasFactory: () => (/* binding */ BaseCanvasFactory), -/* harmony export */ BaseFilterFactory: () => (/* binding */ BaseFilterFactory), -/* harmony export */ BaseSVGFactory: () => (/* binding */ BaseSVGFactory), -/* harmony export */ BaseStandardFontDataFactory: () => (/* binding */ BaseStandardFontDataFactory) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); - -class BaseFilterFactory { - constructor() { - if (this.constructor === BaseFilterFactory) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Cannot initialize BaseFilterFactory."); - } - } - addFilter(maps) { - return "none"; - } - addHCMFilter(fgColor, bgColor) { - return "none"; - } - addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { - return "none"; - } - destroy(keepHCM = false) {} -} -class BaseCanvasFactory { - constructor() { - if (this.constructor === BaseCanvasFactory) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Cannot initialize BaseCanvasFactory."); - } - } - create(width, height) { - if (width <= 0 || height <= 0) { - throw new Error("Invalid canvas size"); - } - const canvas = this._createCanvas(width, height); - return { - canvas, - context: canvas.getContext("2d") - }; - } - reset(canvasAndContext, width, height) { - if (!canvasAndContext.canvas) { - throw new Error("Canvas is not specified"); - } - if (width <= 0 || height <= 0) { - throw new Error("Invalid canvas size"); - } - canvasAndContext.canvas.width = width; - canvasAndContext.canvas.height = height; - } - destroy(canvasAndContext) { - if (!canvasAndContext.canvas) { - throw new Error("Canvas is not specified"); - } - canvasAndContext.canvas.width = 0; - canvasAndContext.canvas.height = 0; - canvasAndContext.canvas = null; - canvasAndContext.context = null; - } - _createCanvas(width, height) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Abstract method `_createCanvas` called."); - } -} -class BaseCMapReaderFactory { - constructor({ - baseUrl = null, - isCompressed = true - }) { - if (this.constructor === BaseCMapReaderFactory) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Cannot initialize BaseCMapReaderFactory."); - } - this.baseUrl = baseUrl; - this.isCompressed = isCompressed; - } - async fetch({ - name - }) { - if (!this.baseUrl) { - throw new Error('The CMap "baseUrl" parameter must be specified, ensure that ' + 'the "cMapUrl" and "cMapPacked" API parameters are provided.'); - } - if (!name) { - throw new Error("CMap name must be specified."); - } - const url = this.baseUrl + name + (this.isCompressed ? ".bcmap" : ""); - const compressionType = this.isCompressed ? _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.CMapCompressionType.BINARY : _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.CMapCompressionType.NONE; - return this._fetchData(url, compressionType).catch(reason => { - throw new Error(`Unable to load ${this.isCompressed ? "binary " : ""}CMap at: ${url}`); - }); - } - _fetchData(url, compressionType) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Abstract method `_fetchData` called."); - } -} -class BaseStandardFontDataFactory { - constructor({ - baseUrl = null - }) { - if (this.constructor === BaseStandardFontDataFactory) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Cannot initialize BaseStandardFontDataFactory."); - } - this.baseUrl = baseUrl; - } - async fetch({ - filename - }) { - if (!this.baseUrl) { - throw new Error('The standard font "baseUrl" parameter must be specified, ensure that ' + 'the "standardFontDataUrl" API parameter is provided.'); - } - if (!filename) { - throw new Error("Font filename must be specified."); - } - const url = `${this.baseUrl}${filename}`; - return this._fetchData(url).catch(reason => { - throw new Error(`Unable to load font data at: ${url}`); - }); - } - _fetchData(url) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Abstract method `_fetchData` called."); - } -} -class BaseSVGFactory { - constructor() { - if (this.constructor === BaseSVGFactory) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Cannot initialize BaseSVGFactory."); - } - } - create(width, height, skipDimensions = false) { - if (width <= 0 || height <= 0) { - throw new Error("Invalid SVG dimensions"); - } - const svg = this._createSVG("svg:svg"); - svg.setAttribute("version", "1.1"); - if (!skipDimensions) { - svg.setAttribute("width", `${width}px`); - svg.setAttribute("height", `${height}px`); - } - svg.setAttribute("preserveAspectRatio", "none"); - svg.setAttribute("viewBox", `0 0 ${width} ${height}`); - return svg; - } - createElement(type) { - if (typeof type !== "string") { - throw new Error("Invalid SVG element type"); - } - return this._createSVG(type); - } - _createSVG(type) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Abstract method `_createSVG` called."); - } -} - - -/***/ }), - -/***/ 923: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - - -// EXPORTS -__webpack_require__.d(__webpack_exports__, { - CanvasGraphics: () => (/* binding */ CanvasGraphics) -}); - -// EXTERNAL MODULE: ./src/shared/util.js -var util = __webpack_require__(292); -// EXTERNAL MODULE: ./src/display/display_utils.js -var display_utils = __webpack_require__(419); -;// CONCATENATED MODULE: ./src/display/pattern_helper.js - - -const PathType = { - FILL: "Fill", - STROKE: "Stroke", - SHADING: "Shading" -}; -function applyBoundingBox(ctx, bbox) { - if (!bbox) { - return; - } - const width = bbox[2] - bbox[0]; - const height = bbox[3] - bbox[1]; - const region = new Path2D(); - region.rect(bbox[0], bbox[1], width, height); - ctx.clip(region); -} -class BaseShadingPattern { - constructor() { - if (this.constructor === BaseShadingPattern) { - (0,util.unreachable)("Cannot initialize BaseShadingPattern."); - } - } - getPattern() { - (0,util.unreachable)("Abstract method `getPattern` called."); - } -} -class RadialAxialShadingPattern extends BaseShadingPattern { - constructor(IR) { - super(); - this._type = IR[1]; - this._bbox = IR[2]; - this._colorStops = IR[3]; - this._p0 = IR[4]; - this._p1 = IR[5]; - this._r0 = IR[6]; - this._r1 = IR[7]; - this.matrix = null; - } - _createGradient(ctx) { - let grad; - if (this._type === "axial") { - grad = ctx.createLinearGradient(this._p0[0], this._p0[1], this._p1[0], this._p1[1]); - } else if (this._type === "radial") { - grad = ctx.createRadialGradient(this._p0[0], this._p0[1], this._r0, this._p1[0], this._p1[1], this._r1); - } - for (const colorStop of this._colorStops) { - grad.addColorStop(colorStop[0], colorStop[1]); - } - return grad; - } - getPattern(ctx, owner, inverse, pathType) { - let pattern; - if (pathType === PathType.STROKE || pathType === PathType.FILL) { - const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, (0,display_utils.getCurrentTransform)(ctx)) || [0, 0, 0, 0]; - const width = Math.ceil(ownerBBox[2] - ownerBBox[0]) || 1; - const height = Math.ceil(ownerBBox[3] - ownerBBox[1]) || 1; - const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", width, height, true); - const tmpCtx = tmpCanvas.context; - tmpCtx.clearRect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height); - tmpCtx.beginPath(); - tmpCtx.rect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height); - tmpCtx.translate(-ownerBBox[0], -ownerBBox[1]); - inverse = util.Util.transform(inverse, [1, 0, 0, 1, ownerBBox[0], ownerBBox[1]]); - tmpCtx.transform(...owner.baseTransform); - if (this.matrix) { - tmpCtx.transform(...this.matrix); - } - applyBoundingBox(tmpCtx, this._bbox); - tmpCtx.fillStyle = this._createGradient(tmpCtx); - tmpCtx.fill(); - pattern = ctx.createPattern(tmpCanvas.canvas, "no-repeat"); - const domMatrix = new DOMMatrix(inverse); - pattern.setTransform(domMatrix); - } else { - applyBoundingBox(ctx, this._bbox); - pattern = this._createGradient(ctx); - } - return pattern; - } -} -function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) { - const coords = context.coords, - colors = context.colors; - const bytes = data.data, - rowSize = data.width * 4; - let tmp; - if (coords[p1 + 1] > coords[p2 + 1]) { - tmp = p1; - p1 = p2; - p2 = tmp; - tmp = c1; - c1 = c2; - c2 = tmp; - } - if (coords[p2 + 1] > coords[p3 + 1]) { - tmp = p2; - p2 = p3; - p3 = tmp; - tmp = c2; - c2 = c3; - c3 = tmp; - } - if (coords[p1 + 1] > coords[p2 + 1]) { - tmp = p1; - p1 = p2; - p2 = tmp; - tmp = c1; - c1 = c2; - c2 = tmp; - } - const x1 = (coords[p1] + context.offsetX) * context.scaleX; - const y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY; - const x2 = (coords[p2] + context.offsetX) * context.scaleX; - const y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY; - const x3 = (coords[p3] + context.offsetX) * context.scaleX; - const y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY; - if (y1 >= y3) { - return; - } - const c1r = colors[c1], - c1g = colors[c1 + 1], - c1b = colors[c1 + 2]; - const c2r = colors[c2], - c2g = colors[c2 + 1], - c2b = colors[c2 + 2]; - const c3r = colors[c3], - c3g = colors[c3 + 1], - c3b = colors[c3 + 2]; - const minY = Math.round(y1), - maxY = Math.round(y3); - let xa, car, cag, cab; - let xb, cbr, cbg, cbb; - for (let y = minY; y <= maxY; y++) { - if (y < y2) { - const k = y < y1 ? 0 : (y1 - y) / (y1 - y2); - xa = x1 - (x1 - x2) * k; - car = c1r - (c1r - c2r) * k; - cag = c1g - (c1g - c2g) * k; - cab = c1b - (c1b - c2b) * k; - } else { - let k; - if (y > y3) { - k = 1; - } else if (y2 === y3) { - k = 0; - } else { - k = (y2 - y) / (y2 - y3); - } - xa = x2 - (x2 - x3) * k; - car = c2r - (c2r - c3r) * k; - cag = c2g - (c2g - c3g) * k; - cab = c2b - (c2b - c3b) * k; - } - let k; - if (y < y1) { - k = 0; - } else if (y > y3) { - k = 1; - } else { - k = (y1 - y) / (y1 - y3); - } - xb = x1 - (x1 - x3) * k; - cbr = c1r - (c1r - c3r) * k; - cbg = c1g - (c1g - c3g) * k; - cbb = c1b - (c1b - c3b) * k; - const x1_ = Math.round(Math.min(xa, xb)); - const x2_ = Math.round(Math.max(xa, xb)); - let j = rowSize * y + x1_ * 4; - for (let x = x1_; x <= x2_; x++) { - k = (xa - x) / (xa - xb); - if (k < 0) { - k = 0; - } else if (k > 1) { - k = 1; - } - bytes[j++] = car - (car - cbr) * k | 0; - bytes[j++] = cag - (cag - cbg) * k | 0; - bytes[j++] = cab - (cab - cbb) * k | 0; - bytes[j++] = 255; - } - } -} -function drawFigure(data, figure, context) { - const ps = figure.coords; - const cs = figure.colors; - let i, ii; - switch (figure.type) { - case "lattice": - const verticesPerRow = figure.verticesPerRow; - const rows = Math.floor(ps.length / verticesPerRow) - 1; - const cols = verticesPerRow - 1; - for (i = 0; i < rows; i++) { - let q = i * verticesPerRow; - for (let j = 0; j < cols; j++, q++) { - drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]); - drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]); - } - } - break; - case "triangles": - for (i = 0, ii = ps.length; i < ii; i += 3) { - drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]); - } - break; - default: - throw new Error("illegal figure"); - } -} -class MeshShadingPattern extends BaseShadingPattern { - constructor(IR) { - super(); - this._coords = IR[2]; - this._colors = IR[3]; - this._figures = IR[4]; - this._bounds = IR[5]; - this._bbox = IR[7]; - this._background = IR[8]; - this.matrix = null; - } - _createMeshCanvas(combinedScale, backgroundColor, cachedCanvases) { - const EXPECTED_SCALE = 1.1; - const MAX_PATTERN_SIZE = 3000; - const BORDER_SIZE = 2; - const offsetX = Math.floor(this._bounds[0]); - const offsetY = Math.floor(this._bounds[1]); - const boundsWidth = Math.ceil(this._bounds[2]) - offsetX; - const boundsHeight = Math.ceil(this._bounds[3]) - offsetY; - const width = Math.min(Math.ceil(Math.abs(boundsWidth * combinedScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE); - const height = Math.min(Math.ceil(Math.abs(boundsHeight * combinedScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE); - const scaleX = boundsWidth / width; - const scaleY = boundsHeight / height; - const context = { - coords: this._coords, - colors: this._colors, - offsetX: -offsetX, - offsetY: -offsetY, - scaleX: 1 / scaleX, - scaleY: 1 / scaleY - }; - const paddedWidth = width + BORDER_SIZE * 2; - const paddedHeight = height + BORDER_SIZE * 2; - const tmpCanvas = cachedCanvases.getCanvas("mesh", paddedWidth, paddedHeight, false); - const tmpCtx = tmpCanvas.context; - const data = tmpCtx.createImageData(width, height); - if (backgroundColor) { - const bytes = data.data; - for (let i = 0, ii = bytes.length; i < ii; i += 4) { - bytes[i] = backgroundColor[0]; - bytes[i + 1] = backgroundColor[1]; - bytes[i + 2] = backgroundColor[2]; - bytes[i + 3] = 255; - } - } - for (const figure of this._figures) { - drawFigure(data, figure, context); - } - tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE); - const canvas = tmpCanvas.canvas; - return { - canvas, - offsetX: offsetX - BORDER_SIZE * scaleX, - offsetY: offsetY - BORDER_SIZE * scaleY, - scaleX, - scaleY - }; - } - getPattern(ctx, owner, inverse, pathType) { - applyBoundingBox(ctx, this._bbox); - let scale; - if (pathType === PathType.SHADING) { - scale = util.Util.singularValueDecompose2dScale((0,display_utils.getCurrentTransform)(ctx)); - } else { - scale = util.Util.singularValueDecompose2dScale(owner.baseTransform); - if (this.matrix) { - const matrixScale = util.Util.singularValueDecompose2dScale(this.matrix); - scale = [scale[0] * matrixScale[0], scale[1] * matrixScale[1]]; - } - } - const temporaryPatternCanvas = this._createMeshCanvas(scale, pathType === PathType.SHADING ? null : this._background, owner.cachedCanvases); - if (pathType !== PathType.SHADING) { - ctx.setTransform(...owner.baseTransform); - if (this.matrix) { - ctx.transform(...this.matrix); - } - } - ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY); - ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY); - return ctx.createPattern(temporaryPatternCanvas.canvas, "no-repeat"); - } -} -class DummyShadingPattern extends BaseShadingPattern { - getPattern() { - return "hotpink"; - } -} -function getShadingPattern(IR) { - switch (IR[0]) { - case "RadialAxial": - return new RadialAxialShadingPattern(IR); - case "Mesh": - return new MeshShadingPattern(IR); - case "Dummy": - return new DummyShadingPattern(); - } - throw new Error(`Unknown IR type: ${IR[0]}`); -} -const PaintType = { - COLORED: 1, - UNCOLORED: 2 -}; -class TilingPattern { - static MAX_PATTERN_SIZE = 3000; - constructor(IR, color, ctx, canvasGraphicsFactory, baseTransform) { - this.operatorList = IR[2]; - this.matrix = IR[3] || [1, 0, 0, 1, 0, 0]; - this.bbox = IR[4]; - this.xstep = IR[5]; - this.ystep = IR[6]; - this.paintType = IR[7]; - this.tilingType = IR[8]; - this.color = color; - this.ctx = ctx; - this.canvasGraphicsFactory = canvasGraphicsFactory; - this.baseTransform = baseTransform; - } - createPatternCanvas(owner) { - const operatorList = this.operatorList; - const bbox = this.bbox; - const xstep = this.xstep; - const ystep = this.ystep; - const paintType = this.paintType; - const tilingType = this.tilingType; - const color = this.color; - const canvasGraphicsFactory = this.canvasGraphicsFactory; - (0,util.info)("TilingType: " + tilingType); - const x0 = bbox[0], - y0 = bbox[1], - x1 = bbox[2], - y1 = bbox[3]; - const matrixScale = util.Util.singularValueDecompose2dScale(this.matrix); - const curMatrixScale = util.Util.singularValueDecompose2dScale(this.baseTransform); - const combinedScale = [matrixScale[0] * curMatrixScale[0], matrixScale[1] * curMatrixScale[1]]; - const dimx = this.getSizeAndScale(xstep, this.ctx.canvas.width, combinedScale[0]); - const dimy = this.getSizeAndScale(ystep, this.ctx.canvas.height, combinedScale[1]); - const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", dimx.size, dimy.size, true); - const tmpCtx = tmpCanvas.context; - const graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx); - graphics.groupLevel = owner.groupLevel; - this.setFillAndStrokeStyleToContext(graphics, paintType, color); - let adjustedX0 = x0; - let adjustedY0 = y0; - let adjustedX1 = x1; - let adjustedY1 = y1; - if (x0 < 0) { - adjustedX0 = 0; - adjustedX1 += Math.abs(x0); - } - if (y0 < 0) { - adjustedY0 = 0; - adjustedY1 += Math.abs(y0); - } - tmpCtx.translate(-(dimx.scale * adjustedX0), -(dimy.scale * adjustedY0)); - graphics.transform(dimx.scale, 0, 0, dimy.scale, 0, 0); - tmpCtx.save(); - this.clipBbox(graphics, adjustedX0, adjustedY0, adjustedX1, adjustedY1); - graphics.baseTransform = (0,display_utils.getCurrentTransform)(graphics.ctx); - graphics.executeOperatorList(operatorList); - graphics.endDrawing(); - return { - canvas: tmpCanvas.canvas, - scaleX: dimx.scale, - scaleY: dimy.scale, - offsetX: adjustedX0, - offsetY: adjustedY0 - }; - } - getSizeAndScale(step, realOutputSize, scale) { - step = Math.abs(step); - const maxSize = Math.max(TilingPattern.MAX_PATTERN_SIZE, realOutputSize); - let size = Math.ceil(step * scale); - if (size >= maxSize) { - size = maxSize; - } else { - scale = size / step; - } - return { - scale, - size - }; - } - clipBbox(graphics, x0, y0, x1, y1) { - const bboxWidth = x1 - x0; - const bboxHeight = y1 - y0; - graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight); - graphics.current.updateRectMinMax((0,display_utils.getCurrentTransform)(graphics.ctx), [x0, y0, x1, y1]); - graphics.clip(); - graphics.endPath(); - } - setFillAndStrokeStyleToContext(graphics, paintType, color) { - const context = graphics.ctx, - current = graphics.current; - switch (paintType) { - case PaintType.COLORED: - const ctx = this.ctx; - context.fillStyle = ctx.fillStyle; - context.strokeStyle = ctx.strokeStyle; - current.fillColor = ctx.fillStyle; - current.strokeColor = ctx.strokeStyle; - break; - case PaintType.UNCOLORED: - const cssColor = util.Util.makeHexColor(color[0], color[1], color[2]); - context.fillStyle = cssColor; - context.strokeStyle = cssColor; - current.fillColor = cssColor; - current.strokeColor = cssColor; - break; - default: - throw new util.FormatError(`Unsupported paint type: ${paintType}`); - } - } - getPattern(ctx, owner, inverse, pathType) { - let matrix = inverse; - if (pathType !== PathType.SHADING) { - matrix = util.Util.transform(matrix, owner.baseTransform); - if (this.matrix) { - matrix = util.Util.transform(matrix, this.matrix); - } - } - const temporaryPatternCanvas = this.createPatternCanvas(owner); - let domMatrix = new DOMMatrix(matrix); - domMatrix = domMatrix.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY); - domMatrix = domMatrix.scale(1 / temporaryPatternCanvas.scaleX, 1 / temporaryPatternCanvas.scaleY); - const pattern = ctx.createPattern(temporaryPatternCanvas.canvas, "repeat"); - pattern.setTransform(domMatrix); - return pattern; - } -} - -;// CONCATENATED MODULE: ./src/shared/image_utils.js - -function convertToRGBA(params) { - switch (params.kind) { - case ImageKind.GRAYSCALE_1BPP: - return convertBlackAndWhiteToRGBA(params); - case ImageKind.RGB_24BPP: - return convertRGBToRGBA(params); - } - return null; -} -function convertBlackAndWhiteToRGBA({ - src, - srcPos = 0, - dest, - width, - height, - nonBlackColor = 0xffffffff, - inverseDecode = false -}) { - const black = util.FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff; - const [zeroMapping, oneMapping] = inverseDecode ? [nonBlackColor, black] : [black, nonBlackColor]; - const widthInSource = width >> 3; - const widthRemainder = width & 7; - const srcLength = src.length; - dest = new Uint32Array(dest.buffer); - let destPos = 0; - for (let i = 0; i < height; i++) { - for (const max = srcPos + widthInSource; srcPos < max; srcPos++) { - const elem = srcPos < srcLength ? src[srcPos] : 255; - dest[destPos++] = elem & 0b10000000 ? oneMapping : zeroMapping; - dest[destPos++] = elem & 0b1000000 ? oneMapping : zeroMapping; - dest[destPos++] = elem & 0b100000 ? oneMapping : zeroMapping; - dest[destPos++] = elem & 0b10000 ? oneMapping : zeroMapping; - dest[destPos++] = elem & 0b1000 ? oneMapping : zeroMapping; - dest[destPos++] = elem & 0b100 ? oneMapping : zeroMapping; - dest[destPos++] = elem & 0b10 ? oneMapping : zeroMapping; - dest[destPos++] = elem & 0b1 ? oneMapping : zeroMapping; - } - if (widthRemainder === 0) { - continue; - } - const elem = srcPos < srcLength ? src[srcPos++] : 255; - for (let j = 0; j < widthRemainder; j++) { - dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping; - } - } - return { - srcPos, - destPos - }; -} -function convertRGBToRGBA({ - src, - srcPos = 0, - dest, - destPos = 0, - width, - height -}) { - let i = 0; - const len32 = src.length >> 2; - const src32 = new Uint32Array(src.buffer, srcPos, len32); - if (FeatureTest.isLittleEndian) { - for (; i < len32 - 2; i += 3, destPos += 4) { - const s1 = src32[i]; - const s2 = src32[i + 1]; - const s3 = src32[i + 2]; - dest[destPos] = s1 | 0xff000000; - dest[destPos + 1] = s1 >>> 24 | s2 << 8 | 0xff000000; - dest[destPos + 2] = s2 >>> 16 | s3 << 16 | 0xff000000; - dest[destPos + 3] = s3 >>> 8 | 0xff000000; - } - for (let j = i * 4, jj = src.length; j < jj; j += 3) { - dest[destPos++] = src[j] | src[j + 1] << 8 | src[j + 2] << 16 | 0xff000000; - } - } else { - for (; i < len32 - 2; i += 3, destPos += 4) { - const s1 = src32[i]; - const s2 = src32[i + 1]; - const s3 = src32[i + 2]; - dest[destPos] = s1 | 0xff; - dest[destPos + 1] = s1 << 24 | s2 >>> 8 | 0xff; - dest[destPos + 2] = s2 << 16 | s3 >>> 16 | 0xff; - dest[destPos + 3] = s3 << 8 | 0xff; - } - for (let j = i * 4, jj = src.length; j < jj; j += 3) { - dest[destPos++] = src[j] << 24 | src[j + 1] << 16 | src[j + 2] << 8 | 0xff; - } - } - return { - srcPos, - destPos - }; -} -function grayToRGBA(src, dest) { - if (FeatureTest.isLittleEndian) { - for (let i = 0, ii = src.length; i < ii; i++) { - dest[i] = src[i] * 0x10101 | 0xff000000; - } - } else { - for (let i = 0, ii = src.length; i < ii; i++) { - dest[i] = src[i] * 0x1010100 | 0x000000ff; - } - } -} - -;// CONCATENATED MODULE: ./src/display/canvas.js - - - - -const MIN_FONT_SIZE = 16; -const MAX_FONT_SIZE = 100; -const MAX_GROUP_SIZE = 4096; -const EXECUTION_TIME = 15; -const EXECUTION_STEPS = 10; -const MAX_SIZE_TO_COMPILE = 1000; -const FULL_CHUNK_HEIGHT = 16; -function mirrorContextOperations(ctx, destCtx) { - if (ctx._removeMirroring) { - throw new Error("Context is already forwarding operations."); - } - ctx.__originalSave = ctx.save; - ctx.__originalRestore = ctx.restore; - ctx.__originalRotate = ctx.rotate; - ctx.__originalScale = ctx.scale; - ctx.__originalTranslate = ctx.translate; - ctx.__originalTransform = ctx.transform; - ctx.__originalSetTransform = ctx.setTransform; - ctx.__originalResetTransform = ctx.resetTransform; - ctx.__originalClip = ctx.clip; - ctx.__originalMoveTo = ctx.moveTo; - ctx.__originalLineTo = ctx.lineTo; - ctx.__originalBezierCurveTo = ctx.bezierCurveTo; - ctx.__originalRect = ctx.rect; - ctx.__originalClosePath = ctx.closePath; - ctx.__originalBeginPath = ctx.beginPath; - ctx._removeMirroring = () => { - ctx.save = ctx.__originalSave; - ctx.restore = ctx.__originalRestore; - ctx.rotate = ctx.__originalRotate; - ctx.scale = ctx.__originalScale; - ctx.translate = ctx.__originalTranslate; - ctx.transform = ctx.__originalTransform; - ctx.setTransform = ctx.__originalSetTransform; - ctx.resetTransform = ctx.__originalResetTransform; - ctx.clip = ctx.__originalClip; - ctx.moveTo = ctx.__originalMoveTo; - ctx.lineTo = ctx.__originalLineTo; - ctx.bezierCurveTo = ctx.__originalBezierCurveTo; - ctx.rect = ctx.__originalRect; - ctx.closePath = ctx.__originalClosePath; - ctx.beginPath = ctx.__originalBeginPath; - delete ctx._removeMirroring; - }; - ctx.save = function ctxSave() { - destCtx.save(); - this.__originalSave(); - }; - ctx.restore = function ctxRestore() { - destCtx.restore(); - this.__originalRestore(); - }; - ctx.translate = function ctxTranslate(x, y) { - destCtx.translate(x, y); - this.__originalTranslate(x, y); - }; - ctx.scale = function ctxScale(x, y) { - destCtx.scale(x, y); - this.__originalScale(x, y); - }; - ctx.transform = function ctxTransform(a, b, c, d, e, f) { - destCtx.transform(a, b, c, d, e, f); - this.__originalTransform(a, b, c, d, e, f); - }; - ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) { - destCtx.setTransform(a, b, c, d, e, f); - this.__originalSetTransform(a, b, c, d, e, f); - }; - ctx.resetTransform = function ctxResetTransform() { - destCtx.resetTransform(); - this.__originalResetTransform(); - }; - ctx.rotate = function ctxRotate(angle) { - destCtx.rotate(angle); - this.__originalRotate(angle); - }; - ctx.clip = function ctxRotate(rule) { - destCtx.clip(rule); - this.__originalClip(rule); - }; - ctx.moveTo = function (x, y) { - destCtx.moveTo(x, y); - this.__originalMoveTo(x, y); - }; - ctx.lineTo = function (x, y) { - destCtx.lineTo(x, y); - this.__originalLineTo(x, y); - }; - ctx.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) { - destCtx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); - this.__originalBezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); - }; - ctx.rect = function (x, y, width, height) { - destCtx.rect(x, y, width, height); - this.__originalRect(x, y, width, height); - }; - ctx.closePath = function () { - destCtx.closePath(); - this.__originalClosePath(); - }; - ctx.beginPath = function () { - destCtx.beginPath(); - this.__originalBeginPath(); - }; -} -class CachedCanvases { - constructor(canvasFactory) { - this.canvasFactory = canvasFactory; - this.cache = Object.create(null); - } - getCanvas(id, width, height) { - let canvasEntry; - if (this.cache[id] !== undefined) { - canvasEntry = this.cache[id]; - this.canvasFactory.reset(canvasEntry, width, height); - } else { - canvasEntry = this.canvasFactory.create(width, height); - this.cache[id] = canvasEntry; - } - return canvasEntry; - } - delete(id) { - delete this.cache[id]; - } - clear() { - for (const id in this.cache) { - const canvasEntry = this.cache[id]; - this.canvasFactory.destroy(canvasEntry); - delete this.cache[id]; - } - } -} -function drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH) { - const [a, b, c, d, tx, ty] = (0,display_utils.getCurrentTransform)(ctx); - if (b === 0 && c === 0) { - const tlX = destX * a + tx; - const rTlX = Math.round(tlX); - const tlY = destY * d + ty; - const rTlY = Math.round(tlY); - const brX = (destX + destW) * a + tx; - const rWidth = Math.abs(Math.round(brX) - rTlX) || 1; - const brY = (destY + destH) * d + ty; - const rHeight = Math.abs(Math.round(brY) - rTlY) || 1; - ctx.setTransform(Math.sign(a), 0, 0, Math.sign(d), rTlX, rTlY); - ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rWidth, rHeight); - ctx.setTransform(a, b, c, d, tx, ty); - return [rWidth, rHeight]; - } - if (a === 0 && d === 0) { - const tlX = destY * c + tx; - const rTlX = Math.round(tlX); - const tlY = destX * b + ty; - const rTlY = Math.round(tlY); - const brX = (destY + destH) * c + tx; - const rWidth = Math.abs(Math.round(brX) - rTlX) || 1; - const brY = (destX + destW) * b + ty; - const rHeight = Math.abs(Math.round(brY) - rTlY) || 1; - ctx.setTransform(0, Math.sign(b), Math.sign(c), 0, rTlX, rTlY); - ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rHeight, rWidth); - ctx.setTransform(a, b, c, d, tx, ty); - return [rHeight, rWidth]; - } - ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH); - const scaleX = Math.hypot(a, b); - const scaleY = Math.hypot(c, d); - return [scaleX * destW, scaleY * destH]; -} -function compileType3Glyph(imgData) { - const { - width, - height - } = imgData; - if (width > MAX_SIZE_TO_COMPILE || height > MAX_SIZE_TO_COMPILE) { - return null; - } - const POINT_TO_PROCESS_LIMIT = 1000; - const POINT_TYPES = new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]); - const width1 = width + 1; - let points = new Uint8Array(width1 * (height + 1)); - let i, j, j0; - const lineSize = width + 7 & ~7; - let data = new Uint8Array(lineSize * height), - pos = 0; - for (const elem of imgData.data) { - let mask = 128; - while (mask > 0) { - data[pos++] = elem & mask ? 0 : 255; - mask >>= 1; - } - } - let count = 0; - pos = 0; - if (data[pos] !== 0) { - points[0] = 1; - ++count; - } - for (j = 1; j < width; j++) { - if (data[pos] !== data[pos + 1]) { - points[j] = data[pos] ? 2 : 1; - ++count; - } - pos++; - } - if (data[pos] !== 0) { - points[j] = 2; - ++count; - } - for (i = 1; i < height; i++) { - pos = i * lineSize; - j0 = i * width1; - if (data[pos - lineSize] !== data[pos]) { - points[j0] = data[pos] ? 1 : 8; - ++count; - } - let sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0); - for (j = 1; j < width; j++) { - sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0); - if (POINT_TYPES[sum]) { - points[j0 + j] = POINT_TYPES[sum]; - ++count; - } - pos++; - } - if (data[pos - lineSize] !== data[pos]) { - points[j0 + j] = data[pos] ? 2 : 4; - ++count; - } - if (count > POINT_TO_PROCESS_LIMIT) { - return null; - } - } - pos = lineSize * (height - 1); - j0 = i * width1; - if (data[pos] !== 0) { - points[j0] = 8; - ++count; - } - for (j = 1; j < width; j++) { - if (data[pos] !== data[pos + 1]) { - points[j0 + j] = data[pos] ? 4 : 8; - ++count; - } - pos++; - } - if (data[pos] !== 0) { - points[j0 + j] = 4; - ++count; - } - if (count > POINT_TO_PROCESS_LIMIT) { - return null; - } - const steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]); - const path = new Path2D(); - for (i = 0; count && i <= height; i++) { - let p = i * width1; - const end = p + width; - while (p < end && !points[p]) { - p++; - } - if (p === end) { - continue; - } - path.moveTo(p % width1, i); - const p0 = p; - let type = points[p]; - do { - const step = steps[type]; - do { - p += step; - } while (!points[p]); - const pp = points[p]; - if (pp !== 5 && pp !== 10) { - type = pp; - points[p] = 0; - } else { - type = pp & 0x33 * type >> 4; - points[p] &= type >> 2 | type << 2; - } - path.lineTo(p % width1, p / width1 | 0); - if (!points[p]) { - --count; - } - } while (p0 !== p); - --i; - } - data = null; - points = null; - const drawOutline = function (c) { - c.save(); - c.scale(1 / width, -1 / height); - c.translate(0, -height); - c.fill(path); - c.beginPath(); - c.restore(); - }; - return drawOutline; -} -class CanvasExtraState { - constructor(width, height) { - this.alphaIsShape = false; - this.fontSize = 0; - this.fontSizeScale = 1; - this.textMatrix = util.IDENTITY_MATRIX; - this.textMatrixScale = 1; - this.fontMatrix = util.FONT_IDENTITY_MATRIX; - this.leading = 0; - this.x = 0; - this.y = 0; - this.lineX = 0; - this.lineY = 0; - this.charSpacing = 0; - this.wordSpacing = 0; - this.textHScale = 1; - this.textRenderingMode = util.TextRenderingMode.FILL; - this.textRise = 0; - this.fillColor = "#000000"; - this.strokeColor = "#000000"; - this.patternFill = false; - this.fillAlpha = 1; - this.strokeAlpha = 1; - this.lineWidth = 1; - this.activeSMask = null; - this.transferMaps = "none"; - this.startNewPathAndClipBox([0, 0, width, height]); - } - clone() { - const clone = Object.create(this); - clone.clipBox = this.clipBox.slice(); - return clone; - } - setCurrentPoint(x, y) { - this.x = x; - this.y = y; - } - updatePathMinMax(transform, x, y) { - [x, y] = util.Util.applyTransform([x, y], transform); - this.minX = Math.min(this.minX, x); - this.minY = Math.min(this.minY, y); - this.maxX = Math.max(this.maxX, x); - this.maxY = Math.max(this.maxY, y); - } - updateRectMinMax(transform, rect) { - const p1 = util.Util.applyTransform(rect, transform); - const p2 = util.Util.applyTransform(rect.slice(2), transform); - const p3 = util.Util.applyTransform([rect[0], rect[3]], transform); - const p4 = util.Util.applyTransform([rect[2], rect[1]], transform); - this.minX = Math.min(this.minX, p1[0], p2[0], p3[0], p4[0]); - this.minY = Math.min(this.minY, p1[1], p2[1], p3[1], p4[1]); - this.maxX = Math.max(this.maxX, p1[0], p2[0], p3[0], p4[0]); - this.maxY = Math.max(this.maxY, p1[1], p2[1], p3[1], p4[1]); - } - updateScalingPathMinMax(transform, minMax) { - util.Util.scaleMinMax(transform, minMax); - this.minX = Math.min(this.minX, minMax[0]); - this.minY = Math.min(this.minY, minMax[1]); - this.maxX = Math.max(this.maxX, minMax[2]); - this.maxY = Math.max(this.maxY, minMax[3]); - } - updateCurvePathMinMax(transform, x0, y0, x1, y1, x2, y2, x3, y3, minMax) { - const box = util.Util.bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax); - if (minMax) { - return; - } - this.updateRectMinMax(transform, box); - } - getPathBoundingBox(pathType = PathType.FILL, transform = null) { - const box = [this.minX, this.minY, this.maxX, this.maxY]; - if (pathType === PathType.STROKE) { - if (!transform) { - (0,util.unreachable)("Stroke bounding box must include transform."); - } - const scale = util.Util.singularValueDecompose2dScale(transform); - const xStrokePad = scale[0] * this.lineWidth / 2; - const yStrokePad = scale[1] * this.lineWidth / 2; - box[0] -= xStrokePad; - box[1] -= yStrokePad; - box[2] += xStrokePad; - box[3] += yStrokePad; - } - return box; - } - updateClipFromPath() { - const intersect = util.Util.intersect(this.clipBox, this.getPathBoundingBox()); - this.startNewPathAndClipBox(intersect || [0, 0, 0, 0]); - } - isEmptyClip() { - return this.minX === Infinity; - } - startNewPathAndClipBox(box) { - this.clipBox = box; - this.minX = Infinity; - this.minY = Infinity; - this.maxX = 0; - this.maxY = 0; - } - getClippedPathBoundingBox(pathType = PathType.FILL, transform = null) { - return util.Util.intersect(this.clipBox, this.getPathBoundingBox(pathType, transform)); - } -} -function putBinaryImageData(ctx, imgData) { - if (typeof ImageData !== "undefined" && imgData instanceof ImageData) { - ctx.putImageData(imgData, 0, 0); - return; - } - const height = imgData.height, - width = imgData.width; - const partialChunkHeight = height % FULL_CHUNK_HEIGHT; - const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; - const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; - const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); - let srcPos = 0, - destPos; - const src = imgData.data; - const dest = chunkImgData.data; - let i, j, thisChunkHeight, elemsInThisChunk; - if (imgData.kind === util.ImageKind.GRAYSCALE_1BPP) { - const srcLength = src.byteLength; - const dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2); - const dest32DataLength = dest32.length; - const fullSrcDiff = width + 7 >> 3; - const white = 0xffffffff; - const black = util.FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff; - for (i = 0; i < totalChunks; i++) { - thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight; - destPos = 0; - for (j = 0; j < thisChunkHeight; j++) { - const srcDiff = srcLength - srcPos; - let k = 0; - const kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7; - const kEndUnrolled = kEnd & ~7; - let mask = 0; - let srcByte = 0; - for (; k < kEndUnrolled; k += 8) { - srcByte = src[srcPos++]; - dest32[destPos++] = srcByte & 128 ? white : black; - dest32[destPos++] = srcByte & 64 ? white : black; - dest32[destPos++] = srcByte & 32 ? white : black; - dest32[destPos++] = srcByte & 16 ? white : black; - dest32[destPos++] = srcByte & 8 ? white : black; - dest32[destPos++] = srcByte & 4 ? white : black; - dest32[destPos++] = srcByte & 2 ? white : black; - dest32[destPos++] = srcByte & 1 ? white : black; - } - for (; k < kEnd; k++) { - if (mask === 0) { - srcByte = src[srcPos++]; - mask = 128; - } - dest32[destPos++] = srcByte & mask ? white : black; - mask >>= 1; - } - } - while (destPos < dest32DataLength) { - dest32[destPos++] = 0; - } - ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); - } - } else if (imgData.kind === util.ImageKind.RGBA_32BPP) { - j = 0; - elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4; - for (i = 0; i < fullChunks; i++) { - dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); - srcPos += elemsInThisChunk; - ctx.putImageData(chunkImgData, 0, j); - j += FULL_CHUNK_HEIGHT; - } - if (i < totalChunks) { - elemsInThisChunk = width * partialChunkHeight * 4; - dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); - ctx.putImageData(chunkImgData, 0, j); - } - } else if (imgData.kind === util.ImageKind.RGB_24BPP) { - thisChunkHeight = FULL_CHUNK_HEIGHT; - elemsInThisChunk = width * thisChunkHeight; - for (i = 0; i < totalChunks; i++) { - if (i >= fullChunks) { - thisChunkHeight = partialChunkHeight; - elemsInThisChunk = width * thisChunkHeight; - } - destPos = 0; - for (j = elemsInThisChunk; j--;) { - dest[destPos++] = src[srcPos++]; - dest[destPos++] = src[srcPos++]; - dest[destPos++] = src[srcPos++]; - dest[destPos++] = 255; - } - ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); - } - } else { - throw new Error(`bad image kind: ${imgData.kind}`); - } -} -function putBinaryImageMask(ctx, imgData) { - if (imgData.bitmap) { - ctx.drawImage(imgData.bitmap, 0, 0); - return; - } - const height = imgData.height, - width = imgData.width; - const partialChunkHeight = height % FULL_CHUNK_HEIGHT; - const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; - const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; - const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); - let srcPos = 0; - const src = imgData.data; - const dest = chunkImgData.data; - for (let i = 0; i < totalChunks; i++) { - const thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight; - ({ - srcPos - } = convertBlackAndWhiteToRGBA({ - src, - srcPos, - dest, - width, - height: thisChunkHeight, - nonBlackColor: 0 - })); - ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); - } -} -function copyCtxState(sourceCtx, destCtx) { - const properties = ["strokeStyle", "fillStyle", "fillRule", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "globalCompositeOperation", "font", "filter"]; - for (const property of properties) { - if (sourceCtx[property] !== undefined) { - destCtx[property] = sourceCtx[property]; - } - } - if (sourceCtx.setLineDash !== undefined) { - destCtx.setLineDash(sourceCtx.getLineDash()); - destCtx.lineDashOffset = sourceCtx.lineDashOffset; - } -} -function resetCtxToDefault(ctx) { - ctx.strokeStyle = ctx.fillStyle = "#000000"; - ctx.fillRule = "nonzero"; - ctx.globalAlpha = 1; - ctx.lineWidth = 1; - ctx.lineCap = "butt"; - ctx.lineJoin = "miter"; - ctx.miterLimit = 10; - ctx.globalCompositeOperation = "source-over"; - ctx.font = "10px sans-serif"; - if (ctx.setLineDash !== undefined) { - ctx.setLineDash([]); - ctx.lineDashOffset = 0; - } - if (!util.isNodeJS) { - const { - filter - } = ctx; - if (filter !== "none" && filter !== "") { - ctx.filter = "none"; - } - } -} -function composeSMaskBackdrop(bytes, r0, g0, b0) { - const length = bytes.length; - for (let i = 3; i < length; i += 4) { - const alpha = bytes[i]; - if (alpha === 0) { - bytes[i - 3] = r0; - bytes[i - 2] = g0; - bytes[i - 1] = b0; - } else if (alpha < 255) { - const alpha_ = 255 - alpha; - bytes[i - 3] = bytes[i - 3] * alpha + r0 * alpha_ >> 8; - bytes[i - 2] = bytes[i - 2] * alpha + g0 * alpha_ >> 8; - bytes[i - 1] = bytes[i - 1] * alpha + b0 * alpha_ >> 8; - } - } -} -function composeSMaskAlpha(maskData, layerData, transferMap) { - const length = maskData.length; - const scale = 1 / 255; - for (let i = 3; i < length; i += 4) { - const alpha = transferMap ? transferMap[maskData[i]] : maskData[i]; - layerData[i] = layerData[i] * alpha * scale | 0; - } -} -function composeSMaskLuminosity(maskData, layerData, transferMap) { - const length = maskData.length; - for (let i = 3; i < length; i += 4) { - const y = maskData[i - 3] * 77 + maskData[i - 2] * 152 + maskData[i - 1] * 28; - layerData[i] = transferMap ? layerData[i] * transferMap[y >> 8] >> 8 : layerData[i] * y >> 16; - } -} -function genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap, layerOffsetX, layerOffsetY, maskOffsetX, maskOffsetY) { - const hasBackdrop = !!backdrop; - const r0 = hasBackdrop ? backdrop[0] : 0; - const g0 = hasBackdrop ? backdrop[1] : 0; - const b0 = hasBackdrop ? backdrop[2] : 0; - const composeFn = subtype === "Luminosity" ? composeSMaskLuminosity : composeSMaskAlpha; - const PIXELS_TO_PROCESS = 1048576; - const chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width)); - for (let row = 0; row < height; row += chunkSize) { - const chunkHeight = Math.min(chunkSize, height - row); - const maskData = maskCtx.getImageData(layerOffsetX - maskOffsetX, row + (layerOffsetY - maskOffsetY), width, chunkHeight); - const layerData = layerCtx.getImageData(layerOffsetX, row + layerOffsetY, width, chunkHeight); - if (hasBackdrop) { - composeSMaskBackdrop(maskData.data, r0, g0, b0); - } - composeFn(maskData.data, layerData.data, transferMap); - layerCtx.putImageData(layerData, layerOffsetX, row + layerOffsetY); - } -} -function composeSMask(ctx, smask, layerCtx, layerBox) { - const layerOffsetX = layerBox[0]; - const layerOffsetY = layerBox[1]; - const layerWidth = layerBox[2] - layerOffsetX; - const layerHeight = layerBox[3] - layerOffsetY; - if (layerWidth === 0 || layerHeight === 0) { - return; - } - genericComposeSMask(smask.context, layerCtx, layerWidth, layerHeight, smask.subtype, smask.backdrop, smask.transferMap, layerOffsetX, layerOffsetY, smask.offsetX, smask.offsetY); - ctx.save(); - ctx.globalAlpha = 1; - ctx.globalCompositeOperation = "source-over"; - ctx.setTransform(1, 0, 0, 1, 0, 0); - ctx.drawImage(layerCtx.canvas, 0, 0); - ctx.restore(); -} -function getImageSmoothingEnabled(transform, interpolate) { - if (interpolate) { - return true; - } - const scale = util.Util.singularValueDecompose2dScale(transform); - scale[0] = Math.fround(scale[0]); - scale[1] = Math.fround(scale[1]); - const actualScale = Math.fround((globalThis.devicePixelRatio || 1) * display_utils.PixelsPerInch.PDF_TO_CSS_UNITS); - return scale[0] <= actualScale && scale[1] <= actualScale; -} -const LINE_CAP_STYLES = ["butt", "round", "square"]; -const LINE_JOIN_STYLES = ["miter", "round", "bevel"]; -const NORMAL_CLIP = {}; -const EO_CLIP = {}; -class CanvasGraphics { - constructor(canvasCtx, commonObjs, objs, canvasFactory, filterFactory, { - optionalContentConfig, - markedContentStack = null - }, annotationCanvasMap, pageColors) { - this.ctx = canvasCtx; - this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height); - this.stateStack = []; - this.pendingClip = null; - this.pendingEOFill = false; - this.res = null; - this.xobjs = null; - this.commonObjs = commonObjs; - this.objs = objs; - this.canvasFactory = canvasFactory; - this.filterFactory = filterFactory; - this.groupStack = []; - this.processingType3 = null; - this.baseTransform = null; - this.baseTransformStack = []; - this.groupLevel = 0; - this.smaskStack = []; - this.smaskCounter = 0; - this.tempSMask = null; - this.suspendedCtx = null; - this.contentVisible = true; - this.markedContentStack = markedContentStack || []; - this.optionalContentConfig = optionalContentConfig; - this.cachedCanvases = new CachedCanvases(this.canvasFactory); - this.cachedPatterns = new Map(); - this.annotationCanvasMap = annotationCanvasMap; - this.viewportScale = 1; - this.outputScaleX = 1; - this.outputScaleY = 1; - this.pageColors = pageColors; - this._cachedScaleForStroking = [-1, 0]; - this._cachedGetSinglePixelWidth = null; - this._cachedBitmapsMap = new Map(); - } - getObject(data, fallback = null) { - if (typeof data === "string") { - return data.startsWith("g_") ? this.commonObjs.get(data) : this.objs.get(data); - } - return fallback; - } - beginDrawing({ - transform, - viewport, - transparency = false, - background = null - }) { - const width = this.ctx.canvas.width; - const height = this.ctx.canvas.height; - const savedFillStyle = this.ctx.fillStyle; - this.ctx.fillStyle = background || "#ffffff"; - this.ctx.fillRect(0, 0, width, height); - this.ctx.fillStyle = savedFillStyle; - if (transparency) { - const transparentCanvas = this.cachedCanvases.getCanvas("transparent", width, height); - this.compositeCtx = this.ctx; - this.transparentCanvas = transparentCanvas.canvas; - this.ctx = transparentCanvas.context; - this.ctx.save(); - this.ctx.transform(...(0,display_utils.getCurrentTransform)(this.compositeCtx)); - } - this.ctx.save(); - resetCtxToDefault(this.ctx); - if (transform) { - this.ctx.transform(...transform); - this.outputScaleX = transform[0]; - this.outputScaleY = transform[0]; - } - this.ctx.transform(...viewport.transform); - this.viewportScale = viewport.scale; - this.baseTransform = (0,display_utils.getCurrentTransform)(this.ctx); - } - executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper) { - const argsArray = operatorList.argsArray; - const fnArray = operatorList.fnArray; - let i = executionStartIdx || 0; - const argsArrayLen = argsArray.length; - if (argsArrayLen === i) { - return i; - } - const chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === "function"; - const endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0; - let steps = 0; - const commonObjs = this.commonObjs; - const objs = this.objs; - let fnId; - while (true) { - if (stepper !== undefined && i === stepper.nextBreakPoint) { - stepper.breakIt(i, continueCallback); - return i; - } - fnId = fnArray[i]; - if (fnId !== util.OPS.dependency) { - this[fnId].apply(this, argsArray[i]); - } else { - for (const depObjId of argsArray[i]) { - const objsPool = depObjId.startsWith("g_") ? commonObjs : objs; - if (!objsPool.has(depObjId)) { - objsPool.get(depObjId, continueCallback); - return i; - } - } - } - i++; - if (i === argsArrayLen) { - return i; - } - if (chunkOperations && ++steps > EXECUTION_STEPS) { - if (Date.now() > endTime) { - continueCallback(); - return i; - } - steps = 0; - } - } - } - #restoreInitialState() { - while (this.stateStack.length || this.inSMaskMode) { - this.restore(); - } - this.ctx.restore(); - if (this.transparentCanvas) { - this.ctx = this.compositeCtx; - this.ctx.save(); - this.ctx.setTransform(1, 0, 0, 1, 0, 0); - this.ctx.drawImage(this.transparentCanvas, 0, 0); - this.ctx.restore(); - this.transparentCanvas = null; - } - } - endDrawing() { - this.#restoreInitialState(); - this.cachedCanvases.clear(); - this.cachedPatterns.clear(); - for (const cache of this._cachedBitmapsMap.values()) { - for (const canvas of cache.values()) { - if (typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement) { - canvas.width = canvas.height = 0; - } - } - cache.clear(); - } - this._cachedBitmapsMap.clear(); - this.#drawFilter(); - } - #drawFilter() { - if (this.pageColors) { - const hcmFilterId = this.filterFactory.addHCMFilter(this.pageColors.foreground, this.pageColors.background); - if (hcmFilterId !== "none") { - const savedFilter = this.ctx.filter; - this.ctx.filter = hcmFilterId; - this.ctx.drawImage(this.ctx.canvas, 0, 0); - this.ctx.filter = savedFilter; - } - } - } - _scaleImage(img, inverseTransform) { - const width = img.width; - const height = img.height; - let widthScale = Math.max(Math.hypot(inverseTransform[0], inverseTransform[1]), 1); - let heightScale = Math.max(Math.hypot(inverseTransform[2], inverseTransform[3]), 1); - let paintWidth = width, - paintHeight = height; - let tmpCanvasId = "prescale1"; - let tmpCanvas, tmpCtx; - while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) { - let newWidth = paintWidth, - newHeight = paintHeight; - if (widthScale > 2 && paintWidth > 1) { - newWidth = paintWidth >= 16384 ? Math.floor(paintWidth / 2) - 1 || 1 : Math.ceil(paintWidth / 2); - widthScale /= paintWidth / newWidth; - } - if (heightScale > 2 && paintHeight > 1) { - newHeight = paintHeight >= 16384 ? Math.floor(paintHeight / 2) - 1 || 1 : Math.ceil(paintHeight) / 2; - heightScale /= paintHeight / newHeight; - } - tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight); - tmpCtx = tmpCanvas.context; - tmpCtx.clearRect(0, 0, newWidth, newHeight); - tmpCtx.drawImage(img, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight); - img = tmpCanvas.canvas; - paintWidth = newWidth; - paintHeight = newHeight; - tmpCanvasId = tmpCanvasId === "prescale1" ? "prescale2" : "prescale1"; - } - return { - img, - paintWidth, - paintHeight - }; - } - _createMaskCanvas(img) { - const ctx = this.ctx; - const { - width, - height - } = img; - const fillColor = this.current.fillColor; - const isPatternFill = this.current.patternFill; - const currentTransform = (0,display_utils.getCurrentTransform)(ctx); - let cache, cacheKey, scaled, maskCanvas; - if ((img.bitmap || img.data) && img.count > 1) { - const mainKey = img.bitmap || img.data.buffer; - cacheKey = JSON.stringify(isPatternFill ? currentTransform : [currentTransform.slice(0, 4), fillColor]); - cache = this._cachedBitmapsMap.get(mainKey); - if (!cache) { - cache = new Map(); - this._cachedBitmapsMap.set(mainKey, cache); - } - const cachedImage = cache.get(cacheKey); - if (cachedImage && !isPatternFill) { - const offsetX = Math.round(Math.min(currentTransform[0], currentTransform[2]) + currentTransform[4]); - const offsetY = Math.round(Math.min(currentTransform[1], currentTransform[3]) + currentTransform[5]); - return { - canvas: cachedImage, - offsetX, - offsetY - }; - } - scaled = cachedImage; - } - if (!scaled) { - maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height); - putBinaryImageMask(maskCanvas.context, img); - } - let maskToCanvas = util.Util.transform(currentTransform, [1 / width, 0, 0, -1 / height, 0, 0]); - maskToCanvas = util.Util.transform(maskToCanvas, [1, 0, 0, 1, 0, -height]); - const [minX, minY, maxX, maxY] = util.Util.getAxialAlignedBoundingBox([0, 0, width, height], maskToCanvas); - const drawnWidth = Math.round(maxX - minX) || 1; - const drawnHeight = Math.round(maxY - minY) || 1; - const fillCanvas = this.cachedCanvases.getCanvas("fillCanvas", drawnWidth, drawnHeight); - const fillCtx = fillCanvas.context; - const offsetX = minX; - const offsetY = minY; - fillCtx.translate(-offsetX, -offsetY); - fillCtx.transform(...maskToCanvas); - if (!scaled) { - scaled = this._scaleImage(maskCanvas.canvas, (0,display_utils.getCurrentTransformInverse)(fillCtx)); - scaled = scaled.img; - if (cache && isPatternFill) { - cache.set(cacheKey, scaled); - } - } - fillCtx.imageSmoothingEnabled = getImageSmoothingEnabled((0,display_utils.getCurrentTransform)(fillCtx), img.interpolate); - drawImageAtIntegerCoords(fillCtx, scaled, 0, 0, scaled.width, scaled.height, 0, 0, width, height); - fillCtx.globalCompositeOperation = "source-in"; - const inverse = util.Util.transform((0,display_utils.getCurrentTransformInverse)(fillCtx), [1, 0, 0, 1, -offsetX, -offsetY]); - fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(ctx, this, inverse, PathType.FILL) : fillColor; - fillCtx.fillRect(0, 0, width, height); - if (cache && !isPatternFill) { - this.cachedCanvases.delete("fillCanvas"); - cache.set(cacheKey, fillCanvas.canvas); - } - return { - canvas: fillCanvas.canvas, - offsetX: Math.round(offsetX), - offsetY: Math.round(offsetY) - }; - } - setLineWidth(width) { - if (width !== this.current.lineWidth) { - this._cachedScaleForStroking[0] = -1; - } - this.current.lineWidth = width; - this.ctx.lineWidth = width; - } - setLineCap(style) { - this.ctx.lineCap = LINE_CAP_STYLES[style]; - } - setLineJoin(style) { - this.ctx.lineJoin = LINE_JOIN_STYLES[style]; - } - setMiterLimit(limit) { - this.ctx.miterLimit = limit; - } - setDash(dashArray, dashPhase) { - const ctx = this.ctx; - if (ctx.setLineDash !== undefined) { - ctx.setLineDash(dashArray); - ctx.lineDashOffset = dashPhase; - } - } - setRenderingIntent(intent) {} - setFlatness(flatness) {} - setGState(states) { - for (const [key, value] of states) { - switch (key) { - case "LW": - this.setLineWidth(value); - break; - case "LC": - this.setLineCap(value); - break; - case "LJ": - this.setLineJoin(value); - break; - case "ML": - this.setMiterLimit(value); - break; - case "D": - this.setDash(value[0], value[1]); - break; - case "RI": - this.setRenderingIntent(value); - break; - case "FL": - this.setFlatness(value); - break; - case "Font": - this.setFont(value[0], value[1]); - break; - case "CA": - this.current.strokeAlpha = value; - break; - case "ca": - this.current.fillAlpha = value; - this.ctx.globalAlpha = value; - break; - case "BM": - this.ctx.globalCompositeOperation = value; - break; - case "SMask": - this.current.activeSMask = value ? this.tempSMask : null; - this.tempSMask = null; - this.checkSMaskState(); - break; - case "TR": - this.ctx.filter = this.current.transferMaps = this.filterFactory.addFilter(value); - break; - } - } - } - get inSMaskMode() { - return !!this.suspendedCtx; - } - checkSMaskState() { - const inSMaskMode = this.inSMaskMode; - if (this.current.activeSMask && !inSMaskMode) { - this.beginSMaskMode(); - } else if (!this.current.activeSMask && inSMaskMode) { - this.endSMaskMode(); - } - } - beginSMaskMode() { - if (this.inSMaskMode) { - throw new Error("beginSMaskMode called while already in smask mode"); - } - const drawnWidth = this.ctx.canvas.width; - const drawnHeight = this.ctx.canvas.height; - const cacheId = "smaskGroupAt" + this.groupLevel; - const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight); - this.suspendedCtx = this.ctx; - this.ctx = scratchCanvas.context; - const ctx = this.ctx; - ctx.setTransform(...(0,display_utils.getCurrentTransform)(this.suspendedCtx)); - copyCtxState(this.suspendedCtx, ctx); - mirrorContextOperations(ctx, this.suspendedCtx); - this.setGState([["BM", "source-over"], ["ca", 1], ["CA", 1]]); - } - endSMaskMode() { - if (!this.inSMaskMode) { - throw new Error("endSMaskMode called while not in smask mode"); - } - this.ctx._removeMirroring(); - copyCtxState(this.ctx, this.suspendedCtx); - this.ctx = this.suspendedCtx; - this.suspendedCtx = null; - } - compose(dirtyBox) { - if (!this.current.activeSMask) { - return; - } - if (!dirtyBox) { - dirtyBox = [0, 0, this.ctx.canvas.width, this.ctx.canvas.height]; - } else { - dirtyBox[0] = Math.floor(dirtyBox[0]); - dirtyBox[1] = Math.floor(dirtyBox[1]); - dirtyBox[2] = Math.ceil(dirtyBox[2]); - dirtyBox[3] = Math.ceil(dirtyBox[3]); - } - const smask = this.current.activeSMask; - const suspendedCtx = this.suspendedCtx; - composeSMask(suspendedCtx, smask, this.ctx, dirtyBox); - this.ctx.save(); - this.ctx.setTransform(1, 0, 0, 1, 0, 0); - this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); - this.ctx.restore(); - } - save() { - if (this.inSMaskMode) { - copyCtxState(this.ctx, this.suspendedCtx); - this.suspendedCtx.save(); - } else { - this.ctx.save(); - } - const old = this.current; - this.stateStack.push(old); - this.current = old.clone(); - } - restore() { - if (this.stateStack.length === 0 && this.inSMaskMode) { - this.endSMaskMode(); - } - if (this.stateStack.length !== 0) { - this.current = this.stateStack.pop(); - if (this.inSMaskMode) { - this.suspendedCtx.restore(); - copyCtxState(this.suspendedCtx, this.ctx); - } else { - this.ctx.restore(); - } - this.checkSMaskState(); - this.pendingClip = null; - this._cachedScaleForStroking[0] = -1; - this._cachedGetSinglePixelWidth = null; - } - } - transform(a, b, c, d, e, f) { - this.ctx.transform(a, b, c, d, e, f); - this._cachedScaleForStroking[0] = -1; - this._cachedGetSinglePixelWidth = null; - } - constructPath(ops, args, minMax) { - const ctx = this.ctx; - const current = this.current; - let x = current.x, - y = current.y; - let startX, startY; - const currentTransform = (0,display_utils.getCurrentTransform)(ctx); - const isScalingMatrix = currentTransform[0] === 0 && currentTransform[3] === 0 || currentTransform[1] === 0 && currentTransform[2] === 0; - const minMaxForBezier = isScalingMatrix ? minMax.slice(0) : null; - for (let i = 0, j = 0, ii = ops.length; i < ii; i++) { - switch (ops[i] | 0) { - case util.OPS.rectangle: - x = args[j++]; - y = args[j++]; - const width = args[j++]; - const height = args[j++]; - const xw = x + width; - const yh = y + height; - ctx.moveTo(x, y); - if (width === 0 || height === 0) { - ctx.lineTo(xw, yh); - } else { - ctx.lineTo(xw, y); - ctx.lineTo(xw, yh); - ctx.lineTo(x, yh); - } - if (!isScalingMatrix) { - current.updateRectMinMax(currentTransform, [x, y, xw, yh]); - } - ctx.closePath(); - break; - case util.OPS.moveTo: - x = args[j++]; - y = args[j++]; - ctx.moveTo(x, y); - if (!isScalingMatrix) { - current.updatePathMinMax(currentTransform, x, y); - } - break; - case util.OPS.lineTo: - x = args[j++]; - y = args[j++]; - ctx.lineTo(x, y); - if (!isScalingMatrix) { - current.updatePathMinMax(currentTransform, x, y); - } - break; - case util.OPS.curveTo: - startX = x; - startY = y; - x = args[j + 4]; - y = args[j + 5]; - ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], x, y); - current.updateCurvePathMinMax(currentTransform, startX, startY, args[j], args[j + 1], args[j + 2], args[j + 3], x, y, minMaxForBezier); - j += 6; - break; - case util.OPS.curveTo2: - startX = x; - startY = y; - ctx.bezierCurveTo(x, y, args[j], args[j + 1], args[j + 2], args[j + 3]); - current.updateCurvePathMinMax(currentTransform, startX, startY, x, y, args[j], args[j + 1], args[j + 2], args[j + 3], minMaxForBezier); - x = args[j + 2]; - y = args[j + 3]; - j += 4; - break; - case util.OPS.curveTo3: - startX = x; - startY = y; - x = args[j + 2]; - y = args[j + 3]; - ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y); - current.updateCurvePathMinMax(currentTransform, startX, startY, args[j], args[j + 1], x, y, x, y, minMaxForBezier); - j += 4; - break; - case util.OPS.closePath: - ctx.closePath(); - break; - } - } - if (isScalingMatrix) { - current.updateScalingPathMinMax(currentTransform, minMaxForBezier); - } - current.setCurrentPoint(x, y); - } - closePath() { - this.ctx.closePath(); - } - stroke(consumePath = true) { - const ctx = this.ctx; - const strokeColor = this.current.strokeColor; - ctx.globalAlpha = this.current.strokeAlpha; - if (this.contentVisible) { - if (typeof strokeColor === "object" && strokeColor?.getPattern) { - ctx.save(); - ctx.strokeStyle = strokeColor.getPattern(ctx, this, (0,display_utils.getCurrentTransformInverse)(ctx), PathType.STROKE); - this.rescaleAndStroke(false); - ctx.restore(); - } else { - this.rescaleAndStroke(true); - } - } - if (consumePath) { - this.consumePath(this.current.getClippedPathBoundingBox()); - } - ctx.globalAlpha = this.current.fillAlpha; - } - closeStroke() { - this.closePath(); - this.stroke(); - } - fill(consumePath = true) { - const ctx = this.ctx; - const fillColor = this.current.fillColor; - const isPatternFill = this.current.patternFill; - let needRestore = false; - if (isPatternFill) { - ctx.save(); - ctx.fillStyle = fillColor.getPattern(ctx, this, (0,display_utils.getCurrentTransformInverse)(ctx), PathType.FILL); - needRestore = true; - } - const intersect = this.current.getClippedPathBoundingBox(); - if (this.contentVisible && intersect !== null) { - if (this.pendingEOFill) { - ctx.fill("evenodd"); - this.pendingEOFill = false; - } else { - ctx.fill(); - } - } - if (needRestore) { - ctx.restore(); - } - if (consumePath) { - this.consumePath(intersect); - } - } - eoFill() { - this.pendingEOFill = true; - this.fill(); - } - fillStroke() { - this.fill(false); - this.stroke(false); - this.consumePath(); - } - eoFillStroke() { - this.pendingEOFill = true; - this.fillStroke(); - } - closeFillStroke() { - this.closePath(); - this.fillStroke(); - } - closeEOFillStroke() { - this.pendingEOFill = true; - this.closePath(); - this.fillStroke(); - } - endPath() { - this.consumePath(); - } - clip() { - this.pendingClip = NORMAL_CLIP; - } - eoClip() { - this.pendingClip = EO_CLIP; - } - beginText() { - this.current.textMatrix = util.IDENTITY_MATRIX; - this.current.textMatrixScale = 1; - this.current.x = this.current.lineX = 0; - this.current.y = this.current.lineY = 0; - } - endText() { - const paths = this.pendingTextPaths; - const ctx = this.ctx; - if (paths === undefined) { - ctx.beginPath(); - return; - } - ctx.save(); - ctx.beginPath(); - for (const path of paths) { - ctx.setTransform(...path.transform); - ctx.translate(path.x, path.y); - path.addToPath(ctx, path.fontSize); - } - ctx.restore(); - ctx.clip(); - ctx.beginPath(); - delete this.pendingTextPaths; - } - setCharSpacing(spacing) { - this.current.charSpacing = spacing; - } - setWordSpacing(spacing) { - this.current.wordSpacing = spacing; - } - setHScale(scale) { - this.current.textHScale = scale / 100; - } - setLeading(leading) { - this.current.leading = -leading; - } - setFont(fontRefName, size) { - const fontObj = this.commonObjs.get(fontRefName); - const current = this.current; - if (!fontObj) { - throw new Error(`Can't find font for ${fontRefName}`); - } - current.fontMatrix = fontObj.fontMatrix || util.FONT_IDENTITY_MATRIX; - if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) { - (0,util.warn)("Invalid font matrix for font " + fontRefName); - } - if (size < 0) { - size = -size; - current.fontDirection = -1; - } else { - current.fontDirection = 1; - } - this.current.font = fontObj; - this.current.fontSize = size; - if (fontObj.isType3Font) { - return; - } - const name = fontObj.loadedName || "sans-serif"; - const typeface = fontObj.systemFontInfo?.css || `"${name}", ${fontObj.fallbackName}`; - let bold = "normal"; - if (fontObj.black) { - bold = "900"; - } else if (fontObj.bold) { - bold = "bold"; - } - const italic = fontObj.italic ? "italic" : "normal"; - let browserFontSize = size; - if (size < MIN_FONT_SIZE) { - browserFontSize = MIN_FONT_SIZE; - } else if (size > MAX_FONT_SIZE) { - browserFontSize = MAX_FONT_SIZE; - } - this.current.fontSizeScale = size / browserFontSize; - this.ctx.font = `${italic} ${bold} ${browserFontSize}px ${typeface}`; - } - setTextRenderingMode(mode) { - this.current.textRenderingMode = mode; - } - setTextRise(rise) { - this.current.textRise = rise; - } - moveText(x, y) { - this.current.x = this.current.lineX += x; - this.current.y = this.current.lineY += y; - } - setLeadingMoveText(x, y) { - this.setLeading(-y); - this.moveText(x, y); - } - setTextMatrix(a, b, c, d, e, f) { - this.current.textMatrix = [a, b, c, d, e, f]; - this.current.textMatrixScale = Math.hypot(a, b); - this.current.x = this.current.lineX = 0; - this.current.y = this.current.lineY = 0; - } - nextLine() { - this.moveText(0, this.current.leading); - } - paintChar(character, x, y, patternTransform) { - const ctx = this.ctx; - const current = this.current; - const font = current.font; - const textRenderingMode = current.textRenderingMode; - const fontSize = current.fontSize / current.fontSizeScale; - const fillStrokeMode = textRenderingMode & util.TextRenderingMode.FILL_STROKE_MASK; - const isAddToPathSet = !!(textRenderingMode & util.TextRenderingMode.ADD_TO_PATH_FLAG); - const patternFill = current.patternFill && !font.missingFile; - let addToPath; - if (font.disableFontFace || isAddToPathSet || patternFill) { - addToPath = font.getPathGenerator(this.commonObjs, character); - } - if (font.disableFontFace || patternFill) { - ctx.save(); - ctx.translate(x, y); - ctx.beginPath(); - addToPath(ctx, fontSize); - if (patternTransform) { - ctx.setTransform(...patternTransform); - } - if (fillStrokeMode === util.TextRenderingMode.FILL || fillStrokeMode === util.TextRenderingMode.FILL_STROKE) { - ctx.fill(); - } - if (fillStrokeMode === util.TextRenderingMode.STROKE || fillStrokeMode === util.TextRenderingMode.FILL_STROKE) { - ctx.stroke(); - } - ctx.restore(); - } else { - if (fillStrokeMode === util.TextRenderingMode.FILL || fillStrokeMode === util.TextRenderingMode.FILL_STROKE) { - ctx.fillText(character, x, y); - } - if (fillStrokeMode === util.TextRenderingMode.STROKE || fillStrokeMode === util.TextRenderingMode.FILL_STROKE) { - ctx.strokeText(character, x, y); - } - } - if (isAddToPathSet) { - const paths = this.pendingTextPaths ||= []; - paths.push({ - transform: (0,display_utils.getCurrentTransform)(ctx), - x, - y, - fontSize, - addToPath - }); - } - } - get isFontSubpixelAAEnabled() { - const { - context: ctx - } = this.cachedCanvases.getCanvas("isFontSubpixelAAEnabled", 10, 10); - ctx.scale(1.5, 1); - ctx.fillText("I", 0, 10); - const data = ctx.getImageData(0, 0, 10, 10).data; - let enabled = false; - for (let i = 3; i < data.length; i += 4) { - if (data[i] > 0 && data[i] < 255) { - enabled = true; - break; - } - } - return (0,util.shadow)(this, "isFontSubpixelAAEnabled", enabled); - } - showText(glyphs) { - const current = this.current; - const font = current.font; - if (font.isType3Font) { - return this.showType3Text(glyphs); - } - const fontSize = current.fontSize; - if (fontSize === 0) { - return undefined; - } - const ctx = this.ctx; - const fontSizeScale = current.fontSizeScale; - const charSpacing = current.charSpacing; - const wordSpacing = current.wordSpacing; - const fontDirection = current.fontDirection; - const textHScale = current.textHScale * fontDirection; - const glyphsLength = glyphs.length; - const vertical = font.vertical; - const spacingDir = vertical ? 1 : -1; - const defaultVMetrics = font.defaultVMetrics; - const widthAdvanceScale = fontSize * current.fontMatrix[0]; - const simpleFillText = current.textRenderingMode === util.TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill; - ctx.save(); - ctx.transform(...current.textMatrix); - ctx.translate(current.x, current.y + current.textRise); - if (fontDirection > 0) { - ctx.scale(textHScale, -1); - } else { - ctx.scale(textHScale, 1); - } - let patternTransform; - if (current.patternFill) { - ctx.save(); - const pattern = current.fillColor.getPattern(ctx, this, (0,display_utils.getCurrentTransformInverse)(ctx), PathType.FILL); - patternTransform = (0,display_utils.getCurrentTransform)(ctx); - ctx.restore(); - ctx.fillStyle = pattern; - } - let lineWidth = current.lineWidth; - const scale = current.textMatrixScale; - if (scale === 0 || lineWidth === 0) { - const fillStrokeMode = current.textRenderingMode & util.TextRenderingMode.FILL_STROKE_MASK; - if (fillStrokeMode === util.TextRenderingMode.STROKE || fillStrokeMode === util.TextRenderingMode.FILL_STROKE) { - lineWidth = this.getSinglePixelWidth(); - } - } else { - lineWidth /= scale; - } - if (fontSizeScale !== 1.0) { - ctx.scale(fontSizeScale, fontSizeScale); - lineWidth /= fontSizeScale; - } - ctx.lineWidth = lineWidth; - if (font.isInvalidPDFjsFont) { - const chars = []; - let width = 0; - for (const glyph of glyphs) { - chars.push(glyph.unicode); - width += glyph.width; - } - ctx.fillText(chars.join(""), 0, 0); - current.x += width * widthAdvanceScale * textHScale; - ctx.restore(); - this.compose(); - return undefined; - } - let x = 0, - i; - for (i = 0; i < glyphsLength; ++i) { - const glyph = glyphs[i]; - if (typeof glyph === "number") { - x += spacingDir * glyph * fontSize / 1000; - continue; - } - let restoreNeeded = false; - const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; - const character = glyph.fontChar; - const accent = glyph.accent; - let scaledX, scaledY; - let width = glyph.width; - if (vertical) { - const vmetric = glyph.vmetric || defaultVMetrics; - const vx = -(glyph.vmetric ? vmetric[1] : width * 0.5) * widthAdvanceScale; - const vy = vmetric[2] * widthAdvanceScale; - width = vmetric ? -vmetric[0] : width; - scaledX = vx / fontSizeScale; - scaledY = (x + vy) / fontSizeScale; - } else { - scaledX = x / fontSizeScale; - scaledY = 0; - } - if (font.remeasure && width > 0) { - const measuredWidth = ctx.measureText(character).width * 1000 / fontSize * fontSizeScale; - if (width < measuredWidth && this.isFontSubpixelAAEnabled) { - const characterScaleX = width / measuredWidth; - restoreNeeded = true; - ctx.save(); - ctx.scale(characterScaleX, 1); - scaledX /= characterScaleX; - } else if (width !== measuredWidth) { - scaledX += (width - measuredWidth) / 2000 * fontSize / fontSizeScale; - } - } - if (this.contentVisible && (glyph.isInFont || font.missingFile)) { - if (simpleFillText && !accent) { - ctx.fillText(character, scaledX, scaledY); - } else { - this.paintChar(character, scaledX, scaledY, patternTransform); - if (accent) { - const scaledAccentX = scaledX + fontSize * accent.offset.x / fontSizeScale; - const scaledAccentY = scaledY - fontSize * accent.offset.y / fontSizeScale; - this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY, patternTransform); - } - } - } - const charWidth = vertical ? width * widthAdvanceScale - spacing * fontDirection : width * widthAdvanceScale + spacing * fontDirection; - x += charWidth; - if (restoreNeeded) { - ctx.restore(); - } - } - if (vertical) { - current.y -= x; - } else { - current.x += x * textHScale; - } - ctx.restore(); - this.compose(); - return undefined; - } - showType3Text(glyphs) { - const ctx = this.ctx; - const current = this.current; - const font = current.font; - const fontSize = current.fontSize; - const fontDirection = current.fontDirection; - const spacingDir = font.vertical ? 1 : -1; - const charSpacing = current.charSpacing; - const wordSpacing = current.wordSpacing; - const textHScale = current.textHScale * fontDirection; - const fontMatrix = current.fontMatrix || util.FONT_IDENTITY_MATRIX; - const glyphsLength = glyphs.length; - const isTextInvisible = current.textRenderingMode === util.TextRenderingMode.INVISIBLE; - let i, glyph, width, spacingLength; - if (isTextInvisible || fontSize === 0) { - return; - } - this._cachedScaleForStroking[0] = -1; - this._cachedGetSinglePixelWidth = null; - ctx.save(); - ctx.transform(...current.textMatrix); - ctx.translate(current.x, current.y); - ctx.scale(textHScale, fontDirection); - for (i = 0; i < glyphsLength; ++i) { - glyph = glyphs[i]; - if (typeof glyph === "number") { - spacingLength = spacingDir * glyph * fontSize / 1000; - this.ctx.translate(spacingLength, 0); - current.x += spacingLength * textHScale; - continue; - } - const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; - const operatorList = font.charProcOperatorList[glyph.operatorListId]; - if (!operatorList) { - (0,util.warn)(`Type3 character "${glyph.operatorListId}" is not available.`); - continue; - } - if (this.contentVisible) { - this.processingType3 = glyph; - this.save(); - ctx.scale(fontSize, fontSize); - ctx.transform(...fontMatrix); - this.executeOperatorList(operatorList); - this.restore(); - } - const transformed = util.Util.applyTransform([glyph.width, 0], fontMatrix); - width = transformed[0] * fontSize + spacing; - ctx.translate(width, 0); - current.x += width * textHScale; - } - ctx.restore(); - this.processingType3 = null; - } - setCharWidth(xWidth, yWidth) {} - setCharWidthAndBounds(xWidth, yWidth, llx, lly, urx, ury) { - this.ctx.rect(llx, lly, urx - llx, ury - lly); - this.ctx.clip(); - this.endPath(); - } - getColorN_Pattern(IR) { - let pattern; - if (IR[0] === "TilingPattern") { - const color = IR[1]; - const baseTransform = this.baseTransform || (0,display_utils.getCurrentTransform)(this.ctx); - const canvasGraphicsFactory = { - createCanvasGraphics: ctx => new CanvasGraphics(ctx, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, { - optionalContentConfig: this.optionalContentConfig, - markedContentStack: this.markedContentStack - }) - }; - pattern = new TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform); - } else { - pattern = this._getPattern(IR[1], IR[2]); - } - return pattern; - } - setStrokeColorN() { - this.current.strokeColor = this.getColorN_Pattern(arguments); - } - setFillColorN() { - this.current.fillColor = this.getColorN_Pattern(arguments); - this.current.patternFill = true; - } - setStrokeRGBColor(r, g, b) { - const color = util.Util.makeHexColor(r, g, b); - this.ctx.strokeStyle = color; - this.current.strokeColor = color; - } - setFillRGBColor(r, g, b) { - const color = util.Util.makeHexColor(r, g, b); - this.ctx.fillStyle = color; - this.current.fillColor = color; - this.current.patternFill = false; - } - _getPattern(objId, matrix = null) { - let pattern; - if (this.cachedPatterns.has(objId)) { - pattern = this.cachedPatterns.get(objId); - } else { - pattern = getShadingPattern(this.getObject(objId)); - this.cachedPatterns.set(objId, pattern); - } - if (matrix) { - pattern.matrix = matrix; - } - return pattern; - } - shadingFill(objId) { - if (!this.contentVisible) { - return; - } - const ctx = this.ctx; - this.save(); - const pattern = this._getPattern(objId); - ctx.fillStyle = pattern.getPattern(ctx, this, (0,display_utils.getCurrentTransformInverse)(ctx), PathType.SHADING); - const inv = (0,display_utils.getCurrentTransformInverse)(ctx); - if (inv) { - const { - width, - height - } = ctx.canvas; - const [x0, y0, x1, y1] = util.Util.getAxialAlignedBoundingBox([0, 0, width, height], inv); - this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0); - } else { - this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); - } - this.compose(this.current.getClippedPathBoundingBox()); - this.restore(); - } - beginInlineImage() { - (0,util.unreachable)("Should not call beginInlineImage"); - } - beginImageData() { - (0,util.unreachable)("Should not call beginImageData"); - } - paintFormXObjectBegin(matrix, bbox) { - if (!this.contentVisible) { - return; - } - this.save(); - this.baseTransformStack.push(this.baseTransform); - if (Array.isArray(matrix) && matrix.length === 6) { - this.transform(...matrix); - } - this.baseTransform = (0,display_utils.getCurrentTransform)(this.ctx); - if (bbox) { - const width = bbox[2] - bbox[0]; - const height = bbox[3] - bbox[1]; - this.ctx.rect(bbox[0], bbox[1], width, height); - this.current.updateRectMinMax((0,display_utils.getCurrentTransform)(this.ctx), bbox); - this.clip(); - this.endPath(); - } - } - paintFormXObjectEnd() { - if (!this.contentVisible) { - return; - } - this.restore(); - this.baseTransform = this.baseTransformStack.pop(); - } - beginGroup(group) { - if (!this.contentVisible) { - return; - } - this.save(); - if (this.inSMaskMode) { - this.endSMaskMode(); - this.current.activeSMask = null; - } - const currentCtx = this.ctx; - if (!group.isolated) { - (0,util.info)("TODO: Support non-isolated groups."); - } - if (group.knockout) { - (0,util.warn)("Knockout groups not supported."); - } - const currentTransform = (0,display_utils.getCurrentTransform)(currentCtx); - if (group.matrix) { - currentCtx.transform(...group.matrix); - } - if (!group.bbox) { - throw new Error("Bounding box is required."); - } - let bounds = util.Util.getAxialAlignedBoundingBox(group.bbox, (0,display_utils.getCurrentTransform)(currentCtx)); - const canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height]; - bounds = util.Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0]; - const offsetX = Math.floor(bounds[0]); - const offsetY = Math.floor(bounds[1]); - let drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1); - let drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1); - let scaleX = 1, - scaleY = 1; - if (drawnWidth > MAX_GROUP_SIZE) { - scaleX = drawnWidth / MAX_GROUP_SIZE; - drawnWidth = MAX_GROUP_SIZE; - } - if (drawnHeight > MAX_GROUP_SIZE) { - scaleY = drawnHeight / MAX_GROUP_SIZE; - drawnHeight = MAX_GROUP_SIZE; - } - this.current.startNewPathAndClipBox([0, 0, drawnWidth, drawnHeight]); - let cacheId = "groupAt" + this.groupLevel; - if (group.smask) { - cacheId += "_smask_" + this.smaskCounter++ % 2; - } - const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight); - const groupCtx = scratchCanvas.context; - groupCtx.scale(1 / scaleX, 1 / scaleY); - groupCtx.translate(-offsetX, -offsetY); - groupCtx.transform(...currentTransform); - if (group.smask) { - this.smaskStack.push({ - canvas: scratchCanvas.canvas, - context: groupCtx, - offsetX, - offsetY, - scaleX, - scaleY, - subtype: group.smask.subtype, - backdrop: group.smask.backdrop, - transferMap: group.smask.transferMap || null, - startTransformInverse: null - }); - } else { - currentCtx.setTransform(1, 0, 0, 1, 0, 0); - currentCtx.translate(offsetX, offsetY); - currentCtx.scale(scaleX, scaleY); - currentCtx.save(); - } - copyCtxState(currentCtx, groupCtx); - this.ctx = groupCtx; - this.setGState([["BM", "source-over"], ["ca", 1], ["CA", 1]]); - this.groupStack.push(currentCtx); - this.groupLevel++; - } - endGroup(group) { - if (!this.contentVisible) { - return; - } - this.groupLevel--; - const groupCtx = this.ctx; - const ctx = this.groupStack.pop(); - this.ctx = ctx; - this.ctx.imageSmoothingEnabled = false; - if (group.smask) { - this.tempSMask = this.smaskStack.pop(); - this.restore(); - } else { - this.ctx.restore(); - const currentMtx = (0,display_utils.getCurrentTransform)(this.ctx); - this.restore(); - this.ctx.save(); - this.ctx.setTransform(...currentMtx); - const dirtyBox = util.Util.getAxialAlignedBoundingBox([0, 0, groupCtx.canvas.width, groupCtx.canvas.height], currentMtx); - this.ctx.drawImage(groupCtx.canvas, 0, 0); - this.ctx.restore(); - this.compose(dirtyBox); - } - } - beginAnnotation(id, rect, transform, matrix, hasOwnCanvas) { - this.#restoreInitialState(); - resetCtxToDefault(this.ctx); - this.ctx.save(); - this.save(); - if (this.baseTransform) { - this.ctx.setTransform(...this.baseTransform); - } - if (Array.isArray(rect) && rect.length === 4) { - const width = rect[2] - rect[0]; - const height = rect[3] - rect[1]; - if (hasOwnCanvas && this.annotationCanvasMap) { - transform = transform.slice(); - transform[4] -= rect[0]; - transform[5] -= rect[1]; - rect = rect.slice(); - rect[0] = rect[1] = 0; - rect[2] = width; - rect[3] = height; - const [scaleX, scaleY] = util.Util.singularValueDecompose2dScale((0,display_utils.getCurrentTransform)(this.ctx)); - const { - viewportScale - } = this; - const canvasWidth = Math.ceil(width * this.outputScaleX * viewportScale); - const canvasHeight = Math.ceil(height * this.outputScaleY * viewportScale); - this.annotationCanvas = this.canvasFactory.create(canvasWidth, canvasHeight); - const { - canvas, - context - } = this.annotationCanvas; - this.annotationCanvasMap.set(id, canvas); - this.annotationCanvas.savedCtx = this.ctx; - this.ctx = context; - this.ctx.save(); - this.ctx.setTransform(scaleX, 0, 0, -scaleY, 0, height * scaleY); - resetCtxToDefault(this.ctx); - } else { - resetCtxToDefault(this.ctx); - this.ctx.rect(rect[0], rect[1], width, height); - this.ctx.clip(); - this.endPath(); - } - } - this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height); - this.transform(...transform); - this.transform(...matrix); - } - endAnnotation() { - if (this.annotationCanvas) { - this.ctx.restore(); - this.#drawFilter(); - this.ctx = this.annotationCanvas.savedCtx; - delete this.annotationCanvas.savedCtx; - delete this.annotationCanvas; - } - } - paintImageMaskXObject(img) { - if (!this.contentVisible) { - return; - } - const count = img.count; - img = this.getObject(img.data, img); - img.count = count; - const ctx = this.ctx; - const glyph = this.processingType3; - if (glyph) { - if (glyph.compiled === undefined) { - glyph.compiled = compileType3Glyph(img); - } - if (glyph.compiled) { - glyph.compiled(ctx); - return; - } - } - const mask = this._createMaskCanvas(img); - const maskCanvas = mask.canvas; - ctx.save(); - ctx.setTransform(1, 0, 0, 1, 0, 0); - ctx.drawImage(maskCanvas, mask.offsetX, mask.offsetY); - ctx.restore(); - this.compose(); - } - paintImageMaskXObjectRepeat(img, scaleX, skewX = 0, skewY = 0, scaleY, positions) { - if (!this.contentVisible) { - return; - } - img = this.getObject(img.data, img); - const ctx = this.ctx; - ctx.save(); - const currentTransform = (0,display_utils.getCurrentTransform)(ctx); - ctx.transform(scaleX, skewX, skewY, scaleY, 0, 0); - const mask = this._createMaskCanvas(img); - ctx.setTransform(1, 0, 0, 1, mask.offsetX - currentTransform[4], mask.offsetY - currentTransform[5]); - for (let i = 0, ii = positions.length; i < ii; i += 2) { - const trans = util.Util.transform(currentTransform, [scaleX, skewX, skewY, scaleY, positions[i], positions[i + 1]]); - const [x, y] = util.Util.applyTransform([0, 0], trans); - ctx.drawImage(mask.canvas, x, y); - } - ctx.restore(); - this.compose(); - } - paintImageMaskXObjectGroup(images) { - if (!this.contentVisible) { - return; - } - const ctx = this.ctx; - const fillColor = this.current.fillColor; - const isPatternFill = this.current.patternFill; - for (const image of images) { - const { - data, - width, - height, - transform - } = image; - const maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height); - const maskCtx = maskCanvas.context; - maskCtx.save(); - const img = this.getObject(data, image); - putBinaryImageMask(maskCtx, img); - maskCtx.globalCompositeOperation = "source-in"; - maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, (0,display_utils.getCurrentTransformInverse)(ctx), PathType.FILL) : fillColor; - maskCtx.fillRect(0, 0, width, height); - maskCtx.restore(); - ctx.save(); - ctx.transform(...transform); - ctx.scale(1, -1); - drawImageAtIntegerCoords(ctx, maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1); - ctx.restore(); - } - this.compose(); - } - paintImageXObject(objId) { - if (!this.contentVisible) { - return; - } - const imgData = this.getObject(objId); - if (!imgData) { - (0,util.warn)("Dependent image isn't ready yet"); - return; - } - this.paintInlineImageXObject(imgData); - } - paintImageXObjectRepeat(objId, scaleX, scaleY, positions) { - if (!this.contentVisible) { - return; - } - const imgData = this.getObject(objId); - if (!imgData) { - (0,util.warn)("Dependent image isn't ready yet"); - return; - } - const width = imgData.width; - const height = imgData.height; - const map = []; - for (let i = 0, ii = positions.length; i < ii; i += 2) { - map.push({ - transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]], - x: 0, - y: 0, - w: width, - h: height - }); - } - this.paintInlineImageXObjectGroup(imgData, map); - } - applyTransferMapsToCanvas(ctx) { - if (this.current.transferMaps !== "none") { - ctx.filter = this.current.transferMaps; - ctx.drawImage(ctx.canvas, 0, 0); - ctx.filter = "none"; - } - return ctx.canvas; - } - applyTransferMapsToBitmap(imgData) { - if (this.current.transferMaps === "none") { - return imgData.bitmap; - } - const { - bitmap, - width, - height - } = imgData; - const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height); - const tmpCtx = tmpCanvas.context; - tmpCtx.filter = this.current.transferMaps; - tmpCtx.drawImage(bitmap, 0, 0); - tmpCtx.filter = "none"; - return tmpCanvas.canvas; - } - paintInlineImageXObject(imgData) { - if (!this.contentVisible) { - return; - } - const width = imgData.width; - const height = imgData.height; - const ctx = this.ctx; - this.save(); - if (!util.isNodeJS) { - const { - filter - } = ctx; - if (filter !== "none" && filter !== "") { - ctx.filter = "none"; - } - } - ctx.scale(1 / width, -1 / height); - let imgToPaint; - if (imgData.bitmap) { - imgToPaint = this.applyTransferMapsToBitmap(imgData); - } else if (typeof HTMLElement === "function" && imgData instanceof HTMLElement || !imgData.data) { - imgToPaint = imgData; - } else { - const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height); - const tmpCtx = tmpCanvas.context; - putBinaryImageData(tmpCtx, imgData); - imgToPaint = this.applyTransferMapsToCanvas(tmpCtx); - } - const scaled = this._scaleImage(imgToPaint, (0,display_utils.getCurrentTransformInverse)(ctx)); - ctx.imageSmoothingEnabled = getImageSmoothingEnabled((0,display_utils.getCurrentTransform)(ctx), imgData.interpolate); - drawImageAtIntegerCoords(ctx, scaled.img, 0, 0, scaled.paintWidth, scaled.paintHeight, 0, -height, width, height); - this.compose(); - this.restore(); - } - paintInlineImageXObjectGroup(imgData, map) { - if (!this.contentVisible) { - return; - } - const ctx = this.ctx; - let imgToPaint; - if (imgData.bitmap) { - imgToPaint = imgData.bitmap; - } else { - const w = imgData.width; - const h = imgData.height; - const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", w, h); - const tmpCtx = tmpCanvas.context; - putBinaryImageData(tmpCtx, imgData); - imgToPaint = this.applyTransferMapsToCanvas(tmpCtx); - } - for (const entry of map) { - ctx.save(); - ctx.transform(...entry.transform); - ctx.scale(1, -1); - drawImageAtIntegerCoords(ctx, imgToPaint, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1); - ctx.restore(); - } - this.compose(); - } - paintSolidColorImageMask() { - if (!this.contentVisible) { - return; - } - this.ctx.fillRect(0, 0, 1, 1); - this.compose(); - } - markPoint(tag) {} - markPointProps(tag, properties) {} - beginMarkedContent(tag) { - this.markedContentStack.push({ - visible: true - }); - } - beginMarkedContentProps(tag, properties) { - if (tag === "OC") { - this.markedContentStack.push({ - visible: this.optionalContentConfig.isVisible(properties) - }); - } else { - this.markedContentStack.push({ - visible: true - }); - } - this.contentVisible = this.isContentVisible(); - } - endMarkedContent() { - this.markedContentStack.pop(); - this.contentVisible = this.isContentVisible(); - } - beginCompat() {} - endCompat() {} - consumePath(clipBox) { - const isEmpty = this.current.isEmptyClip(); - if (this.pendingClip) { - this.current.updateClipFromPath(); - } - if (!this.pendingClip) { - this.compose(clipBox); - } - const ctx = this.ctx; - if (this.pendingClip) { - if (!isEmpty) { - if (this.pendingClip === EO_CLIP) { - ctx.clip("evenodd"); - } else { - ctx.clip(); - } - } - this.pendingClip = null; - } - this.current.startNewPathAndClipBox(this.current.clipBox); - ctx.beginPath(); - } - getSinglePixelWidth() { - if (!this._cachedGetSinglePixelWidth) { - const m = (0,display_utils.getCurrentTransform)(this.ctx); - if (m[1] === 0 && m[2] === 0) { - this._cachedGetSinglePixelWidth = 1 / Math.min(Math.abs(m[0]), Math.abs(m[3])); - } else { - const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]); - const normX = Math.hypot(m[0], m[2]); - const normY = Math.hypot(m[1], m[3]); - this._cachedGetSinglePixelWidth = Math.max(normX, normY) / absDet; - } - } - return this._cachedGetSinglePixelWidth; - } - getScaleForStroking() { - if (this._cachedScaleForStroking[0] === -1) { - const { - lineWidth - } = this.current; - const { - a, - b, - c, - d - } = this.ctx.getTransform(); - let scaleX, scaleY; - if (b === 0 && c === 0) { - const normX = Math.abs(a); - const normY = Math.abs(d); - if (normX === normY) { - if (lineWidth === 0) { - scaleX = scaleY = 1 / normX; - } else { - const scaledLineWidth = normX * lineWidth; - scaleX = scaleY = scaledLineWidth < 1 ? 1 / scaledLineWidth : 1; - } - } else if (lineWidth === 0) { - scaleX = 1 / normX; - scaleY = 1 / normY; - } else { - const scaledXLineWidth = normX * lineWidth; - const scaledYLineWidth = normY * lineWidth; - scaleX = scaledXLineWidth < 1 ? 1 / scaledXLineWidth : 1; - scaleY = scaledYLineWidth < 1 ? 1 / scaledYLineWidth : 1; - } - } else { - const absDet = Math.abs(a * d - b * c); - const normX = Math.hypot(a, b); - const normY = Math.hypot(c, d); - if (lineWidth === 0) { - scaleX = normY / absDet; - scaleY = normX / absDet; - } else { - const baseArea = lineWidth * absDet; - scaleX = normY > baseArea ? normY / baseArea : 1; - scaleY = normX > baseArea ? normX / baseArea : 1; - } - } - this._cachedScaleForStroking[0] = scaleX; - this._cachedScaleForStroking[1] = scaleY; - } - return this._cachedScaleForStroking; - } - rescaleAndStroke(saveRestore) { - const { - ctx - } = this; - const { - lineWidth - } = this.current; - const [scaleX, scaleY] = this.getScaleForStroking(); - ctx.lineWidth = lineWidth || 1; - if (scaleX === 1 && scaleY === 1) { - ctx.stroke(); - return; - } - const dashes = ctx.getLineDash(); - if (saveRestore) { - ctx.save(); - } - ctx.scale(scaleX, scaleY); - if (dashes.length > 0) { - const scale = Math.max(scaleX, scaleY); - ctx.setLineDash(dashes.map(x => x / scale)); - ctx.lineDashOffset /= scale; - } - ctx.stroke(); - if (saveRestore) { - ctx.restore(); - } - } - isContentVisible() { - for (let i = this.markedContentStack.length - 1; i >= 0; i--) { - if (!this.markedContentStack[i].visible) { - return false; - } - } - return true; - } -} -for (const op in util.OPS) { - if (CanvasGraphics.prototype[op] !== undefined) { - CanvasGraphics.prototype[util.OPS[op]] = CanvasGraphics.prototype[op]; - } -} - - -/***/ }), - -/***/ 419: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ DOMCMapReaderFactory: () => (/* binding */ DOMCMapReaderFactory), -/* harmony export */ DOMCanvasFactory: () => (/* binding */ DOMCanvasFactory), -/* harmony export */ DOMFilterFactory: () => (/* binding */ DOMFilterFactory), -/* harmony export */ DOMSVGFactory: () => (/* binding */ DOMSVGFactory), -/* harmony export */ DOMStandardFontDataFactory: () => (/* binding */ DOMStandardFontDataFactory), -/* harmony export */ PDFDateString: () => (/* binding */ PDFDateString), -/* harmony export */ PageViewport: () => (/* binding */ PageViewport), -/* harmony export */ PixelsPerInch: () => (/* binding */ PixelsPerInch), -/* harmony export */ RenderingCancelledException: () => (/* binding */ RenderingCancelledException), -/* harmony export */ StatTimer: () => (/* binding */ StatTimer), -/* harmony export */ fetchData: () => (/* binding */ fetchData), -/* harmony export */ getColorValues: () => (/* binding */ getColorValues), -/* harmony export */ getCurrentTransform: () => (/* binding */ getCurrentTransform), -/* harmony export */ getCurrentTransformInverse: () => (/* binding */ getCurrentTransformInverse), -/* harmony export */ getFilenameFromUrl: () => (/* binding */ getFilenameFromUrl), -/* harmony export */ getPdfFilenameFromUrl: () => (/* binding */ getPdfFilenameFromUrl), -/* harmony export */ getRGB: () => (/* binding */ getRGB), -/* harmony export */ getXfaPageViewport: () => (/* binding */ getXfaPageViewport), -/* harmony export */ isDataScheme: () => (/* binding */ isDataScheme), -/* harmony export */ isPdfFile: () => (/* binding */ isPdfFile), -/* harmony export */ isValidFetchUrl: () => (/* binding */ isValidFetchUrl), -/* harmony export */ noContextMenu: () => (/* binding */ noContextMenu), -/* harmony export */ setLayerDimensions: () => (/* binding */ setLayerDimensions) -/* harmony export */ }); -/* unused harmony export deprecated */ -/* harmony import */ var _base_factory_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(583); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(292); - - -const SVG_NS = "http://www.w3.org/2000/svg"; -class PixelsPerInch { - static CSS = 96.0; - static PDF = 72.0; - static PDF_TO_CSS_UNITS = this.CSS / this.PDF; -} -class DOMFilterFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseFilterFactory { - #_cache; - #_defs; - #docId; - #document; - #_hcmCache; - #id = 0; - constructor({ - docId, - ownerDocument = globalThis.document - } = {}) { - super(); - this.#docId = docId; - this.#document = ownerDocument; - } - get #cache() { - return this.#_cache ||= new Map(); - } - get #hcmCache() { - return this.#_hcmCache ||= new Map(); - } - get #defs() { - if (!this.#_defs) { - const div = this.#document.createElement("div"); - const { - style - } = div; - style.visibility = "hidden"; - style.contain = "strict"; - style.width = style.height = 0; - style.position = "absolute"; - style.top = style.left = 0; - style.zIndex = -1; - const svg = this.#document.createElementNS(SVG_NS, "svg"); - svg.setAttribute("width", 0); - svg.setAttribute("height", 0); - this.#_defs = this.#document.createElementNS(SVG_NS, "defs"); - div.append(svg); - svg.append(this.#_defs); - this.#document.body.append(div); - } - return this.#_defs; - } - addFilter(maps) { - if (!maps) { - return "none"; - } - let value = this.#cache.get(maps); - if (value) { - return value; - } - let tableR, tableG, tableB, key; - if (maps.length === 1) { - const mapR = maps[0]; - const buffer = new Array(256); - for (let i = 0; i < 256; i++) { - buffer[i] = mapR[i] / 255; - } - key = tableR = tableG = tableB = buffer.join(","); - } else { - const [mapR, mapG, mapB] = maps; - const bufferR = new Array(256); - const bufferG = new Array(256); - const bufferB = new Array(256); - for (let i = 0; i < 256; i++) { - bufferR[i] = mapR[i] / 255; - bufferG[i] = mapG[i] / 255; - bufferB[i] = mapB[i] / 255; - } - tableR = bufferR.join(","); - tableG = bufferG.join(","); - tableB = bufferB.join(","); - key = `${tableR}${tableG}${tableB}`; - } - value = this.#cache.get(key); - if (value) { - this.#cache.set(maps, value); - return value; - } - const id = `g_${this.#docId}_transfer_map_${this.#id++}`; - const url = `url(#${id})`; - this.#cache.set(maps, url); - this.#cache.set(key, url); - const filter = this.#createFilter(id); - this.#addTransferMapConversion(tableR, tableG, tableB, filter); - return url; - } - addHCMFilter(fgColor, bgColor) { - const key = `${fgColor}-${bgColor}`; - const filterName = "base"; - let info = this.#hcmCache.get(filterName); - if (info?.key === key) { - return info.url; - } - if (info) { - info.filter?.remove(); - info.key = key; - info.url = "none"; - info.filter = null; - } else { - info = { - key, - url: "none", - filter: null - }; - this.#hcmCache.set(filterName, info); - } - if (!fgColor || !bgColor) { - return info.url; - } - const fgRGB = this.#getRGB(fgColor); - fgColor = _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.makeHexColor(...fgRGB); - const bgRGB = this.#getRGB(bgColor); - bgColor = _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.makeHexColor(...bgRGB); - this.#defs.style.color = ""; - if (fgColor === "#000000" && bgColor === "#ffffff" || fgColor === bgColor) { - return info.url; - } - const map = new Array(256); - for (let i = 0; i <= 255; i++) { - const x = i / 255; - map[i] = x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4; - } - const table = map.join(","); - const id = `g_${this.#docId}_hcm_filter`; - const filter = info.filter = this.#createFilter(id); - this.#addTransferMapConversion(table, table, table, filter); - this.#addGrayConversion(filter); - const getSteps = (c, n) => { - const start = fgRGB[c] / 255; - const end = bgRGB[c] / 255; - const arr = new Array(n + 1); - for (let i = 0; i <= n; i++) { - arr[i] = start + i / n * (end - start); - } - return arr.join(","); - }; - this.#addTransferMapConversion(getSteps(0, 5), getSteps(1, 5), getSteps(2, 5), filter); - info.url = `url(#${id})`; - return info.url; - } - addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { - const key = `${fgColor}-${bgColor}-${newFgColor}-${newBgColor}`; - let info = this.#hcmCache.get(filterName); - if (info?.key === key) { - return info.url; - } - if (info) { - info.filter?.remove(); - info.key = key; - info.url = "none"; - info.filter = null; - } else { - info = { - key, - url: "none", - filter: null - }; - this.#hcmCache.set(filterName, info); - } - if (!fgColor || !bgColor) { - return info.url; - } - const [fgRGB, bgRGB] = [fgColor, bgColor].map(this.#getRGB.bind(this)); - let fgGray = Math.round(0.2126 * fgRGB[0] + 0.7152 * fgRGB[1] + 0.0722 * fgRGB[2]); - let bgGray = Math.round(0.2126 * bgRGB[0] + 0.7152 * bgRGB[1] + 0.0722 * bgRGB[2]); - let [newFgRGB, newBgRGB] = [newFgColor, newBgColor].map(this.#getRGB.bind(this)); - if (bgGray < fgGray) { - [fgGray, bgGray, newFgRGB, newBgRGB] = [bgGray, fgGray, newBgRGB, newFgRGB]; - } - this.#defs.style.color = ""; - const getSteps = (fg, bg, n) => { - const arr = new Array(256); - const step = (bgGray - fgGray) / n; - const newStart = fg / 255; - const newStep = (bg - fg) / (255 * n); - let prev = 0; - for (let i = 0; i <= n; i++) { - const k = Math.round(fgGray + i * step); - const value = newStart + i * newStep; - for (let j = prev; j <= k; j++) { - arr[j] = value; - } - prev = k + 1; - } - for (let i = prev; i < 256; i++) { - arr[i] = arr[prev - 1]; - } - return arr.join(","); - }; - const id = `g_${this.#docId}_hcm_${filterName}_filter`; - const filter = info.filter = this.#createFilter(id); - this.#addGrayConversion(filter); - this.#addTransferMapConversion(getSteps(newFgRGB[0], newBgRGB[0], 5), getSteps(newFgRGB[1], newBgRGB[1], 5), getSteps(newFgRGB[2], newBgRGB[2], 5), filter); - info.url = `url(#${id})`; - return info.url; - } - destroy(keepHCM = false) { - if (keepHCM && this.#hcmCache.size !== 0) { - return; - } - if (this.#_defs) { - this.#_defs.parentNode.parentNode.remove(); - this.#_defs = null; - } - if (this.#_cache) { - this.#_cache.clear(); - this.#_cache = null; - } - this.#id = 0; - } - #addGrayConversion(filter) { - const feColorMatrix = this.#document.createElementNS(SVG_NS, "feColorMatrix"); - feColorMatrix.setAttribute("type", "matrix"); - feColorMatrix.setAttribute("values", "0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"); - filter.append(feColorMatrix); - } - #createFilter(id) { - const filter = this.#document.createElementNS(SVG_NS, "filter"); - filter.setAttribute("color-interpolation-filters", "sRGB"); - filter.setAttribute("id", id); - this.#defs.append(filter); - return filter; - } - #appendFeFunc(feComponentTransfer, func, table) { - const feFunc = this.#document.createElementNS(SVG_NS, func); - feFunc.setAttribute("type", "discrete"); - feFunc.setAttribute("tableValues", table); - feComponentTransfer.append(feFunc); - } - #addTransferMapConversion(rTable, gTable, bTable, filter) { - const feComponentTransfer = this.#document.createElementNS(SVG_NS, "feComponentTransfer"); - filter.append(feComponentTransfer); - this.#appendFeFunc(feComponentTransfer, "feFuncR", rTable); - this.#appendFeFunc(feComponentTransfer, "feFuncG", gTable); - this.#appendFeFunc(feComponentTransfer, "feFuncB", bTable); - } - #getRGB(color) { - this.#defs.style.color = color; - return getRGB(getComputedStyle(this.#defs).getPropertyValue("color")); - } -} -class DOMCanvasFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseCanvasFactory { - constructor({ - ownerDocument = globalThis.document - } = {}) { - super(); - this._document = ownerDocument; - } - _createCanvas(width, height) { - const canvas = this._document.createElement("canvas"); - canvas.width = width; - canvas.height = height; - return canvas; - } -} -async function fetchData(url, type = "text") { - if (isValidFetchUrl(url, document.baseURI)) { - const response = await fetch(url); - if (!response.ok) { - throw new Error(response.statusText); - } - switch (type) { - case "arraybuffer": - return response.arrayBuffer(); - case "blob": - return response.blob(); - case "json": - return response.json(); - } - return response.text(); - } - return new Promise((resolve, reject) => { - const request = new XMLHttpRequest(); - request.open("GET", url, true); - request.responseType = type; - request.onreadystatechange = () => { - if (request.readyState !== XMLHttpRequest.DONE) { - return; - } - if (request.status === 200 || request.status === 0) { - switch (type) { - case "arraybuffer": - case "blob": - case "json": - resolve(request.response); - return; - } - resolve(request.responseText); - return; - } - reject(new Error(request.statusText)); - }; - request.send(null); - }); -} -class DOMCMapReaderFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseCMapReaderFactory { - _fetchData(url, compressionType) { - return fetchData(url, this.isCompressed ? "arraybuffer" : "text").then(data => ({ - cMapData: data instanceof ArrayBuffer ? new Uint8Array(data) : (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.stringToBytes)(data), - compressionType - })); - } -} -class DOMStandardFontDataFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseStandardFontDataFactory { - _fetchData(url) { - return fetchData(url, "arraybuffer").then(data => new Uint8Array(data)); - } -} -class DOMSVGFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseSVGFactory { - _createSVG(type) { - return document.createElementNS(SVG_NS, type); - } -} -class PageViewport { - constructor({ - viewBox, - scale, - rotation, - offsetX = 0, - offsetY = 0, - dontFlip = false - }) { - this.viewBox = viewBox; - this.scale = scale; - this.rotation = rotation; - this.offsetX = offsetX; - this.offsetY = offsetY; - const centerX = (viewBox[2] + viewBox[0]) / 2; - const centerY = (viewBox[3] + viewBox[1]) / 2; - let rotateA, rotateB, rotateC, rotateD; - rotation %= 360; - if (rotation < 0) { - rotation += 360; - } - switch (rotation) { - case 180: - rotateA = -1; - rotateB = 0; - rotateC = 0; - rotateD = 1; - break; - case 90: - rotateA = 0; - rotateB = 1; - rotateC = 1; - rotateD = 0; - break; - case 270: - rotateA = 0; - rotateB = -1; - rotateC = -1; - rotateD = 0; - break; - case 0: - rotateA = 1; - rotateB = 0; - rotateC = 0; - rotateD = -1; - break; - default: - throw new Error("PageViewport: Invalid rotation, must be a multiple of 90 degrees."); - } - if (dontFlip) { - rotateC = -rotateC; - rotateD = -rotateD; - } - let offsetCanvasX, offsetCanvasY; - let width, height; - if (rotateA === 0) { - offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; - offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; - width = (viewBox[3] - viewBox[1]) * scale; - height = (viewBox[2] - viewBox[0]) * scale; - } else { - offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; - offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; - width = (viewBox[2] - viewBox[0]) * scale; - height = (viewBox[3] - viewBox[1]) * scale; - } - this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY]; - this.width = width; - this.height = height; - } - get rawDims() { - const { - viewBox - } = this; - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "rawDims", { - pageWidth: viewBox[2] - viewBox[0], - pageHeight: viewBox[3] - viewBox[1], - pageX: viewBox[0], - pageY: viewBox[1] - }); - } - clone({ - scale = this.scale, - rotation = this.rotation, - offsetX = this.offsetX, - offsetY = this.offsetY, - dontFlip = false - } = {}) { - return new PageViewport({ - viewBox: this.viewBox.slice(), - scale, - rotation, - offsetX, - offsetY, - dontFlip - }); - } - convertToViewportPoint(x, y) { - return _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.applyTransform([x, y], this.transform); - } - convertToViewportRectangle(rect) { - const topLeft = _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.applyTransform([rect[0], rect[1]], this.transform); - const bottomRight = _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.applyTransform([rect[2], rect[3]], this.transform); - return [topLeft[0], topLeft[1], bottomRight[0], bottomRight[1]]; - } - convertToPdfPoint(x, y) { - return _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.Util.applyInverseTransform([x, y], this.transform); - } -} -class RenderingCancelledException extends _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.BaseException { - constructor(msg, extraDelay = 0) { - super(msg, "RenderingCancelledException"); - this.extraDelay = extraDelay; - } -} -function isDataScheme(url) { - const ii = url.length; - let i = 0; - while (i < ii && url[i].trim() === "") { - i++; - } - return url.substring(i, i + 5).toLowerCase() === "data:"; -} -function isPdfFile(filename) { - return typeof filename === "string" && /\.pdf$/i.test(filename); -} -function getFilenameFromUrl(url, onlyStripPath = false) { - if (!onlyStripPath) { - [url] = url.split(/[#?]/, 1); - } - return url.substring(url.lastIndexOf("/") + 1); -} -function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") { - if (typeof url !== "string") { - return defaultFilename; - } - if (isDataScheme(url)) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.warn)('getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.'); - return defaultFilename; - } - const reURI = /^(?:(?:[^:]+:)?\/\/[^/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/; - const reFilename = /[^/?#=]+\.pdf\b(?!.*\.pdf\b)/i; - const splitURI = reURI.exec(url); - let suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]); - if (suggestedFilename) { - suggestedFilename = suggestedFilename[0]; - if (suggestedFilename.includes("%")) { - try { - suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0]; - } catch {} - } - } - return suggestedFilename || defaultFilename; -} -class StatTimer { - started = Object.create(null); - times = []; - time(name) { - if (name in this.started) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.warn)(`Timer is already running for ${name}`); - } - this.started[name] = Date.now(); - } - timeEnd(name) { - if (!(name in this.started)) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.warn)(`Timer has not been started for ${name}`); - } - this.times.push({ - name, - start: this.started[name], - end: Date.now() - }); - delete this.started[name]; - } - toString() { - const outBuf = []; - let longest = 0; - for (const { - name - } of this.times) { - longest = Math.max(name.length, longest); - } - for (const { - name, - start, - end - } of this.times) { - outBuf.push(`${name.padEnd(longest)} ${end - start}ms\n`); - } - return outBuf.join(""); - } -} -function isValidFetchUrl(url, baseUrl) { - try { - const { - protocol - } = baseUrl ? new URL(url, baseUrl) : new URL(url); - return protocol === "http:" || protocol === "https:"; - } catch { - return false; - } -} -function noContextMenu(e) { - e.preventDefault(); -} -function deprecated(details) { - console.log("Deprecated API usage: " + details); -} -let pdfDateStringRegex; -class PDFDateString { - static toDateObject(input) { - if (!input || typeof input !== "string") { - return null; - } - pdfDateStringRegex ||= new RegExp("^D:" + "(\\d{4})" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "([Z|+|-])?" + "(\\d{2})?" + "'?" + "(\\d{2})?" + "'?"); - const matches = pdfDateStringRegex.exec(input); - if (!matches) { - return null; - } - const year = parseInt(matches[1], 10); - let month = parseInt(matches[2], 10); - month = month >= 1 && month <= 12 ? month - 1 : 0; - let day = parseInt(matches[3], 10); - day = day >= 1 && day <= 31 ? day : 1; - let hour = parseInt(matches[4], 10); - hour = hour >= 0 && hour <= 23 ? hour : 0; - let minute = parseInt(matches[5], 10); - minute = minute >= 0 && minute <= 59 ? minute : 0; - let second = parseInt(matches[6], 10); - second = second >= 0 && second <= 59 ? second : 0; - const universalTimeRelation = matches[7] || "Z"; - let offsetHour = parseInt(matches[8], 10); - offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0; - let offsetMinute = parseInt(matches[9], 10) || 0; - offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0; - if (universalTimeRelation === "-") { - hour += offsetHour; - minute += offsetMinute; - } else if (universalTimeRelation === "+") { - hour -= offsetHour; - minute -= offsetMinute; - } - return new Date(Date.UTC(year, month, day, hour, minute, second)); - } -} -function getXfaPageViewport(xfaPage, { - scale = 1, - rotation = 0 -}) { - const { - width, - height - } = xfaPage.attributes.style; - const viewBox = [0, 0, parseInt(width), parseInt(height)]; - return new PageViewport({ - viewBox, - scale, - rotation - }); -} -function getRGB(color) { - if (color.startsWith("#")) { - const colorRGB = parseInt(color.slice(1), 16); - return [(colorRGB & 0xff0000) >> 16, (colorRGB & 0x00ff00) >> 8, colorRGB & 0x0000ff]; - } - if (color.startsWith("rgb(")) { - return color.slice(4, -1).split(",").map(x => parseInt(x)); - } - if (color.startsWith("rgba(")) { - return color.slice(5, -1).split(",").map(x => parseInt(x)).slice(0, 3); - } - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.warn)(`Not a valid color format: "${color}"`); - return [0, 0, 0]; -} -function getColorValues(colors) { - const span = document.createElement("span"); - span.style.visibility = "hidden"; - document.body.append(span); - for (const name of colors.keys()) { - span.style.color = name; - const computedColor = window.getComputedStyle(span).color; - colors.set(name, getRGB(computedColor)); - } - span.remove(); -} -function getCurrentTransform(ctx) { - const { - a, - b, - c, - d, - e, - f - } = ctx.getTransform(); - return [a, b, c, d, e, f]; -} -function getCurrentTransformInverse(ctx) { - const { - a, - b, - c, - d, - e, - f - } = ctx.getTransform().invertSelf(); - return [a, b, c, d, e, f]; -} -function setLayerDimensions(div, viewport, mustFlip = false, mustRotate = true) { - if (viewport instanceof PageViewport) { - const { - pageWidth, - pageHeight - } = viewport.rawDims; - const { - style - } = div; - const useRound = _shared_util_js__WEBPACK_IMPORTED_MODULE_1__.FeatureTest.isCSSRoundSupported; - const w = `var(--scale-factor) * ${pageWidth}px`, - h = `var(--scale-factor) * ${pageHeight}px`; - const widthStr = useRound ? `round(${w}, 1px)` : `calc(${w})`, - heightStr = useRound ? `round(${h}, 1px)` : `calc(${h})`; - if (!mustFlip || viewport.rotation % 180 === 0) { - style.width = widthStr; - style.height = heightStr; - } else { - style.width = heightStr; - style.height = widthStr; - } - } - if (mustRotate) { - div.setAttribute("data-main-rotation", viewport.rotation); - } -} - - -/***/ }), - -/***/ 47: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ DrawLayer: () => (/* binding */ DrawLayer) -/* harmony export */ }); -/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(419); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(292); - - -class DrawLayer { - #parent = null; - #id = 0; - #mapping = new Map(); - #toUpdate = new Map(); - constructor({ - pageIndex - }) { - this.pageIndex = pageIndex; - } - setParent(parent) { - if (!this.#parent) { - this.#parent = parent; - return; - } - if (this.#parent !== parent) { - if (this.#mapping.size > 0) { - for (const root of this.#mapping.values()) { - root.remove(); - parent.append(root); - } - } - this.#parent = parent; - } - } - static get _svgFactory() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "_svgFactory", new _display_utils_js__WEBPACK_IMPORTED_MODULE_0__.DOMSVGFactory()); - } - static #setBox(element, { - x = 0, - y = 0, - width = 1, - height = 1 - } = {}) { - const { - style - } = element; - style.top = `${100 * y}%`; - style.left = `${100 * x}%`; - style.width = `${100 * width}%`; - style.height = `${100 * height}%`; - } - #createSVG(box) { - const svg = DrawLayer._svgFactory.create(1, 1, true); - this.#parent.append(svg); - svg.setAttribute("aria-hidden", true); - DrawLayer.#setBox(svg, box); - return svg; - } - #createClipPath(defs, pathId) { - const clipPath = DrawLayer._svgFactory.createElement("clipPath"); - defs.append(clipPath); - const clipPathId = `clip_${pathId}`; - clipPath.setAttribute("id", clipPathId); - clipPath.setAttribute("clipPathUnits", "objectBoundingBox"); - const clipPathUse = DrawLayer._svgFactory.createElement("use"); - clipPath.append(clipPathUse); - clipPathUse.setAttribute("href", `#${pathId}`); - clipPathUse.classList.add("clip"); - return clipPathId; - } - highlight(outlines, color, opacity, isPathUpdatable = false) { - const id = this.#id++; - const root = this.#createSVG(outlines.box); - root.classList.add("highlight"); - if (outlines.free) { - root.classList.add("free"); - } - const defs = DrawLayer._svgFactory.createElement("defs"); - root.append(defs); - const path = DrawLayer._svgFactory.createElement("path"); - defs.append(path); - const pathId = `path_p${this.pageIndex}_${id}`; - path.setAttribute("id", pathId); - path.setAttribute("d", outlines.toSVGPath()); - if (isPathUpdatable) { - this.#toUpdate.set(id, path); - } - const clipPathId = this.#createClipPath(defs, pathId); - const use = DrawLayer._svgFactory.createElement("use"); - root.append(use); - root.setAttribute("fill", color); - root.setAttribute("fill-opacity", opacity); - use.setAttribute("href", `#${pathId}`); - this.#mapping.set(id, root); - return { - id, - clipPathId: `url(#${clipPathId})` - }; - } - highlightOutline(outlines) { - const id = this.#id++; - const root = this.#createSVG(outlines.box); - root.classList.add("highlightOutline"); - const defs = DrawLayer._svgFactory.createElement("defs"); - root.append(defs); - const path = DrawLayer._svgFactory.createElement("path"); - defs.append(path); - const pathId = `path_p${this.pageIndex}_${id}`; - path.setAttribute("id", pathId); - path.setAttribute("d", outlines.toSVGPath()); - path.setAttribute("vector-effect", "non-scaling-stroke"); - let maskId; - if (outlines.free) { - root.classList.add("free"); - const mask = DrawLayer._svgFactory.createElement("mask"); - defs.append(mask); - maskId = `mask_p${this.pageIndex}_${id}`; - mask.setAttribute("id", maskId); - mask.setAttribute("maskUnits", "objectBoundingBox"); - const rect = DrawLayer._svgFactory.createElement("rect"); - mask.append(rect); - rect.setAttribute("width", "1"); - rect.setAttribute("height", "1"); - rect.setAttribute("fill", "white"); - const use = DrawLayer._svgFactory.createElement("use"); - mask.append(use); - use.setAttribute("href", `#${pathId}`); - use.setAttribute("stroke", "none"); - use.setAttribute("fill", "black"); - use.setAttribute("fill-rule", "nonzero"); - use.classList.add("mask"); - } - const use1 = DrawLayer._svgFactory.createElement("use"); - root.append(use1); - use1.setAttribute("href", `#${pathId}`); - if (maskId) { - use1.setAttribute("mask", `url(#${maskId})`); - } - const use2 = use1.cloneNode(); - root.append(use2); - use1.classList.add("mainOutline"); - use2.classList.add("secondaryOutline"); - this.#mapping.set(id, root); - return id; - } - finalizeLine(id, line) { - const path = this.#toUpdate.get(id); - this.#toUpdate.delete(id); - this.updateBox(id, line.box); - path.setAttribute("d", line.toSVGPath()); - } - updateLine(id, line) { - const root = this.#mapping.get(id); - const defs = root.firstChild; - const path = defs.firstChild; - path.setAttribute("d", line.toSVGPath()); - } - removeFreeHighlight(id) { - this.remove(id); - this.#toUpdate.delete(id); - } - updatePath(id, line) { - this.#toUpdate.get(id).setAttribute("d", line.toSVGPath()); - } - updateBox(id, box) { - DrawLayer.#setBox(this.#mapping.get(id), box); - } - show(id, visible) { - this.#mapping.get(id).classList.toggle("hidden", !visible); - } - rotate(id, angle) { - this.#mapping.get(id).setAttribute("data-main-rotation", angle); - } - changeColor(id, color) { - this.#mapping.get(id).setAttribute("fill", color); - } - changeOpacity(id, opacity) { - this.#mapping.get(id).setAttribute("fill-opacity", opacity); - } - addClass(id, className) { - this.#mapping.get(id).classList.add(className); - } - removeClass(id, className) { - this.#mapping.get(id).classList.remove(className); - } - remove(id) { - if (this.#parent === null) { - return; - } - this.#mapping.get(id).remove(); - this.#mapping.delete(id); - } - destroy() { - this.#parent = null; - for (const root of this.#mapping.values()) { - root.remove(); - } - this.#mapping.clear(); - } -} - - -/***/ }), - -/***/ 731: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - - -// EXPORTS -__webpack_require__.d(__webpack_exports__, { - AnnotationEditorLayer: () => (/* binding */ AnnotationEditorLayer) -}); - -// EXTERNAL MODULE: ./src/shared/util.js -var util = __webpack_require__(292); -// EXTERNAL MODULE: ./src/display/editor/editor.js + 1 modules -var editor_editor = __webpack_require__(310); -// EXTERNAL MODULE: ./src/display/editor/tools.js -var tools = __webpack_require__(830); -// EXTERNAL MODULE: ./src/display/annotation_layer.js + 1 modules -var annotation_layer = __webpack_require__(976); -;// CONCATENATED MODULE: ./src/display/editor/freetext.js - - - - -const EOL_PATTERN = /\r\n?|\n/g; -class FreeTextEditor extends editor_editor.AnnotationEditor { - #boundEditorDivBlur = this.editorDivBlur.bind(this); - #boundEditorDivFocus = this.editorDivFocus.bind(this); - #boundEditorDivInput = this.editorDivInput.bind(this); - #boundEditorDivKeydown = this.editorDivKeydown.bind(this); - #boundEditorDivPaste = this.editorDivPaste.bind(this); - #color; - #content = ""; - #editorDivId = `${this.id}-editor`; - #fontSize; - #initialData = null; - static _freeTextDefaultContent = ""; - static _internalPadding = 0; - static _defaultColor = null; - static _defaultFontSize = 10; - static get _keyboardManager() { - const proto = FreeTextEditor.prototype; - const arrowChecker = self => self.isEmpty(); - const small = tools.AnnotationEditorUIManager.TRANSLATE_SMALL; - const big = tools.AnnotationEditorUIManager.TRANSLATE_BIG; - return (0,util.shadow)(this, "_keyboardManager", new tools.KeyboardManager([[["ctrl+s", "mac+meta+s", "ctrl+p", "mac+meta+p"], proto.commitOrRemove, { - bubbles: true - }], [["ctrl+Enter", "mac+meta+Enter", "Escape", "mac+Escape"], proto.commitOrRemove], [["ArrowLeft", "mac+ArrowLeft"], proto._translateEmpty, { - args: [-small, 0], - checker: arrowChecker - }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], proto._translateEmpty, { - args: [-big, 0], - checker: arrowChecker - }], [["ArrowRight", "mac+ArrowRight"], proto._translateEmpty, { - args: [small, 0], - checker: arrowChecker - }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], proto._translateEmpty, { - args: [big, 0], - checker: arrowChecker - }], [["ArrowUp", "mac+ArrowUp"], proto._translateEmpty, { - args: [0, -small], - checker: arrowChecker - }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], proto._translateEmpty, { - args: [0, -big], - checker: arrowChecker - }], [["ArrowDown", "mac+ArrowDown"], proto._translateEmpty, { - args: [0, small], - checker: arrowChecker - }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], proto._translateEmpty, { - args: [0, big], - checker: arrowChecker - }]])); - } - static _type = "freetext"; - static _editorType = util.AnnotationEditorType.FREETEXT; - constructor(params) { - super({ - ...params, - name: "freeTextEditor" - }); - this.#color = params.color || FreeTextEditor._defaultColor || editor_editor.AnnotationEditor._defaultLineColor; - this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize; - } - static initialize(l10n, uiManager) { - editor_editor.AnnotationEditor.initialize(l10n, uiManager, { - strings: ["pdfjs-free-text-default-content"] - }); - const style = getComputedStyle(document.documentElement); - this._internalPadding = parseFloat(style.getPropertyValue("--freetext-padding")); - } - static updateDefaultParams(type, value) { - switch (type) { - case util.AnnotationEditorParamsType.FREETEXT_SIZE: - FreeTextEditor._defaultFontSize = value; - break; - case util.AnnotationEditorParamsType.FREETEXT_COLOR: - FreeTextEditor._defaultColor = value; - break; - } - } - updateParams(type, value) { - switch (type) { - case util.AnnotationEditorParamsType.FREETEXT_SIZE: - this.#updateFontSize(value); - break; - case util.AnnotationEditorParamsType.FREETEXT_COLOR: - this.#updateColor(value); - break; - } - } - static get defaultPropertiesToUpdate() { - return [[util.AnnotationEditorParamsType.FREETEXT_SIZE, FreeTextEditor._defaultFontSize], [util.AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor || editor_editor.AnnotationEditor._defaultLineColor]]; - } - get propertiesToUpdate() { - return [[util.AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize], [util.AnnotationEditorParamsType.FREETEXT_COLOR, this.#color]]; - } - #updateFontSize(fontSize) { - const setFontsize = size => { - this.editorDiv.style.fontSize = `calc(${size}px * var(--scale-factor))`; - this.translate(0, -(size - this.#fontSize) * this.parentScale); - this.#fontSize = size; - this.#setEditorDimensions(); - }; - const savedFontsize = this.#fontSize; - this.addCommands({ - cmd: setFontsize.bind(this, fontSize), - undo: setFontsize.bind(this, savedFontsize), - post: this._uiManager.updateUI.bind(this._uiManager, this), - mustExec: true, - type: util.AnnotationEditorParamsType.FREETEXT_SIZE, - overwriteIfSameType: true, - keepUndo: true - }); - } - #updateColor(color) { - const setColor = col => { - this.#color = this.editorDiv.style.color = col; - }; - const savedColor = this.#color; - this.addCommands({ - cmd: setColor.bind(this, color), - undo: setColor.bind(this, savedColor), - post: this._uiManager.updateUI.bind(this._uiManager, this), - mustExec: true, - type: util.AnnotationEditorParamsType.FREETEXT_COLOR, - overwriteIfSameType: true, - keepUndo: true - }); - } - _translateEmpty(x, y) { - this._uiManager.translateSelectedEditors(x, y, true); - } - getInitialTranslation() { - const scale = this.parentScale; - return [-FreeTextEditor._internalPadding * scale, -(FreeTextEditor._internalPadding + this.#fontSize) * scale]; - } - rebuild() { - if (!this.parent) { - return; - } - super.rebuild(); - if (this.div === null) { - return; - } - if (!this.isAttachedToDOM) { - this.parent.add(this); - } - } - enableEditMode() { - if (this.isInEditMode()) { - return; - } - this.parent.setEditingState(false); - this.parent.updateToolbar(util.AnnotationEditorType.FREETEXT); - super.enableEditMode(); - this.overlayDiv.classList.remove("enabled"); - this.editorDiv.contentEditable = true; - this._isDraggable = false; - this.div.removeAttribute("aria-activedescendant"); - this.editorDiv.addEventListener("keydown", this.#boundEditorDivKeydown); - this.editorDiv.addEventListener("focus", this.#boundEditorDivFocus); - this.editorDiv.addEventListener("blur", this.#boundEditorDivBlur); - this.editorDiv.addEventListener("input", this.#boundEditorDivInput); - this.editorDiv.addEventListener("paste", this.#boundEditorDivPaste); - } - disableEditMode() { - if (!this.isInEditMode()) { - return; - } - this.parent.setEditingState(true); - super.disableEditMode(); - this.overlayDiv.classList.add("enabled"); - this.editorDiv.contentEditable = false; - this.div.setAttribute("aria-activedescendant", this.#editorDivId); - this._isDraggable = true; - this.editorDiv.removeEventListener("keydown", this.#boundEditorDivKeydown); - this.editorDiv.removeEventListener("focus", this.#boundEditorDivFocus); - this.editorDiv.removeEventListener("blur", this.#boundEditorDivBlur); - this.editorDiv.removeEventListener("input", this.#boundEditorDivInput); - this.editorDiv.removeEventListener("paste", this.#boundEditorDivPaste); - this.div.focus({ - preventScroll: true - }); - this.isEditing = false; - this.parent.div.classList.add("freetextEditing"); - } - focusin(event) { - if (!this._focusEventsAllowed) { - return; - } - super.focusin(event); - if (event.target !== this.editorDiv) { - this.editorDiv.focus(); - } - } - onceAdded() { - if (this.width) { - return; - } - this.enableEditMode(); - this.editorDiv.focus(); - if (this._initialOptions?.isCentered) { - this.center(); - } - this._initialOptions = null; - } - isEmpty() { - return !this.editorDiv || this.editorDiv.innerText.trim() === ""; - } - remove() { - this.isEditing = false; - if (this.parent) { - this.parent.setEditingState(true); - this.parent.div.classList.add("freetextEditing"); - } - super.remove(); - } - #extractText() { - const buffer = []; - this.editorDiv.normalize(); - for (const child of this.editorDiv.childNodes) { - buffer.push(FreeTextEditor.#getNodeContent(child)); - } - return buffer.join("\n"); - } - #setEditorDimensions() { - const [parentWidth, parentHeight] = this.parentDimensions; - let rect; - if (this.isAttachedToDOM) { - rect = this.div.getBoundingClientRect(); - } else { - const { - currentLayer, - div - } = this; - const savedDisplay = div.style.display; - const savedVisibility = div.classList.contains("hidden"); - div.classList.remove("hidden"); - div.style.display = "hidden"; - currentLayer.div.append(this.div); - rect = div.getBoundingClientRect(); - div.remove(); - div.style.display = savedDisplay; - div.classList.toggle("hidden", savedVisibility); - } - if (this.rotation % 180 === this.parentRotation % 180) { - this.width = rect.width / parentWidth; - this.height = rect.height / parentHeight; - } else { - this.width = rect.height / parentWidth; - this.height = rect.width / parentHeight; - } - this.fixAndSetPosition(); - } - commit() { - if (!this.isInEditMode()) { - return; - } - super.commit(); - this.disableEditMode(); - const savedText = this.#content; - const newText = this.#content = this.#extractText().trimEnd(); - if (savedText === newText) { - return; - } - const setText = text => { - this.#content = text; - if (!text) { - this.remove(); - return; - } - this.#setContent(); - this._uiManager.rebuild(this); - this.#setEditorDimensions(); - }; - this.addCommands({ - cmd: () => { - setText(newText); - }, - undo: () => { - setText(savedText); - }, - mustExec: false - }); - this.#setEditorDimensions(); - } - shouldGetKeyboardEvents() { - return this.isInEditMode(); - } - enterInEditMode() { - this.enableEditMode(); - this.editorDiv.focus(); - } - dblclick(event) { - this.enterInEditMode(); - } - keydown(event) { - if (event.target === this.div && event.key === "Enter") { - this.enterInEditMode(); - event.preventDefault(); - } - } - editorDivKeydown(event) { - FreeTextEditor._keyboardManager.exec(this, event); - } - editorDivFocus(event) { - this.isEditing = true; - } - editorDivBlur(event) { - this.isEditing = false; - } - editorDivInput(event) { - this.parent.div.classList.toggle("freetextEditing", this.isEmpty()); - } - disableEditing() { - this.editorDiv.setAttribute("role", "comment"); - this.editorDiv.removeAttribute("aria-multiline"); - } - enableEditing() { - this.editorDiv.setAttribute("role", "textbox"); - this.editorDiv.setAttribute("aria-multiline", true); - } - render() { - if (this.div) { - return this.div; - } - let baseX, baseY; - if (this.width) { - baseX = this.x; - baseY = this.y; - } - super.render(); - this.editorDiv = document.createElement("div"); - this.editorDiv.className = "internal"; - this.editorDiv.setAttribute("id", this.#editorDivId); - this.editorDiv.setAttribute("data-l10n-id", "pdfjs-free-text"); - this.enableEditing(); - editor_editor.AnnotationEditor._l10nPromise.get("pdfjs-free-text-default-content").then(msg => this.editorDiv?.setAttribute("default-content", msg)); - this.editorDiv.contentEditable = true; - const { - style - } = this.editorDiv; - style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`; - style.color = this.#color; - this.div.append(this.editorDiv); - this.overlayDiv = document.createElement("div"); - this.overlayDiv.classList.add("overlay", "enabled"); - this.div.append(this.overlayDiv); - (0,tools.bindEvents)(this, this.div, ["dblclick", "keydown"]); - if (this.width) { - const [parentWidth, parentHeight] = this.parentDimensions; - if (this.annotationElementId) { - const { - position - } = this.#initialData; - let [tx, ty] = this.getInitialTranslation(); - [tx, ty] = this.pageTranslationToScreen(tx, ty); - const [pageWidth, pageHeight] = this.pageDimensions; - const [pageX, pageY] = this.pageTranslation; - let posX, posY; - switch (this.rotation) { - case 0: - posX = baseX + (position[0] - pageX) / pageWidth; - posY = baseY + this.height - (position[1] - pageY) / pageHeight; - break; - case 90: - posX = baseX + (position[0] - pageX) / pageWidth; - posY = baseY - (position[1] - pageY) / pageHeight; - [tx, ty] = [ty, -tx]; - break; - case 180: - posX = baseX - this.width + (position[0] - pageX) / pageWidth; - posY = baseY - (position[1] - pageY) / pageHeight; - [tx, ty] = [-tx, -ty]; - break; - case 270: - posX = baseX + (position[0] - pageX - this.height * pageHeight) / pageWidth; - posY = baseY + (position[1] - pageY - this.width * pageWidth) / pageHeight; - [tx, ty] = [-ty, tx]; - break; - } - this.setAt(posX * parentWidth, posY * parentHeight, tx, ty); - } else { - this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight); - } - this.#setContent(); - this._isDraggable = true; - this.editorDiv.contentEditable = false; - } else { - this._isDraggable = false; - this.editorDiv.contentEditable = true; - } - return this.div; - } - static #getNodeContent(node) { - return (node.nodeType === Node.TEXT_NODE ? node.nodeValue : node.innerText).replaceAll(EOL_PATTERN, ""); - } - editorDivPaste(event) { - const clipboardData = event.clipboardData || window.clipboardData; - const { - types - } = clipboardData; - if (types.length === 1 && types[0] === "text/plain") { - return; - } - event.preventDefault(); - const paste = FreeTextEditor.#deserializeContent(clipboardData.getData("text") || "").replaceAll(EOL_PATTERN, "\n"); - if (!paste) { - return; - } - const selection = window.getSelection(); - if (!selection.rangeCount) { - return; - } - this.editorDiv.normalize(); - selection.deleteFromDocument(); - const range = selection.getRangeAt(0); - if (!paste.includes("\n")) { - range.insertNode(document.createTextNode(paste)); - this.editorDiv.normalize(); - selection.collapseToStart(); - return; - } - const { - startContainer, - startOffset - } = range; - const bufferBefore = []; - const bufferAfter = []; - if (startContainer.nodeType === Node.TEXT_NODE) { - const parent = startContainer.parentElement; - bufferAfter.push(startContainer.nodeValue.slice(startOffset).replaceAll(EOL_PATTERN, "")); - if (parent !== this.editorDiv) { - let buffer = bufferBefore; - for (const child of this.editorDiv.childNodes) { - if (child === parent) { - buffer = bufferAfter; - continue; - } - buffer.push(FreeTextEditor.#getNodeContent(child)); - } - } - bufferBefore.push(startContainer.nodeValue.slice(0, startOffset).replaceAll(EOL_PATTERN, "")); - } else if (startContainer === this.editorDiv) { - let buffer = bufferBefore; - let i = 0; - for (const child of this.editorDiv.childNodes) { - if (i++ === startOffset) { - buffer = bufferAfter; - } - buffer.push(FreeTextEditor.#getNodeContent(child)); - } - } - this.#content = `${bufferBefore.join("\n")}${paste}${bufferAfter.join("\n")}`; - this.#setContent(); - const newRange = new Range(); - let beforeLength = bufferBefore.reduce((acc, line) => acc + line.length, 0); - for (const { - firstChild - } of this.editorDiv.childNodes) { - if (firstChild.nodeType === Node.TEXT_NODE) { - const length = firstChild.nodeValue.length; - if (beforeLength <= length) { - newRange.setStart(firstChild, beforeLength); - newRange.setEnd(firstChild, beforeLength); - break; - } - beforeLength -= length; - } - } - selection.removeAllRanges(); - selection.addRange(newRange); - } - #setContent() { - this.editorDiv.replaceChildren(); - if (!this.#content) { - return; - } - for (const line of this.#content.split("\n")) { - const div = document.createElement("div"); - div.append(line ? document.createTextNode(line) : document.createElement("br")); - this.editorDiv.append(div); - } - } - #serializeContent() { - return this.#content.replaceAll("\xa0", " "); - } - static #deserializeContent(content) { - return content.replaceAll(" ", "\xa0"); - } - get contentDiv() { - return this.editorDiv; - } - static deserialize(data, parent, uiManager) { - let initialData = null; - if (data instanceof annotation_layer.FreeTextAnnotationElement) { - const { - data: { - defaultAppearanceData: { - fontSize, - fontColor - }, - rect, - rotation, - id - }, - textContent, - textPosition, - parent: { - page: { - pageNumber - } - } - } = data; - if (!textContent || textContent.length === 0) { - return null; - } - initialData = data = { - annotationType: util.AnnotationEditorType.FREETEXT, - color: Array.from(fontColor), - fontSize, - value: textContent.join("\n"), - position: textPosition, - pageIndex: pageNumber - 1, - rect: rect.slice(0), - rotation, - id, - deleted: false - }; - } - const editor = super.deserialize(data, parent, uiManager); - editor.#fontSize = data.fontSize; - editor.#color = util.Util.makeHexColor(...data.color); - editor.#content = FreeTextEditor.#deserializeContent(data.value); - editor.annotationElementId = data.id || null; - editor.#initialData = initialData; - return editor; - } - serialize(isForCopying = false) { - if (this.isEmpty()) { - return null; - } - if (this.deleted) { - return { - pageIndex: this.pageIndex, - id: this.annotationElementId, - deleted: true - }; - } - const padding = FreeTextEditor._internalPadding * this.parentScale; - const rect = this.getRect(padding, padding); - const color = editor_editor.AnnotationEditor._colorManager.convert(this.isAttachedToDOM ? getComputedStyle(this.editorDiv).color : this.#color); - const serialized = { - annotationType: util.AnnotationEditorType.FREETEXT, - color, - fontSize: this.#fontSize, - value: this.#serializeContent(), - pageIndex: this.pageIndex, - rect, - rotation: this.rotation, - structTreeParentId: this._structTreeParentId - }; - if (isForCopying) { - return serialized; - } - if (this.annotationElementId && !this.#hasElementChanged(serialized)) { - return null; - } - serialized.id = this.annotationElementId; - return serialized; - } - #hasElementChanged(serialized) { - const { - value, - fontSize, - color, - pageIndex - } = this.#initialData; - return this._hasBeenMoved || serialized.value !== value || serialized.fontSize !== fontSize || serialized.color.some((c, i) => c !== color[i]) || serialized.pageIndex !== pageIndex; - } - renderAnnotationElement(annotation) { - const content = super.renderAnnotationElement(annotation); - if (this.deleted) { - return content; - } - const { - style - } = content; - style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`; - style.color = this.#color; - content.replaceChildren(); - for (const line of this.#content.split("\n")) { - const div = document.createElement("div"); - div.append(line ? document.createTextNode(line) : document.createElement("br")); - content.append(div); - } - const padding = FreeTextEditor._internalPadding * this.parentScale; - annotation.updateEdited({ - rect: this.getRect(padding, padding) - }); - return content; - } - resetAnnotationElement(annotation) { - super.resetAnnotationElement(annotation); - annotation.resetEdited(); - } -} - -// EXTERNAL MODULE: ./src/display/editor/outliner.js -var editor_outliner = __webpack_require__(61); -// EXTERNAL MODULE: ./src/display/editor/color_picker.js -var color_picker = __webpack_require__(259); -// EXTERNAL MODULE: ./src/display/display_utils.js -var display_utils = __webpack_require__(419); -;// CONCATENATED MODULE: ./src/display/editor/highlight.js - - - - - - -class HighlightEditor extends editor_editor.AnnotationEditor { - #anchorNode = null; - #anchorOffset = 0; - #boxes; - #clipPathId = null; - #colorPicker = null; - #focusOutlines = null; - #focusNode = null; - #focusOffset = 0; - #highlightDiv = null; - #highlightOutlines = null; - #id = null; - #isFreeHighlight = false; - #boundKeydown = this.#keydown.bind(this); - #lastPoint = null; - #opacity; - #outlineId = null; - #text = ""; - #thickness; - #methodOfCreation = ""; - static _defaultColor = null; - static _defaultOpacity = 1; - static _defaultThickness = 12; - static _l10nPromise; - static _type = "highlight"; - static _editorType = util.AnnotationEditorType.HIGHLIGHT; - static _freeHighlightId = -1; - static _freeHighlight = null; - static _freeHighlightClipId = ""; - static get _keyboardManager() { - const proto = HighlightEditor.prototype; - return (0,util.shadow)(this, "_keyboardManager", new tools.KeyboardManager([[["ArrowLeft", "mac+ArrowLeft"], proto._moveCaret, { - args: [0] - }], [["ArrowRight", "mac+ArrowRight"], proto._moveCaret, { - args: [1] - }], [["ArrowUp", "mac+ArrowUp"], proto._moveCaret, { - args: [2] - }], [["ArrowDown", "mac+ArrowDown"], proto._moveCaret, { - args: [3] - }]])); - } - constructor(params) { - super({ - ...params, - name: "highlightEditor" - }); - this.color = params.color || HighlightEditor._defaultColor; - this.#thickness = params.thickness || HighlightEditor._defaultThickness; - this.#opacity = params.opacity || HighlightEditor._defaultOpacity; - this.#boxes = params.boxes || null; - this.#methodOfCreation = params.methodOfCreation || ""; - this.#text = params.text || ""; - this._isDraggable = false; - if (params.highlightId > -1) { - this.#isFreeHighlight = true; - this.#createFreeOutlines(params); - this.#addToDrawLayer(); - } else { - this.#anchorNode = params.anchorNode; - this.#anchorOffset = params.anchorOffset; - this.#focusNode = params.focusNode; - this.#focusOffset = params.focusOffset; - this.#createOutlines(); - this.#addToDrawLayer(); - this.rotate(this.rotation); - } - } - get telemetryInitialData() { - return { - action: "added", - type: this.#isFreeHighlight ? "free_highlight" : "highlight", - color: this._uiManager.highlightColorNames.get(this.color), - thickness: this.#thickness, - methodOfCreation: this.#methodOfCreation - }; - } - get telemetryFinalData() { - return { - type: "highlight", - color: this._uiManager.highlightColorNames.get(this.color) - }; - } - static computeTelemetryFinalData(data) { - return { - numberOfColors: data.get("color").size - }; - } - #createOutlines() { - const outliner = new editor_outliner.Outliner(this.#boxes, 0.001); - this.#highlightOutlines = outliner.getOutlines(); - ({ - x: this.x, - y: this.y, - width: this.width, - height: this.height - } = this.#highlightOutlines.box); - const outlinerForOutline = new editor_outliner.Outliner(this.#boxes, 0.0025, 0.001, this._uiManager.direction === "ltr"); - this.#focusOutlines = outlinerForOutline.getOutlines(); - const { - lastPoint - } = this.#focusOutlines.box; - this.#lastPoint = [(lastPoint[0] - this.x) / this.width, (lastPoint[1] - this.y) / this.height]; - } - #createFreeOutlines({ - highlightOutlines, - highlightId, - clipPathId - }) { - this.#highlightOutlines = highlightOutlines; - const extraThickness = 1.5; - this.#focusOutlines = highlightOutlines.getNewOutline(this.#thickness / 2 + extraThickness, 0.0025); - if (highlightId >= 0) { - this.#id = highlightId; - this.#clipPathId = clipPathId; - this.parent.drawLayer.finalizeLine(highlightId, highlightOutlines); - this.#outlineId = this.parent.drawLayer.highlightOutline(this.#focusOutlines); - } else if (this.parent) { - const angle = this.parent.viewport.rotation; - this.parent.drawLayer.updateLine(this.#id, highlightOutlines); - this.parent.drawLayer.updateBox(this.#id, HighlightEditor.#rotateBbox(this.#highlightOutlines.box, (angle - this.rotation + 360) % 360)); - this.parent.drawLayer.updateLine(this.#outlineId, this.#focusOutlines); - this.parent.drawLayer.updateBox(this.#outlineId, HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle)); - } - const { - x, - y, - width, - height - } = highlightOutlines.box; - switch (this.rotation) { - case 0: - this.x = x; - this.y = y; - this.width = width; - this.height = height; - break; - case 90: - { - const [pageWidth, pageHeight] = this.parentDimensions; - this.x = y; - this.y = 1 - x; - this.width = width * pageHeight / pageWidth; - this.height = height * pageWidth / pageHeight; - break; - } - case 180: - this.x = 1 - x; - this.y = 1 - y; - this.width = width; - this.height = height; - break; - case 270: - { - const [pageWidth, pageHeight] = this.parentDimensions; - this.x = 1 - y; - this.y = x; - this.width = width * pageHeight / pageWidth; - this.height = height * pageWidth / pageHeight; - break; - } - } - const { - lastPoint - } = this.#focusOutlines.box; - this.#lastPoint = [(lastPoint[0] - x) / width, (lastPoint[1] - y) / height]; - } - static initialize(l10n, uiManager) { - editor_editor.AnnotationEditor.initialize(l10n, uiManager); - HighlightEditor._defaultColor ||= uiManager.highlightColors?.values().next().value || "#fff066"; - } - static updateDefaultParams(type, value) { - switch (type) { - case util.AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR: - HighlightEditor._defaultColor = value; - break; - case util.AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: - HighlightEditor._defaultThickness = value; - break; - } - } - translateInPage(x, y) {} - get toolbarPosition() { - return this.#lastPoint; - } - updateParams(type, value) { - switch (type) { - case util.AnnotationEditorParamsType.HIGHLIGHT_COLOR: - this.#updateColor(value); - break; - case util.AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: - this.#updateThickness(value); - break; - } - } - static get defaultPropertiesToUpdate() { - return [[util.AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR, HighlightEditor._defaultColor], [util.AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, HighlightEditor._defaultThickness]]; - } - get propertiesToUpdate() { - return [[util.AnnotationEditorParamsType.HIGHLIGHT_COLOR, this.color || HighlightEditor._defaultColor], [util.AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, this.#thickness || HighlightEditor._defaultThickness], [util.AnnotationEditorParamsType.HIGHLIGHT_FREE, this.#isFreeHighlight]]; - } - #updateColor(color) { - const setColor = col => { - this.color = col; - this.parent?.drawLayer.changeColor(this.#id, col); - this.#colorPicker?.updateColor(col); - }; - const savedColor = this.color; - this.addCommands({ - cmd: setColor.bind(this, color), - undo: setColor.bind(this, savedColor), - post: this._uiManager.updateUI.bind(this._uiManager, this), - mustExec: true, - type: util.AnnotationEditorParamsType.HIGHLIGHT_COLOR, - overwriteIfSameType: true, - keepUndo: true - }); - this._reportTelemetry({ - action: "color_changed", - color: this._uiManager.highlightColorNames.get(color) - }, true); - } - #updateThickness(thickness) { - const savedThickness = this.#thickness; - const setThickness = th => { - this.#thickness = th; - this.#changeThickness(th); - }; - this.addCommands({ - cmd: setThickness.bind(this, thickness), - undo: setThickness.bind(this, savedThickness), - post: this._uiManager.updateUI.bind(this._uiManager, this), - mustExec: true, - type: util.AnnotationEditorParamsType.INK_THICKNESS, - overwriteIfSameType: true, - keepUndo: true - }); - this._reportTelemetry({ - action: "thickness_changed", - thickness - }, true); - } - async addEditToolbar() { - const toolbar = await super.addEditToolbar(); - if (!toolbar) { - return null; - } - if (this._uiManager.highlightColors) { - this.#colorPicker = new color_picker.ColorPicker({ - editor: this - }); - toolbar.addColorPicker(this.#colorPicker); - } - return toolbar; - } - disableEditing() { - super.disableEditing(); - this.div.classList.toggle("disabled", true); - } - enableEditing() { - super.enableEditing(); - this.div.classList.toggle("disabled", false); - } - fixAndSetPosition() { - return super.fixAndSetPosition(this.#getRotation()); - } - getBaseTranslation() { - return [0, 0]; - } - getRect(tx, ty) { - return super.getRect(tx, ty, this.#getRotation()); - } - onceAdded() { - this.parent.addUndoableEditor(this); - this.div.focus(); - } - remove() { - this.#cleanDrawLayer(); - this._reportTelemetry({ - action: "deleted" - }); - super.remove(); - } - rebuild() { - if (!this.parent) { - return; - } - super.rebuild(); - if (this.div === null) { - return; - } - this.#addToDrawLayer(); - if (!this.isAttachedToDOM) { - this.parent.add(this); - } - } - setParent(parent) { - let mustBeSelected = false; - if (this.parent && !parent) { - this.#cleanDrawLayer(); - } else if (parent) { - this.#addToDrawLayer(parent); - mustBeSelected = !this.parent && this.div?.classList.contains("selectedEditor"); - } - super.setParent(parent); - this.show(this._isVisible); - if (mustBeSelected) { - this.select(); - } - } - #changeThickness(thickness) { - if (!this.#isFreeHighlight) { - return; - } - this.#createFreeOutlines({ - highlightOutlines: this.#highlightOutlines.getNewOutline(thickness / 2) - }); - this.fixAndSetPosition(); - const [parentWidth, parentHeight] = this.parentDimensions; - this.setDims(this.width * parentWidth, this.height * parentHeight); - } - #cleanDrawLayer() { - if (this.#id === null || !this.parent) { - return; - } - this.parent.drawLayer.remove(this.#id); - this.#id = null; - this.parent.drawLayer.remove(this.#outlineId); - this.#outlineId = null; - } - #addToDrawLayer(parent = this.parent) { - if (this.#id !== null) { - return; - } - ({ - id: this.#id, - clipPathId: this.#clipPathId - } = parent.drawLayer.highlight(this.#highlightOutlines, this.color, this.#opacity)); - this.#outlineId = parent.drawLayer.highlightOutline(this.#focusOutlines); - if (this.#highlightDiv) { - this.#highlightDiv.style.clipPath = this.#clipPathId; - } - } - static #rotateBbox({ - x, - y, - width, - height - }, angle) { - switch (angle) { - case 90: - return { - x: 1 - y - height, - y: x, - width: height, - height: width - }; - case 180: - return { - x: 1 - x - width, - y: 1 - y - height, - width, - height - }; - case 270: - return { - x: y, - y: 1 - x - width, - width: height, - height: width - }; - } - return { - x, - y, - width, - height - }; - } - rotate(angle) { - const { - drawLayer - } = this.parent; - let box; - if (this.#isFreeHighlight) { - angle = (angle - this.rotation + 360) % 360; - box = HighlightEditor.#rotateBbox(this.#highlightOutlines.box, angle); - } else { - box = HighlightEditor.#rotateBbox(this, angle); - } - drawLayer.rotate(this.#id, angle); - drawLayer.rotate(this.#outlineId, angle); - drawLayer.updateBox(this.#id, box); - drawLayer.updateBox(this.#outlineId, HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle)); - } - render() { - if (this.div) { - return this.div; - } - const div = super.render(); - if (this.#text) { - div.setAttribute("aria-label", this.#text); - div.setAttribute("role", "mark"); - } - if (this.#isFreeHighlight) { - div.classList.add("free"); - } else { - this.div.addEventListener("keydown", this.#boundKeydown); - } - const highlightDiv = this.#highlightDiv = document.createElement("div"); - div.append(highlightDiv); - highlightDiv.setAttribute("aria-hidden", "true"); - highlightDiv.className = "internal"; - highlightDiv.style.clipPath = this.#clipPathId; - const [parentWidth, parentHeight] = this.parentDimensions; - this.setDims(this.width * parentWidth, this.height * parentHeight); - (0,tools.bindEvents)(this, this.#highlightDiv, ["pointerover", "pointerleave"]); - this.enableEditing(); - return div; - } - pointerover() { - this.parent.drawLayer.addClass(this.#outlineId, "hovered"); - } - pointerleave() { - this.parent.drawLayer.removeClass(this.#outlineId, "hovered"); - } - #keydown(event) { - HighlightEditor._keyboardManager.exec(this, event); - } - _moveCaret(direction) { - this.parent.unselect(this); - switch (direction) { - case 0: - case 2: - this.#setCaret(true); - break; - case 1: - case 3: - this.#setCaret(false); - break; - } - } - #setCaret(start) { - if (!this.#anchorNode) { - return; - } - const selection = window.getSelection(); - if (start) { - selection.setPosition(this.#anchorNode, this.#anchorOffset); - } else { - selection.setPosition(this.#focusNode, this.#focusOffset); - } - } - select() { - super.select(); - if (!this.#outlineId) { - return; - } - this.parent?.drawLayer.removeClass(this.#outlineId, "hovered"); - this.parent?.drawLayer.addClass(this.#outlineId, "selected"); - } - unselect() { - super.unselect(); - if (!this.#outlineId) { - return; - } - this.parent?.drawLayer.removeClass(this.#outlineId, "selected"); - if (!this.#isFreeHighlight) { - this.#setCaret(false); - } - } - get _mustFixPosition() { - return !this.#isFreeHighlight; - } - show(visible = this._isVisible) { - super.show(visible); - if (this.parent) { - this.parent.drawLayer.show(this.#id, visible); - this.parent.drawLayer.show(this.#outlineId, visible); - } - } - #getRotation() { - return this.#isFreeHighlight ? this.rotation : 0; - } - #serializeBoxes() { - if (this.#isFreeHighlight) { - return null; - } - const [pageWidth, pageHeight] = this.pageDimensions; - const boxes = this.#boxes; - const quadPoints = new Array(boxes.length * 8); - let i = 0; - for (const { - x, - y, - width, - height - } of boxes) { - const sx = x * pageWidth; - const sy = (1 - y - height) * pageHeight; - quadPoints[i] = quadPoints[i + 4] = sx; - quadPoints[i + 1] = quadPoints[i + 3] = sy; - quadPoints[i + 2] = quadPoints[i + 6] = sx + width * pageWidth; - quadPoints[i + 5] = quadPoints[i + 7] = sy + height * pageHeight; - i += 8; - } - return quadPoints; - } - #serializeOutlines(rect) { - return this.#highlightOutlines.serialize(rect, this.#getRotation()); - } - static startHighlighting(parent, isLTR, { - target: textLayer, - x, - y - }) { - const { - x: layerX, - y: layerY, - width: parentWidth, - height: parentHeight - } = textLayer.getBoundingClientRect(); - const pointerMove = e => { - this.#highlightMove(parent, e); - }; - const pointerDownOptions = { - capture: true, - passive: false - }; - const pointerDown = e => { - e.preventDefault(); - e.stopPropagation(); - }; - const pointerUpCallback = e => { - textLayer.removeEventListener("pointermove", pointerMove); - window.removeEventListener("blur", pointerUpCallback); - window.removeEventListener("pointerup", pointerUpCallback); - window.removeEventListener("pointerdown", pointerDown, pointerDownOptions); - window.removeEventListener("contextmenu", display_utils.noContextMenu); - this.#endHighlight(parent, e); - }; - window.addEventListener("blur", pointerUpCallback); - window.addEventListener("pointerup", pointerUpCallback); - window.addEventListener("pointerdown", pointerDown, pointerDownOptions); - window.addEventListener("contextmenu", display_utils.noContextMenu); - textLayer.addEventListener("pointermove", pointerMove); - this._freeHighlight = new editor_outliner.FreeOutliner({ - x, - y - }, [layerX, layerY, parentWidth, parentHeight], parent.scale, this._defaultThickness / 2, isLTR, 0.001); - ({ - id: this._freeHighlightId, - clipPathId: this._freeHighlightClipId - } = parent.drawLayer.highlight(this._freeHighlight, this._defaultColor, this._defaultOpacity, true)); - } - static #highlightMove(parent, event) { - if (this._freeHighlight.add(event)) { - parent.drawLayer.updatePath(this._freeHighlightId, this._freeHighlight); - } - } - static #endHighlight(parent, event) { - if (!this._freeHighlight.isEmpty()) { - parent.createAndAddNewEditor(event, false, { - highlightId: this._freeHighlightId, - highlightOutlines: this._freeHighlight.getOutlines(), - clipPathId: this._freeHighlightClipId, - methodOfCreation: "main_toolbar" - }); - } else { - parent.drawLayer.removeFreeHighlight(this._freeHighlightId); - } - this._freeHighlightId = -1; - this._freeHighlight = null; - this._freeHighlightClipId = ""; - } - static deserialize(data, parent, uiManager) { - const editor = super.deserialize(data, parent, uiManager); - const { - rect: [blX, blY, trX, trY], - color, - quadPoints - } = data; - editor.color = util.Util.makeHexColor(...color); - editor.#opacity = data.opacity; - const [pageWidth, pageHeight] = editor.pageDimensions; - editor.width = (trX - blX) / pageWidth; - editor.height = (trY - blY) / pageHeight; - const boxes = editor.#boxes = []; - for (let i = 0; i < quadPoints.length; i += 8) { - boxes.push({ - x: (quadPoints[4] - trX) / pageWidth, - y: (trY - (1 - quadPoints[i + 5])) / pageHeight, - width: (quadPoints[i + 2] - quadPoints[i]) / pageWidth, - height: (quadPoints[i + 5] - quadPoints[i + 1]) / pageHeight - }); - } - editor.#createOutlines(); - return editor; - } - serialize(isForCopying = false) { - if (this.isEmpty() || isForCopying) { - return null; - } - const rect = this.getRect(0, 0); - const color = editor_editor.AnnotationEditor._colorManager.convert(this.color); - return { - annotationType: util.AnnotationEditorType.HIGHLIGHT, - color, - opacity: this.#opacity, - thickness: this.#thickness, - quadPoints: this.#serializeBoxes(), - outlines: this.#serializeOutlines(rect), - pageIndex: this.pageIndex, - rect, - rotation: this.#getRotation(), - structTreeParentId: this._structTreeParentId - }; - } - static canCreateNewEmptyEditor() { - return false; - } -} - -;// CONCATENATED MODULE: ./src/display/editor/ink.js - - - - - -class InkEditor extends editor_editor.AnnotationEditor { - #baseHeight = 0; - #baseWidth = 0; - #boundCanvasPointermove = this.canvasPointermove.bind(this); - #boundCanvasPointerleave = this.canvasPointerleave.bind(this); - #boundCanvasPointerup = this.canvasPointerup.bind(this); - #boundCanvasPointerdown = this.canvasPointerdown.bind(this); - #canvasContextMenuTimeoutId = null; - #currentPath2D = new Path2D(); - #disableEditing = false; - #hasSomethingToDraw = false; - #isCanvasInitialized = false; - #observer = null; - #realWidth = 0; - #realHeight = 0; - #requestFrameCallback = null; - static _defaultColor = null; - static _defaultOpacity = 1; - static _defaultThickness = 1; - static _type = "ink"; - static _editorType = util.AnnotationEditorType.INK; - constructor(params) { - super({ - ...params, - name: "inkEditor" - }); - this.color = params.color || null; - this.thickness = params.thickness || null; - this.opacity = params.opacity || null; - this.paths = []; - this.bezierPath2D = []; - this.allRawPaths = []; - this.currentPath = []; - this.scaleFactor = 1; - this.translationX = this.translationY = 0; - this.x = 0; - this.y = 0; - this._willKeepAspectRatio = true; - } - static initialize(l10n, uiManager) { - editor_editor.AnnotationEditor.initialize(l10n, uiManager); - } - static updateDefaultParams(type, value) { - switch (type) { - case util.AnnotationEditorParamsType.INK_THICKNESS: - InkEditor._defaultThickness = value; - break; - case util.AnnotationEditorParamsType.INK_COLOR: - InkEditor._defaultColor = value; - break; - case util.AnnotationEditorParamsType.INK_OPACITY: - InkEditor._defaultOpacity = value / 100; - break; - } - } - updateParams(type, value) { - switch (type) { - case util.AnnotationEditorParamsType.INK_THICKNESS: - this.#updateThickness(value); - break; - case util.AnnotationEditorParamsType.INK_COLOR: - this.#updateColor(value); - break; - case util.AnnotationEditorParamsType.INK_OPACITY: - this.#updateOpacity(value); - break; - } - } - static get defaultPropertiesToUpdate() { - return [[util.AnnotationEditorParamsType.INK_THICKNESS, InkEditor._defaultThickness], [util.AnnotationEditorParamsType.INK_COLOR, InkEditor._defaultColor || editor_editor.AnnotationEditor._defaultLineColor], [util.AnnotationEditorParamsType.INK_OPACITY, Math.round(InkEditor._defaultOpacity * 100)]]; - } - get propertiesToUpdate() { - return [[util.AnnotationEditorParamsType.INK_THICKNESS, this.thickness || InkEditor._defaultThickness], [util.AnnotationEditorParamsType.INK_COLOR, this.color || InkEditor._defaultColor || editor_editor.AnnotationEditor._defaultLineColor], [util.AnnotationEditorParamsType.INK_OPACITY, Math.round(100 * (this.opacity ?? InkEditor._defaultOpacity))]]; - } - #updateThickness(thickness) { - const setThickness = th => { - this.thickness = th; - this.#fitToContent(); - }; - const savedThickness = this.thickness; - this.addCommands({ - cmd: setThickness.bind(this, thickness), - undo: setThickness.bind(this, savedThickness), - post: this._uiManager.updateUI.bind(this._uiManager, this), - mustExec: true, - type: util.AnnotationEditorParamsType.INK_THICKNESS, - overwriteIfSameType: true, - keepUndo: true - }); - } - #updateColor(color) { - const setColor = col => { - this.color = col; - this.#redraw(); - }; - const savedColor = this.color; - this.addCommands({ - cmd: setColor.bind(this, color), - undo: setColor.bind(this, savedColor), - post: this._uiManager.updateUI.bind(this._uiManager, this), - mustExec: true, - type: util.AnnotationEditorParamsType.INK_COLOR, - overwriteIfSameType: true, - keepUndo: true - }); - } - #updateOpacity(opacity) { - const setOpacity = op => { - this.opacity = op; - this.#redraw(); - }; - opacity /= 100; - const savedOpacity = this.opacity; - this.addCommands({ - cmd: setOpacity.bind(this, opacity), - undo: setOpacity.bind(this, savedOpacity), - post: this._uiManager.updateUI.bind(this._uiManager, this), - mustExec: true, - type: util.AnnotationEditorParamsType.INK_OPACITY, - overwriteIfSameType: true, - keepUndo: true - }); - } - rebuild() { - if (!this.parent) { - return; - } - super.rebuild(); - if (this.div === null) { - return; - } - if (!this.canvas) { - this.#createCanvas(); - this.#createObserver(); - } - if (!this.isAttachedToDOM) { - this.parent.add(this); - this.#setCanvasDims(); - } - this.#fitToContent(); - } - remove() { - if (this.canvas === null) { - return; - } - if (!this.isEmpty()) { - this.commit(); - } - this.canvas.width = this.canvas.height = 0; - this.canvas.remove(); - this.canvas = null; - if (this.#canvasContextMenuTimeoutId) { - clearTimeout(this.#canvasContextMenuTimeoutId); - this.#canvasContextMenuTimeoutId = null; - } - this.#observer.disconnect(); - this.#observer = null; - super.remove(); - } - setParent(parent) { - if (!this.parent && parent) { - this._uiManager.removeShouldRescale(this); - } else if (this.parent && parent === null) { - this._uiManager.addShouldRescale(this); - } - super.setParent(parent); - } - onScaleChanging() { - const [parentWidth, parentHeight] = this.parentDimensions; - const width = this.width * parentWidth; - const height = this.height * parentHeight; - this.setDimensions(width, height); - } - enableEditMode() { - if (this.#disableEditing || this.canvas === null) { - return; - } - super.enableEditMode(); - this._isDraggable = false; - this.canvas.addEventListener("pointerdown", this.#boundCanvasPointerdown); - } - disableEditMode() { - if (!this.isInEditMode() || this.canvas === null) { - return; - } - super.disableEditMode(); - this._isDraggable = !this.isEmpty(); - this.div.classList.remove("editing"); - this.canvas.removeEventListener("pointerdown", this.#boundCanvasPointerdown); - } - onceAdded() { - this._isDraggable = !this.isEmpty(); - } - isEmpty() { - return this.paths.length === 0 || this.paths.length === 1 && this.paths[0].length === 0; - } - #getInitialBBox() { - const { - parentRotation, - parentDimensions: [width, height] - } = this; - switch (parentRotation) { - case 90: - return [0, height, height, width]; - case 180: - return [width, height, width, height]; - case 270: - return [width, 0, height, width]; - default: - return [0, 0, width, height]; - } - } - #setStroke() { - const { - ctx, - color, - opacity, - thickness, - parentScale, - scaleFactor - } = this; - ctx.lineWidth = thickness * parentScale / scaleFactor; - ctx.lineCap = "round"; - ctx.lineJoin = "round"; - ctx.miterLimit = 10; - ctx.strokeStyle = `${color}${(0,tools.opacityToHex)(opacity)}`; - } - #startDrawing(x, y) { - this.canvas.addEventListener("contextmenu", display_utils.noContextMenu); - this.canvas.addEventListener("pointerleave", this.#boundCanvasPointerleave); - this.canvas.addEventListener("pointermove", this.#boundCanvasPointermove); - this.canvas.addEventListener("pointerup", this.#boundCanvasPointerup); - this.canvas.removeEventListener("pointerdown", this.#boundCanvasPointerdown); - this.isEditing = true; - if (!this.#isCanvasInitialized) { - this.#isCanvasInitialized = true; - this.#setCanvasDims(); - this.thickness ||= InkEditor._defaultThickness; - this.color ||= InkEditor._defaultColor || editor_editor.AnnotationEditor._defaultLineColor; - this.opacity ??= InkEditor._defaultOpacity; - } - this.currentPath.push([x, y]); - this.#hasSomethingToDraw = false; - this.#setStroke(); - this.#requestFrameCallback = () => { - this.#drawPoints(); - if (this.#requestFrameCallback) { - window.requestAnimationFrame(this.#requestFrameCallback); - } - }; - window.requestAnimationFrame(this.#requestFrameCallback); - } - #draw(x, y) { - const [lastX, lastY] = this.currentPath.at(-1); - if (this.currentPath.length > 1 && x === lastX && y === lastY) { - return; - } - const currentPath = this.currentPath; - let path2D = this.#currentPath2D; - currentPath.push([x, y]); - this.#hasSomethingToDraw = true; - if (currentPath.length <= 2) { - path2D.moveTo(...currentPath[0]); - path2D.lineTo(x, y); - return; - } - if (currentPath.length === 3) { - this.#currentPath2D = path2D = new Path2D(); - path2D.moveTo(...currentPath[0]); - } - this.#makeBezierCurve(path2D, ...currentPath.at(-3), ...currentPath.at(-2), x, y); - } - #endPath() { - if (this.currentPath.length === 0) { - return; - } - const lastPoint = this.currentPath.at(-1); - this.#currentPath2D.lineTo(...lastPoint); - } - #stopDrawing(x, y) { - this.#requestFrameCallback = null; - x = Math.min(Math.max(x, 0), this.canvas.width); - y = Math.min(Math.max(y, 0), this.canvas.height); - this.#draw(x, y); - this.#endPath(); - let bezier; - if (this.currentPath.length !== 1) { - bezier = this.#generateBezierPoints(); - } else { - const xy = [x, y]; - bezier = [[xy, xy.slice(), xy.slice(), xy]]; - } - const path2D = this.#currentPath2D; - const currentPath = this.currentPath; - this.currentPath = []; - this.#currentPath2D = new Path2D(); - const cmd = () => { - this.allRawPaths.push(currentPath); - this.paths.push(bezier); - this.bezierPath2D.push(path2D); - this._uiManager.rebuild(this); - }; - const undo = () => { - this.allRawPaths.pop(); - this.paths.pop(); - this.bezierPath2D.pop(); - if (this.paths.length === 0) { - this.remove(); - } else { - if (!this.canvas) { - this.#createCanvas(); - this.#createObserver(); - } - this.#fitToContent(); - } - }; - this.addCommands({ - cmd, - undo, - mustExec: true - }); - } - #drawPoints() { - if (!this.#hasSomethingToDraw) { - return; - } - this.#hasSomethingToDraw = false; - const thickness = Math.ceil(this.thickness * this.parentScale); - const lastPoints = this.currentPath.slice(-3); - const x = lastPoints.map(xy => xy[0]); - const y = lastPoints.map(xy => xy[1]); - const xMin = Math.min(...x) - thickness; - const xMax = Math.max(...x) + thickness; - const yMin = Math.min(...y) - thickness; - const yMax = Math.max(...y) + thickness; - const { - ctx - } = this; - ctx.save(); - ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); - for (const path of this.bezierPath2D) { - ctx.stroke(path); - } - ctx.stroke(this.#currentPath2D); - ctx.restore(); - } - #makeBezierCurve(path2D, x0, y0, x1, y1, x2, y2) { - const prevX = (x0 + x1) / 2; - const prevY = (y0 + y1) / 2; - const x3 = (x1 + x2) / 2; - const y3 = (y1 + y2) / 2; - path2D.bezierCurveTo(prevX + 2 * (x1 - prevX) / 3, prevY + 2 * (y1 - prevY) / 3, x3 + 2 * (x1 - x3) / 3, y3 + 2 * (y1 - y3) / 3, x3, y3); - } - #generateBezierPoints() { - const path = this.currentPath; - if (path.length <= 2) { - return [[path[0], path[0], path.at(-1), path.at(-1)]]; - } - const bezierPoints = []; - let i; - let [x0, y0] = path[0]; - for (i = 1; i < path.length - 2; i++) { - const [x1, y1] = path[i]; - const [x2, y2] = path[i + 1]; - const x3 = (x1 + x2) / 2; - const y3 = (y1 + y2) / 2; - const control1 = [x0 + 2 * (x1 - x0) / 3, y0 + 2 * (y1 - y0) / 3]; - const control2 = [x3 + 2 * (x1 - x3) / 3, y3 + 2 * (y1 - y3) / 3]; - bezierPoints.push([[x0, y0], control1, control2, [x3, y3]]); - [x0, y0] = [x3, y3]; - } - const [x1, y1] = path[i]; - const [x2, y2] = path[i + 1]; - const control1 = [x0 + 2 * (x1 - x0) / 3, y0 + 2 * (y1 - y0) / 3]; - const control2 = [x2 + 2 * (x1 - x2) / 3, y2 + 2 * (y1 - y2) / 3]; - bezierPoints.push([[x0, y0], control1, control2, [x2, y2]]); - return bezierPoints; - } - #redraw() { - if (this.isEmpty()) { - this.#updateTransform(); - return; - } - this.#setStroke(); - const { - canvas, - ctx - } = this; - ctx.setTransform(1, 0, 0, 1, 0, 0); - ctx.clearRect(0, 0, canvas.width, canvas.height); - this.#updateTransform(); - for (const path of this.bezierPath2D) { - ctx.stroke(path); - } - } - commit() { - if (this.#disableEditing) { - return; - } - super.commit(); - this.isEditing = false; - this.disableEditMode(); - this.setInForeground(); - this.#disableEditing = true; - this.div.classList.add("disabled"); - this.#fitToContent(true); - this.select(); - this.parent.addInkEditorIfNeeded(true); - this.moveInDOM(); - this.div.focus({ - preventScroll: true - }); - } - focusin(event) { - if (!this._focusEventsAllowed) { - return; - } - super.focusin(event); - this.enableEditMode(); - } - canvasPointerdown(event) { - if (event.button !== 0 || !this.isInEditMode() || this.#disableEditing) { - return; - } - this.setInForeground(); - event.preventDefault(); - if (!this.div.contains(document.activeElement)) { - this.div.focus({ - preventScroll: true - }); - } - this.#startDrawing(event.offsetX, event.offsetY); - } - canvasPointermove(event) { - event.preventDefault(); - this.#draw(event.offsetX, event.offsetY); - } - canvasPointerup(event) { - event.preventDefault(); - this.#endDrawing(event); - } - canvasPointerleave(event) { - this.#endDrawing(event); - } - #endDrawing(event) { - this.canvas.removeEventListener("pointerleave", this.#boundCanvasPointerleave); - this.canvas.removeEventListener("pointermove", this.#boundCanvasPointermove); - this.canvas.removeEventListener("pointerup", this.#boundCanvasPointerup); - this.canvas.addEventListener("pointerdown", this.#boundCanvasPointerdown); - if (this.#canvasContextMenuTimeoutId) { - clearTimeout(this.#canvasContextMenuTimeoutId); - } - this.#canvasContextMenuTimeoutId = setTimeout(() => { - this.#canvasContextMenuTimeoutId = null; - this.canvas.removeEventListener("contextmenu", display_utils.noContextMenu); - }, 10); - this.#stopDrawing(event.offsetX, event.offsetY); - this.addToAnnotationStorage(); - this.setInBackground(); - } - #createCanvas() { - this.canvas = document.createElement("canvas"); - this.canvas.width = this.canvas.height = 0; - this.canvas.className = "inkEditorCanvas"; - this.canvas.setAttribute("data-l10n-id", "pdfjs-ink-canvas"); - this.div.append(this.canvas); - this.ctx = this.canvas.getContext("2d"); - } - #createObserver() { - this.#observer = new ResizeObserver(entries => { - const rect = entries[0].contentRect; - if (rect.width && rect.height) { - this.setDimensions(rect.width, rect.height); - } - }); - this.#observer.observe(this.div); - } - get isResizable() { - return !this.isEmpty() && this.#disableEditing; - } - render() { - if (this.div) { - return this.div; - } - let baseX, baseY; - if (this.width) { - baseX = this.x; - baseY = this.y; - } - super.render(); - this.div.setAttribute("data-l10n-id", "pdfjs-ink"); - const [x, y, w, h] = this.#getInitialBBox(); - this.setAt(x, y, 0, 0); - this.setDims(w, h); - this.#createCanvas(); - if (this.width) { - const [parentWidth, parentHeight] = this.parentDimensions; - this.setAspectRatio(this.width * parentWidth, this.height * parentHeight); - this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight); - this.#isCanvasInitialized = true; - this.#setCanvasDims(); - this.setDims(this.width * parentWidth, this.height * parentHeight); - this.#redraw(); - this.div.classList.add("disabled"); - } else { - this.div.classList.add("editing"); - this.enableEditMode(); - } - this.#createObserver(); - return this.div; - } - #setCanvasDims() { - if (!this.#isCanvasInitialized) { - return; - } - const [parentWidth, parentHeight] = this.parentDimensions; - this.canvas.width = Math.ceil(this.width * parentWidth); - this.canvas.height = Math.ceil(this.height * parentHeight); - this.#updateTransform(); - } - setDimensions(width, height) { - const roundedWidth = Math.round(width); - const roundedHeight = Math.round(height); - if (this.#realWidth === roundedWidth && this.#realHeight === roundedHeight) { - return; - } - this.#realWidth = roundedWidth; - this.#realHeight = roundedHeight; - this.canvas.style.visibility = "hidden"; - const [parentWidth, parentHeight] = this.parentDimensions; - this.width = width / parentWidth; - this.height = height / parentHeight; - this.fixAndSetPosition(); - if (this.#disableEditing) { - this.#setScaleFactor(width, height); - } - this.#setCanvasDims(); - this.#redraw(); - this.canvas.style.visibility = "visible"; - this.fixDims(); - } - #setScaleFactor(width, height) { - const padding = this.#getPadding(); - const scaleFactorW = (width - padding) / this.#baseWidth; - const scaleFactorH = (height - padding) / this.#baseHeight; - this.scaleFactor = Math.min(scaleFactorW, scaleFactorH); - } - #updateTransform() { - const padding = this.#getPadding() / 2; - this.ctx.setTransform(this.scaleFactor, 0, 0, this.scaleFactor, this.translationX * this.scaleFactor + padding, this.translationY * this.scaleFactor + padding); - } - static #buildPath2D(bezier) { - const path2D = new Path2D(); - for (let i = 0, ii = bezier.length; i < ii; i++) { - const [first, control1, control2, second] = bezier[i]; - if (i === 0) { - path2D.moveTo(...first); - } - path2D.bezierCurveTo(control1[0], control1[1], control2[0], control2[1], second[0], second[1]); - } - return path2D; - } - static #toPDFCoordinates(points, rect, rotation) { - const [blX, blY, trX, trY] = rect; - switch (rotation) { - case 0: - for (let i = 0, ii = points.length; i < ii; i += 2) { - points[i] += blX; - points[i + 1] = trY - points[i + 1]; - } - break; - case 90: - for (let i = 0, ii = points.length; i < ii; i += 2) { - const x = points[i]; - points[i] = points[i + 1] + blX; - points[i + 1] = x + blY; - } - break; - case 180: - for (let i = 0, ii = points.length; i < ii; i += 2) { - points[i] = trX - points[i]; - points[i + 1] += blY; - } - break; - case 270: - for (let i = 0, ii = points.length; i < ii; i += 2) { - const x = points[i]; - points[i] = trX - points[i + 1]; - points[i + 1] = trY - x; - } - break; - default: - throw new Error("Invalid rotation"); - } - return points; - } - static #fromPDFCoordinates(points, rect, rotation) { - const [blX, blY, trX, trY] = rect; - switch (rotation) { - case 0: - for (let i = 0, ii = points.length; i < ii; i += 2) { - points[i] -= blX; - points[i + 1] = trY - points[i + 1]; - } - break; - case 90: - for (let i = 0, ii = points.length; i < ii; i += 2) { - const x = points[i]; - points[i] = points[i + 1] - blY; - points[i + 1] = x - blX; - } - break; - case 180: - for (let i = 0, ii = points.length; i < ii; i += 2) { - points[i] = trX - points[i]; - points[i + 1] -= blY; - } - break; - case 270: - for (let i = 0, ii = points.length; i < ii; i += 2) { - const x = points[i]; - points[i] = trY - points[i + 1]; - points[i + 1] = trX - x; - } - break; - default: - throw new Error("Invalid rotation"); - } - return points; - } - #serializePaths(s, tx, ty, rect) { - const paths = []; - const padding = this.thickness / 2; - const shiftX = s * tx + padding; - const shiftY = s * ty + padding; - for (const bezier of this.paths) { - const buffer = []; - const points = []; - for (let j = 0, jj = bezier.length; j < jj; j++) { - const [first, control1, control2, second] = bezier[j]; - if (first[0] === second[0] && first[1] === second[1] && jj === 1) { - const p0 = s * first[0] + shiftX; - const p1 = s * first[1] + shiftY; - buffer.push(p0, p1); - points.push(p0, p1); - break; - } - const p10 = s * first[0] + shiftX; - const p11 = s * first[1] + shiftY; - const p20 = s * control1[0] + shiftX; - const p21 = s * control1[1] + shiftY; - const p30 = s * control2[0] + shiftX; - const p31 = s * control2[1] + shiftY; - const p40 = s * second[0] + shiftX; - const p41 = s * second[1] + shiftY; - if (j === 0) { - buffer.push(p10, p11); - points.push(p10, p11); - } - buffer.push(p20, p21, p30, p31, p40, p41); - points.push(p20, p21); - if (j === jj - 1) { - points.push(p40, p41); - } - } - paths.push({ - bezier: InkEditor.#toPDFCoordinates(buffer, rect, this.rotation), - points: InkEditor.#toPDFCoordinates(points, rect, this.rotation) - }); - } - return paths; - } - #getBbox() { - let xMin = Infinity; - let xMax = -Infinity; - let yMin = Infinity; - let yMax = -Infinity; - for (const path of this.paths) { - for (const [first, control1, control2, second] of path) { - const bbox = util.Util.bezierBoundingBox(...first, ...control1, ...control2, ...second); - xMin = Math.min(xMin, bbox[0]); - yMin = Math.min(yMin, bbox[1]); - xMax = Math.max(xMax, bbox[2]); - yMax = Math.max(yMax, bbox[3]); - } - } - return [xMin, yMin, xMax, yMax]; - } - #getPadding() { - return this.#disableEditing ? Math.ceil(this.thickness * this.parentScale) : 0; - } - #fitToContent(firstTime = false) { - if (this.isEmpty()) { - return; - } - if (!this.#disableEditing) { - this.#redraw(); - return; - } - const bbox = this.#getBbox(); - const padding = this.#getPadding(); - this.#baseWidth = Math.max(editor_editor.AnnotationEditor.MIN_SIZE, bbox[2] - bbox[0]); - this.#baseHeight = Math.max(editor_editor.AnnotationEditor.MIN_SIZE, bbox[3] - bbox[1]); - const width = Math.ceil(padding + this.#baseWidth * this.scaleFactor); - const height = Math.ceil(padding + this.#baseHeight * this.scaleFactor); - const [parentWidth, parentHeight] = this.parentDimensions; - this.width = width / parentWidth; - this.height = height / parentHeight; - this.setAspectRatio(width, height); - const prevTranslationX = this.translationX; - const prevTranslationY = this.translationY; - this.translationX = -bbox[0]; - this.translationY = -bbox[1]; - this.#setCanvasDims(); - this.#redraw(); - this.#realWidth = width; - this.#realHeight = height; - this.setDims(width, height); - const unscaledPadding = firstTime ? padding / this.scaleFactor / 2 : 0; - this.translate(prevTranslationX - this.translationX - unscaledPadding, prevTranslationY - this.translationY - unscaledPadding); - } - static deserialize(data, parent, uiManager) { - if (data instanceof annotation_layer.InkAnnotationElement) { - return null; - } - const editor = super.deserialize(data, parent, uiManager); - editor.thickness = data.thickness; - editor.color = util.Util.makeHexColor(...data.color); - editor.opacity = data.opacity; - const [pageWidth, pageHeight] = editor.pageDimensions; - const width = editor.width * pageWidth; - const height = editor.height * pageHeight; - const scaleFactor = editor.parentScale; - const padding = data.thickness / 2; - editor.#disableEditing = true; - editor.#realWidth = Math.round(width); - editor.#realHeight = Math.round(height); - const { - paths, - rect, - rotation - } = data; - for (let { - bezier - } of paths) { - bezier = InkEditor.#fromPDFCoordinates(bezier, rect, rotation); - const path = []; - editor.paths.push(path); - let p0 = scaleFactor * (bezier[0] - padding); - let p1 = scaleFactor * (bezier[1] - padding); - for (let i = 2, ii = bezier.length; i < ii; i += 6) { - const p10 = scaleFactor * (bezier[i] - padding); - const p11 = scaleFactor * (bezier[i + 1] - padding); - const p20 = scaleFactor * (bezier[i + 2] - padding); - const p21 = scaleFactor * (bezier[i + 3] - padding); - const p30 = scaleFactor * (bezier[i + 4] - padding); - const p31 = scaleFactor * (bezier[i + 5] - padding); - path.push([[p0, p1], [p10, p11], [p20, p21], [p30, p31]]); - p0 = p30; - p1 = p31; - } - const path2D = this.#buildPath2D(path); - editor.bezierPath2D.push(path2D); - } - const bbox = editor.#getBbox(); - editor.#baseWidth = Math.max(editor_editor.AnnotationEditor.MIN_SIZE, bbox[2] - bbox[0]); - editor.#baseHeight = Math.max(editor_editor.AnnotationEditor.MIN_SIZE, bbox[3] - bbox[1]); - editor.#setScaleFactor(width, height); - return editor; - } - serialize() { - if (this.isEmpty()) { - return null; - } - const rect = this.getRect(0, 0); - const color = editor_editor.AnnotationEditor._colorManager.convert(this.ctx.strokeStyle); - return { - annotationType: util.AnnotationEditorType.INK, - color, - thickness: this.thickness, - opacity: this.opacity, - paths: this.#serializePaths(this.scaleFactor / this.parentScale, this.translationX, this.translationY, rect), - pageIndex: this.pageIndex, - rect, - rotation: this.rotation, - structTreeParentId: this._structTreeParentId - }; - } -} - -;// CONCATENATED MODULE: ./src/display/editor/stamp.js - - - - -class StampEditor extends editor_editor.AnnotationEditor { - #bitmap = null; - #bitmapId = null; - #bitmapPromise = null; - #bitmapUrl = null; - #bitmapFile = null; - #bitmapFileName = ""; - #canvas = null; - #observer = null; - #resizeTimeoutId = null; - #isSvg = false; - #hasBeenAddedInUndoStack = false; - static _type = "stamp"; - static _editorType = util.AnnotationEditorType.STAMP; - constructor(params) { - super({ - ...params, - name: "stampEditor" - }); - this.#bitmapUrl = params.bitmapUrl; - this.#bitmapFile = params.bitmapFile; - } - static initialize(l10n, uiManager) { - editor_editor.AnnotationEditor.initialize(l10n, uiManager); - } - static get supportedTypes() { - const types = ["apng", "avif", "bmp", "gif", "jpeg", "png", "svg+xml", "webp", "x-icon"]; - return (0,util.shadow)(this, "supportedTypes", types.map(type => `image/${type}`)); - } - static get supportedTypesStr() { - return (0,util.shadow)(this, "supportedTypesStr", this.supportedTypes.join(",")); - } - static isHandlingMimeForPasting(mime) { - return this.supportedTypes.includes(mime); - } - static paste(item, parent) { - parent.pasteEditor(util.AnnotationEditorType.STAMP, { - bitmapFile: item.getAsFile() - }); - } - #getBitmapFetched(data, fromId = false) { - if (!data) { - this.remove(); - return; - } - this.#bitmap = data.bitmap; - if (!fromId) { - this.#bitmapId = data.id; - this.#isSvg = data.isSvg; - } - if (data.file) { - this.#bitmapFileName = data.file.name; - } - this.#createCanvas(); - } - #getBitmapDone() { - this.#bitmapPromise = null; - this._uiManager.enableWaiting(false); - if (this.#canvas) { - this.div.focus(); - } - } - #getBitmap() { - if (this.#bitmapId) { - this._uiManager.enableWaiting(true); - this._uiManager.imageManager.getFromId(this.#bitmapId).then(data => this.#getBitmapFetched(data, true)).finally(() => this.#getBitmapDone()); - return; - } - if (this.#bitmapUrl) { - const url = this.#bitmapUrl; - this.#bitmapUrl = null; - this._uiManager.enableWaiting(true); - this.#bitmapPromise = this._uiManager.imageManager.getFromUrl(url).then(data => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone()); - return; - } - if (this.#bitmapFile) { - const file = this.#bitmapFile; - this.#bitmapFile = null; - this._uiManager.enableWaiting(true); - this.#bitmapPromise = this._uiManager.imageManager.getFromFile(file).then(data => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone()); - return; - } - const input = document.createElement("input"); - input.type = "file"; - input.accept = StampEditor.supportedTypesStr; - this.#bitmapPromise = new Promise(resolve => { - input.addEventListener("change", async () => { - if (!input.files || input.files.length === 0) { - this.remove(); - } else { - this._uiManager.enableWaiting(true); - const data = await this._uiManager.imageManager.getFromFile(input.files[0]); - this.#getBitmapFetched(data); - } - resolve(); - }); - input.addEventListener("cancel", () => { - this.remove(); - resolve(); - }); - }).finally(() => this.#getBitmapDone()); - input.click(); - } - remove() { - if (this.#bitmapId) { - this.#bitmap = null; - this._uiManager.imageManager.deleteId(this.#bitmapId); - this.#canvas?.remove(); - this.#canvas = null; - this.#observer?.disconnect(); - this.#observer = null; - if (this.#resizeTimeoutId) { - clearTimeout(this.#resizeTimeoutId); - this.#resizeTimeoutId = null; - } - } - super.remove(); - } - rebuild() { - if (!this.parent) { - if (this.#bitmapId) { - this.#getBitmap(); - } - return; - } - super.rebuild(); - if (this.div === null) { - return; - } - if (this.#bitmapId && this.#canvas === null) { - this.#getBitmap(); - } - if (!this.isAttachedToDOM) { - this.parent.add(this); - } - } - onceAdded() { - this._isDraggable = true; - this.div.focus(); - } - isEmpty() { - return !(this.#bitmapPromise || this.#bitmap || this.#bitmapUrl || this.#bitmapFile || this.#bitmapId); - } - get isResizable() { - return true; - } - render() { - if (this.div) { - return this.div; - } - let baseX, baseY; - if (this.width) { - baseX = this.x; - baseY = this.y; - } - super.render(); - this.div.hidden = true; - this.addAltTextButton(); - if (this.#bitmap) { - this.#createCanvas(); - } else { - this.#getBitmap(); - } - if (this.width) { - const [parentWidth, parentHeight] = this.parentDimensions; - this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight); - } - return this.div; - } - #createCanvas() { - const { - div - } = this; - let { - width, - height - } = this.#bitmap; - const [pageWidth, pageHeight] = this.pageDimensions; - const MAX_RATIO = 0.75; - if (this.width) { - width = this.width * pageWidth; - height = this.height * pageHeight; - } else if (width > MAX_RATIO * pageWidth || height > MAX_RATIO * pageHeight) { - const factor = Math.min(MAX_RATIO * pageWidth / width, MAX_RATIO * pageHeight / height); - width *= factor; - height *= factor; - } - const [parentWidth, parentHeight] = this.parentDimensions; - this.setDims(width * parentWidth / pageWidth, height * parentHeight / pageHeight); - this._uiManager.enableWaiting(false); - const canvas = this.#canvas = document.createElement("canvas"); - div.append(canvas); - div.hidden = false; - this.#drawBitmap(width, height); - this.#createObserver(); - if (!this.#hasBeenAddedInUndoStack) { - this.parent.addUndoableEditor(this); - this.#hasBeenAddedInUndoStack = true; - } - this._reportTelemetry({ - action: "inserted_image" - }); - if (this.#bitmapFileName) { - canvas.setAttribute("aria-label", this.#bitmapFileName); - } - } - #setDimensions(width, height) { - const [parentWidth, parentHeight] = this.parentDimensions; - this.width = width / parentWidth; - this.height = height / parentHeight; - this.setDims(width, height); - if (this._initialOptions?.isCentered) { - this.center(); - } else { - this.fixAndSetPosition(); - } - this._initialOptions = null; - if (this.#resizeTimeoutId !== null) { - clearTimeout(this.#resizeTimeoutId); - } - const TIME_TO_WAIT = 200; - this.#resizeTimeoutId = setTimeout(() => { - this.#resizeTimeoutId = null; - this.#drawBitmap(width, height); - }, TIME_TO_WAIT); - } - #scaleBitmap(width, height) { - const { - width: bitmapWidth, - height: bitmapHeight - } = this.#bitmap; - let newWidth = bitmapWidth; - let newHeight = bitmapHeight; - let bitmap = this.#bitmap; - while (newWidth > 2 * width || newHeight > 2 * height) { - const prevWidth = newWidth; - const prevHeight = newHeight; - if (newWidth > 2 * width) { - newWidth = newWidth >= 16384 ? Math.floor(newWidth / 2) - 1 : Math.ceil(newWidth / 2); - } - if (newHeight > 2 * height) { - newHeight = newHeight >= 16384 ? Math.floor(newHeight / 2) - 1 : Math.ceil(newHeight / 2); - } - const offscreen = new OffscreenCanvas(newWidth, newHeight); - const ctx = offscreen.getContext("2d"); - ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight); - bitmap = offscreen.transferToImageBitmap(); - } - return bitmap; - } - #drawBitmap(width, height) { - width = Math.ceil(width); - height = Math.ceil(height); - const canvas = this.#canvas; - if (!canvas || canvas.width === width && canvas.height === height) { - return; - } - canvas.width = width; - canvas.height = height; - const bitmap = this.#isSvg ? this.#bitmap : this.#scaleBitmap(width, height); - if (this._uiManager.hasMLManager && !this.hasAltText()) { - const offscreen = new OffscreenCanvas(width, height); - const ctx = offscreen.getContext("2d"); - ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height); - offscreen.convertToBlob().then(blob => { - const fileReader = new FileReader(); - fileReader.onload = () => { - const url = fileReader.result; - this._uiManager.mlGuess({ - service: "image-to-text", - request: { - imageData: url - } - }).then(response => { - const altText = response?.output || ""; - if (this.parent && altText && !this.hasAltText()) { - this.altTextData = { - altText, - decorative: false - }; - } - }); - }; - fileReader.readAsDataURL(blob); - }); - } - const ctx = canvas.getContext("2d"); - ctx.filter = this._uiManager.hcmFilter; - ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height); - } - getImageForAltText() { - return this.#canvas; - } - #serializeBitmap(toUrl) { - if (toUrl) { - if (this.#isSvg) { - const url = this._uiManager.imageManager.getSvgUrl(this.#bitmapId); - if (url) { - return url; - } - } - const canvas = document.createElement("canvas"); - ({ - width: canvas.width, - height: canvas.height - } = this.#bitmap); - const ctx = canvas.getContext("2d"); - ctx.drawImage(this.#bitmap, 0, 0); - return canvas.toDataURL(); - } - if (this.#isSvg) { - const [pageWidth, pageHeight] = this.pageDimensions; - const width = Math.round(this.width * pageWidth * display_utils.PixelsPerInch.PDF_TO_CSS_UNITS); - const height = Math.round(this.height * pageHeight * display_utils.PixelsPerInch.PDF_TO_CSS_UNITS); - const offscreen = new OffscreenCanvas(width, height); - const ctx = offscreen.getContext("2d"); - ctx.drawImage(this.#bitmap, 0, 0, this.#bitmap.width, this.#bitmap.height, 0, 0, width, height); - return offscreen.transferToImageBitmap(); - } - return structuredClone(this.#bitmap); - } - #createObserver() { - this.#observer = new ResizeObserver(entries => { - const rect = entries[0].contentRect; - if (rect.width && rect.height) { - this.#setDimensions(rect.width, rect.height); - } - }); - this.#observer.observe(this.div); - } - static deserialize(data, parent, uiManager) { - if (data instanceof annotation_layer.StampAnnotationElement) { - return null; - } - const editor = super.deserialize(data, parent, uiManager); - const { - rect, - bitmapUrl, - bitmapId, - isSvg, - accessibilityData - } = data; - if (bitmapId && uiManager.imageManager.isValidId(bitmapId)) { - editor.#bitmapId = bitmapId; - } else { - editor.#bitmapUrl = bitmapUrl; - } - editor.#isSvg = isSvg; - const [parentWidth, parentHeight] = editor.pageDimensions; - editor.width = (rect[2] - rect[0]) / parentWidth; - editor.height = (rect[3] - rect[1]) / parentHeight; - if (accessibilityData) { - editor.altTextData = accessibilityData; - } - return editor; - } - serialize(isForCopying = false, context = null) { - if (this.isEmpty()) { - return null; - } - const serialized = { - annotationType: util.AnnotationEditorType.STAMP, - bitmapId: this.#bitmapId, - pageIndex: this.pageIndex, - rect: this.getRect(0, 0), - rotation: this.rotation, - isSvg: this.#isSvg, - structTreeParentId: this._structTreeParentId - }; - if (isForCopying) { - serialized.bitmapUrl = this.#serializeBitmap(true); - serialized.accessibilityData = this.altTextData; - return serialized; - } - const { - decorative, - altText - } = this.altTextData; - if (!decorative && altText) { - serialized.accessibilityData = { - type: "Figure", - alt: altText - }; - } - if (context === null) { - return serialized; - } - context.stamps ||= new Map(); - const area = this.#isSvg ? (serialized.rect[2] - serialized.rect[0]) * (serialized.rect[3] - serialized.rect[1]) : null; - if (!context.stamps.has(this.#bitmapId)) { - context.stamps.set(this.#bitmapId, { - area, - serialized - }); - serialized.bitmap = this.#serializeBitmap(false); - } else if (this.#isSvg) { - const prevData = context.stamps.get(this.#bitmapId); - if (area > prevData.area) { - prevData.area = area; - prevData.serialized.bitmap.close(); - prevData.serialized.bitmap = this.#serializeBitmap(false); - } - } - return serialized; - } -} - -;// CONCATENATED MODULE: ./src/display/editor/annotation_editor_layer.js - - - - - - - -class AnnotationEditorLayer { - #accessibilityManager; - #allowClick = false; - #annotationLayer = null; - #boundPointerup = null; - #boundPointerdown = null; - #boundTextLayerPointerDown = null; - #editorFocusTimeoutId = null; - #editors = new Map(); - #hadPointerDown = false; - #isCleaningUp = false; - #isDisabling = false; - #textLayer = null; - #uiManager; - static _initialized = false; - static #editorTypes = new Map([FreeTextEditor, InkEditor, StampEditor, HighlightEditor].map(type => [type._editorType, type])); - constructor({ - uiManager, - pageIndex, - div, - accessibilityManager, - annotationLayer, - drawLayer, - textLayer, - viewport, - l10n - }) { - const editorTypes = [...AnnotationEditorLayer.#editorTypes.values()]; - if (!AnnotationEditorLayer._initialized) { - AnnotationEditorLayer._initialized = true; - for (const editorType of editorTypes) { - editorType.initialize(l10n, uiManager); - } - } - uiManager.registerEditorTypes(editorTypes); - this.#uiManager = uiManager; - this.pageIndex = pageIndex; - this.div = div; - this.#accessibilityManager = accessibilityManager; - this.#annotationLayer = annotationLayer; - this.viewport = viewport; - this.#textLayer = textLayer; - this.drawLayer = drawLayer; - this.#uiManager.addLayer(this); - } - get isEmpty() { - return this.#editors.size === 0; - } - get isInvisible() { - return this.isEmpty && this.#uiManager.getMode() === util.AnnotationEditorType.NONE; - } - updateToolbar(mode) { - this.#uiManager.updateToolbar(mode); - } - updateMode(mode = this.#uiManager.getMode()) { - this.#cleanup(); - switch (mode) { - case util.AnnotationEditorType.NONE: - this.disableTextSelection(); - this.togglePointerEvents(false); - this.toggleAnnotationLayerPointerEvents(true); - this.disableClick(); - return; - case util.AnnotationEditorType.INK: - this.addInkEditorIfNeeded(false); - this.disableTextSelection(); - this.togglePointerEvents(true); - this.disableClick(); - break; - case util.AnnotationEditorType.HIGHLIGHT: - this.enableTextSelection(); - this.togglePointerEvents(false); - this.disableClick(); - break; - default: - this.disableTextSelection(); - this.togglePointerEvents(true); - this.enableClick(); - } - this.toggleAnnotationLayerPointerEvents(false); - const { - classList - } = this.div; - for (const editorType of AnnotationEditorLayer.#editorTypes.values()) { - classList.toggle(`${editorType._type}Editing`, mode === editorType._editorType); - } - this.div.hidden = false; - } - hasTextLayer(textLayer) { - return textLayer === this.#textLayer?.div; - } - addInkEditorIfNeeded(isCommitting) { - if (this.#uiManager.getMode() !== util.AnnotationEditorType.INK) { - return; - } - if (!isCommitting) { - for (const editor of this.#editors.values()) { - if (editor.isEmpty()) { - editor.setInBackground(); - return; - } - } - } - const editor = this.createAndAddNewEditor({ - offsetX: 0, - offsetY: 0 - }, false); - editor.setInBackground(); - } - setEditingState(isEditing) { - this.#uiManager.setEditingState(isEditing); - } - addCommands(params) { - this.#uiManager.addCommands(params); - } - togglePointerEvents(enabled = false) { - this.div.classList.toggle("disabled", !enabled); - } - toggleAnnotationLayerPointerEvents(enabled = false) { - this.#annotationLayer?.div.classList.toggle("disabled", !enabled); - } - enable() { - this.div.tabIndex = 0; - this.togglePointerEvents(true); - const annotationElementIds = new Set(); - for (const editor of this.#editors.values()) { - editor.enableEditing(); - editor.show(true); - if (editor.annotationElementId) { - this.#uiManager.removeChangedExistingAnnotation(editor); - annotationElementIds.add(editor.annotationElementId); - } - } - if (!this.#annotationLayer) { - return; - } - const editables = this.#annotationLayer.getEditableAnnotations(); - for (const editable of editables) { - editable.hide(); - if (this.#uiManager.isDeletedAnnotationElement(editable.data.id)) { - continue; - } - if (annotationElementIds.has(editable.data.id)) { - continue; - } - const editor = this.deserialize(editable); - if (!editor) { - continue; - } - this.addOrRebuild(editor); - editor.enableEditing(); - } - } - disable() { - this.#isDisabling = true; - this.div.tabIndex = -1; - this.togglePointerEvents(false); - const changedAnnotations = new Map(); - const resetAnnotations = new Map(); - for (const editor of this.#editors.values()) { - editor.disableEditing(); - if (!editor.annotationElementId) { - continue; - } - if (editor.serialize() !== null) { - changedAnnotations.set(editor.annotationElementId, editor); - continue; - } else { - resetAnnotations.set(editor.annotationElementId, editor); - } - this.getEditableAnnotation(editor.annotationElementId)?.show(); - editor.remove(); - } - if (this.#annotationLayer) { - const editables = this.#annotationLayer.getEditableAnnotations(); - for (const editable of editables) { - const { - id - } = editable.data; - if (this.#uiManager.isDeletedAnnotationElement(id)) { - continue; - } - let editor = resetAnnotations.get(id); - if (editor) { - editor.resetAnnotationElement(editable); - editor.show(false); - editable.show(); - continue; - } - editor = changedAnnotations.get(id); - if (editor) { - this.#uiManager.addChangedExistingAnnotation(editor); - editor.renderAnnotationElement(editable); - editor.show(false); - } - editable.show(); - } - } - this.#cleanup(); - if (this.isEmpty) { - this.div.hidden = true; - } - const { - classList - } = this.div; - for (const editorType of AnnotationEditorLayer.#editorTypes.values()) { - classList.remove(`${editorType._type}Editing`); - } - this.disableTextSelection(); - this.toggleAnnotationLayerPointerEvents(true); - this.#isDisabling = false; - } - getEditableAnnotation(id) { - return this.#annotationLayer?.getEditableAnnotation(id) || null; - } - setActiveEditor(editor) { - const currentActive = this.#uiManager.getActive(); - if (currentActive === editor) { - return; - } - this.#uiManager.setActiveEditor(editor); - } - enableTextSelection() { - this.div.tabIndex = -1; - if (this.#textLayer?.div && !this.#boundTextLayerPointerDown) { - this.#boundTextLayerPointerDown = this.#textLayerPointerDown.bind(this); - this.#textLayer.div.addEventListener("pointerdown", this.#boundTextLayerPointerDown); - this.#textLayer.div.classList.add("highlighting"); - } - } - disableTextSelection() { - this.div.tabIndex = 0; - if (this.#textLayer?.div && this.#boundTextLayerPointerDown) { - this.#textLayer.div.removeEventListener("pointerdown", this.#boundTextLayerPointerDown); - this.#boundTextLayerPointerDown = null; - this.#textLayer.div.classList.remove("highlighting"); - } - } - #textLayerPointerDown(event) { - this.#uiManager.unselectAll(); - if (event.target === this.#textLayer.div) { - const { - isMac - } = util.FeatureTest.platform; - if (event.button !== 0 || event.ctrlKey && isMac) { - return; - } - this.#uiManager.showAllEditors("highlight", true, true); - this.#textLayer.div.classList.add("free"); - HighlightEditor.startHighlighting(this, this.#uiManager.direction === "ltr", event); - this.#textLayer.div.addEventListener("pointerup", () => { - this.#textLayer.div.classList.remove("free"); - }, { - once: true - }); - event.preventDefault(); - } - } - enableClick() { - if (this.#boundPointerdown) { - return; - } - this.#boundPointerdown = this.pointerdown.bind(this); - this.#boundPointerup = this.pointerup.bind(this); - this.div.addEventListener("pointerdown", this.#boundPointerdown); - this.div.addEventListener("pointerup", this.#boundPointerup); - } - disableClick() { - if (!this.#boundPointerdown) { - return; - } - this.div.removeEventListener("pointerdown", this.#boundPointerdown); - this.div.removeEventListener("pointerup", this.#boundPointerup); - this.#boundPointerdown = null; - this.#boundPointerup = null; - } - attach(editor) { - this.#editors.set(editor.id, editor); - const { - annotationElementId - } = editor; - if (annotationElementId && this.#uiManager.isDeletedAnnotationElement(annotationElementId)) { - this.#uiManager.removeDeletedAnnotationElement(editor); - } - } - detach(editor) { - this.#editors.delete(editor.id); - this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv); - if (!this.#isDisabling && editor.annotationElementId) { - this.#uiManager.addDeletedAnnotationElement(editor); - } - } - remove(editor) { - this.detach(editor); - this.#uiManager.removeEditor(editor); - editor.div.remove(); - editor.isAttachedToDOM = false; - if (!this.#isCleaningUp) { - this.addInkEditorIfNeeded(false); - } - } - changeParent(editor) { - if (editor.parent === this) { - return; - } - if (editor.parent && editor.annotationElementId) { - this.#uiManager.addDeletedAnnotationElement(editor.annotationElementId); - editor_editor.AnnotationEditor.deleteAnnotationElement(editor); - editor.annotationElementId = null; - } - this.attach(editor); - editor.parent?.detach(editor); - editor.setParent(this); - if (editor.div && editor.isAttachedToDOM) { - editor.div.remove(); - this.div.append(editor.div); - } - } - add(editor) { - if (editor.parent === this && editor.isAttachedToDOM) { - return; - } - this.changeParent(editor); - this.#uiManager.addEditor(editor); - this.attach(editor); - if (!editor.isAttachedToDOM) { - const div = editor.render(); - this.div.append(div); - editor.isAttachedToDOM = true; - } - editor.fixAndSetPosition(); - editor.onceAdded(); - this.#uiManager.addToAnnotationStorage(editor); - editor._reportTelemetry(editor.telemetryInitialData); - } - moveEditorInDOM(editor) { - if (!editor.isAttachedToDOM) { - return; - } - const { - activeElement - } = document; - if (editor.div.contains(activeElement) && !this.#editorFocusTimeoutId) { - editor._focusEventsAllowed = false; - this.#editorFocusTimeoutId = setTimeout(() => { - this.#editorFocusTimeoutId = null; - if (!editor.div.contains(document.activeElement)) { - editor.div.addEventListener("focusin", () => { - editor._focusEventsAllowed = true; - }, { - once: true - }); - activeElement.focus(); - } else { - editor._focusEventsAllowed = true; - } - }, 0); - } - editor._structTreeParentId = this.#accessibilityManager?.moveElementInDOM(this.div, editor.div, editor.contentDiv, true); - } - addOrRebuild(editor) { - if (editor.needsToBeRebuilt()) { - editor.parent ||= this; - editor.rebuild(); - editor.show(); - } else { - this.add(editor); - } - } - addUndoableEditor(editor) { - const cmd = () => editor._uiManager.rebuild(editor); - const undo = () => { - editor.remove(); - }; - this.addCommands({ - cmd, - undo, - mustExec: false - }); - } - getNextId() { - return this.#uiManager.getId(); - } - get #currentEditorType() { - return AnnotationEditorLayer.#editorTypes.get(this.#uiManager.getMode()); - } - #createNewEditor(params) { - const editorType = this.#currentEditorType; - return editorType ? new editorType.prototype.constructor(params) : null; - } - canCreateNewEmptyEditor() { - return this.#currentEditorType?.canCreateNewEmptyEditor(); - } - pasteEditor(mode, params) { - this.#uiManager.updateToolbar(mode); - this.#uiManager.updateMode(mode); - const { - offsetX, - offsetY - } = this.#getCenterPoint(); - const id = this.getNextId(); - const editor = this.#createNewEditor({ - parent: this, - id, - x: offsetX, - y: offsetY, - uiManager: this.#uiManager, - isCentered: true, - ...params - }); - if (editor) { - this.add(editor); - } - } - deserialize(data) { - return AnnotationEditorLayer.#editorTypes.get(data.annotationType ?? data.annotationEditorType)?.deserialize(data, this, this.#uiManager) || null; - } - createAndAddNewEditor(event, isCentered, data = {}) { - const id = this.getNextId(); - const editor = this.#createNewEditor({ - parent: this, - id, - x: event.offsetX, - y: event.offsetY, - uiManager: this.#uiManager, - isCentered, - ...data - }); - if (editor) { - this.add(editor); - } - return editor; - } - #getCenterPoint() { - const { - x, - y, - width, - height - } = this.div.getBoundingClientRect(); - const tlX = Math.max(0, x); - const tlY = Math.max(0, y); - const brX = Math.min(window.innerWidth, x + width); - const brY = Math.min(window.innerHeight, y + height); - const centerX = (tlX + brX) / 2 - x; - const centerY = (tlY + brY) / 2 - y; - const [offsetX, offsetY] = this.viewport.rotation % 180 === 0 ? [centerX, centerY] : [centerY, centerX]; - return { - offsetX, - offsetY - }; - } - addNewEditor() { - this.createAndAddNewEditor(this.#getCenterPoint(), true); - } - setSelected(editor) { - this.#uiManager.setSelected(editor); - } - toggleSelected(editor) { - this.#uiManager.toggleSelected(editor); - } - isSelected(editor) { - return this.#uiManager.isSelected(editor); - } - unselect(editor) { - this.#uiManager.unselect(editor); - } - pointerup(event) { - const { - isMac - } = util.FeatureTest.platform; - if (event.button !== 0 || event.ctrlKey && isMac) { - return; - } - if (event.target !== this.div) { - return; - } - if (!this.#hadPointerDown) { - return; - } - this.#hadPointerDown = false; - if (!this.#allowClick) { - this.#allowClick = true; - return; - } - if (this.#uiManager.getMode() === util.AnnotationEditorType.STAMP) { - this.#uiManager.unselectAll(); - return; - } - this.createAndAddNewEditor(event, false); - } - pointerdown(event) { - if (this.#uiManager.getMode() === util.AnnotationEditorType.HIGHLIGHT) { - this.enableTextSelection(); - } - if (this.#hadPointerDown) { - this.#hadPointerDown = false; - return; - } - const { - isMac - } = util.FeatureTest.platform; - if (event.button !== 0 || event.ctrlKey && isMac) { - return; - } - if (event.target !== this.div) { - return; - } - this.#hadPointerDown = true; - const editor = this.#uiManager.getActive(); - this.#allowClick = !editor || editor.isEmpty(); - } - findNewParent(editor, x, y) { - const layer = this.#uiManager.findParent(x, y); - if (layer === null || layer === this) { - return false; - } - layer.changeParent(editor); - return true; - } - destroy() { - if (this.#uiManager.getActive()?.parent === this) { - this.#uiManager.commitOrRemove(); - this.#uiManager.setActiveEditor(null); - } - if (this.#editorFocusTimeoutId) { - clearTimeout(this.#editorFocusTimeoutId); - this.#editorFocusTimeoutId = null; - } - for (const editor of this.#editors.values()) { - this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv); - editor.setParent(null); - editor.isAttachedToDOM = false; - editor.div.remove(); - } - this.div = null; - this.#editors.clear(); - this.#uiManager.removeLayer(this); - } - #cleanup() { - this.#isCleaningUp = true; - for (const editor of this.#editors.values()) { - if (editor.isEmpty()) { - editor.remove(); - } - } - this.#isCleaningUp = false; - } - render({ - viewport - }) { - this.viewport = viewport; - (0,display_utils.setLayerDimensions)(this.div, viewport); - for (const editor of this.#uiManager.getEditors(this.pageIndex)) { - this.add(editor); - editor.rebuild(); - } - this.updateMode(); - } - update({ - viewport - }) { - this.#uiManager.commitOrRemove(); - this.#cleanup(); - const oldRotation = this.viewport.rotation; - const rotation = viewport.rotation; - this.viewport = viewport; - (0,display_utils.setLayerDimensions)(this.div, { - rotation - }); - if (oldRotation !== rotation) { - for (const editor of this.#editors.values()) { - editor.rotate(rotation); - } - } - this.addInkEditorIfNeeded(false); - } - get pageDimensions() { - const { - pageWidth, - pageHeight - } = this.viewport.rawDims; - return [pageWidth, pageHeight]; - } - get scale() { - return this.#uiManager.viewParameters.realScale; - } -} - - -/***/ }), - -/***/ 259: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ ColorPicker: () => (/* binding */ ColorPicker) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _tools_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(830); -/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(419); - - - -class ColorPicker { - #boundKeyDown = this.#keyDown.bind(this); - #boundPointerDown = this.#pointerDown.bind(this); - #button = null; - #buttonSwatch = null; - #defaultColor; - #dropdown = null; - #dropdownWasFromKeyboard = false; - #isMainColorPicker = false; - #editor = null; - #eventBus; - #uiManager = null; - #type; - static get _keyboardManager() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "_keyboardManager", new _tools_js__WEBPACK_IMPORTED_MODULE_1__.KeyboardManager([[["Escape", "mac+Escape"], ColorPicker.prototype._hideDropdownFromKeyboard], [[" ", "mac+ "], ColorPicker.prototype._colorSelectFromKeyboard], [["ArrowDown", "ArrowRight", "mac+ArrowDown", "mac+ArrowRight"], ColorPicker.prototype._moveToNext], [["ArrowUp", "ArrowLeft", "mac+ArrowUp", "mac+ArrowLeft"], ColorPicker.prototype._moveToPrevious], [["Home", "mac+Home"], ColorPicker.prototype._moveToBeginning], [["End", "mac+End"], ColorPicker.prototype._moveToEnd]])); - } - constructor({ - editor = null, - uiManager = null - }) { - if (editor) { - this.#isMainColorPicker = false; - this.#type = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_COLOR; - this.#editor = editor; - } else { - this.#isMainColorPicker = true; - this.#type = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR; - } - this.#uiManager = editor?._uiManager || uiManager; - this.#eventBus = this.#uiManager._eventBus; - this.#defaultColor = editor?.color || this.#uiManager?.highlightColors.values().next().value || "#FFFF98"; - } - renderButton() { - const button = this.#button = document.createElement("button"); - button.className = "colorPicker"; - button.tabIndex = "0"; - button.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-button"); - button.setAttribute("aria-haspopup", true); - button.addEventListener("click", this.#openDropdown.bind(this)); - button.addEventListener("keydown", this.#boundKeyDown); - const swatch = this.#buttonSwatch = document.createElement("span"); - swatch.className = "swatch"; - swatch.setAttribute("aria-hidden", true); - swatch.style.backgroundColor = this.#defaultColor; - button.append(swatch); - return button; - } - renderMainDropdown() { - const dropdown = this.#dropdown = this.#getDropdownRoot(); - dropdown.setAttribute("aria-orientation", "horizontal"); - dropdown.setAttribute("aria-labelledby", "highlightColorPickerLabel"); - return dropdown; - } - #getDropdownRoot() { - const div = document.createElement("div"); - div.addEventListener("contextmenu", _display_utils_js__WEBPACK_IMPORTED_MODULE_2__.noContextMenu); - div.className = "dropdown"; - div.role = "listbox"; - div.setAttribute("aria-multiselectable", false); - div.setAttribute("aria-orientation", "vertical"); - div.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-dropdown"); - for (const [name, color] of this.#uiManager.highlightColors) { - const button = document.createElement("button"); - button.tabIndex = "0"; - button.role = "option"; - button.setAttribute("data-color", color); - button.title = name; - button.setAttribute("data-l10n-id", `pdfjs-editor-colorpicker-${name}`); - const swatch = document.createElement("span"); - button.append(swatch); - swatch.className = "swatch"; - swatch.style.backgroundColor = color; - button.setAttribute("aria-selected", color === this.#defaultColor); - button.addEventListener("click", this.#colorSelect.bind(this, color)); - div.append(button); - } - div.addEventListener("keydown", this.#boundKeyDown); - return div; - } - #colorSelect(color, event) { - event.stopPropagation(); - this.#eventBus.dispatch("switchannotationeditorparams", { - source: this, - type: this.#type, - value: color - }); - } - _colorSelectFromKeyboard(event) { - if (event.target === this.#button) { - this.#openDropdown(event); - return; - } - const color = event.target.getAttribute("data-color"); - if (!color) { - return; - } - this.#colorSelect(color, event); - } - _moveToNext(event) { - if (!this.#isDropdownVisible) { - this.#openDropdown(event); - return; - } - if (event.target === this.#button) { - this.#dropdown.firstChild?.focus(); - return; - } - event.target.nextSibling?.focus(); - } - _moveToPrevious(event) { - if (event.target === this.#dropdown?.firstChild || event.target === this.#button) { - if (this.#isDropdownVisible) { - this._hideDropdownFromKeyboard(); - } - return; - } - if (!this.#isDropdownVisible) { - this.#openDropdown(event); - } - event.target.previousSibling?.focus(); - } - _moveToBeginning(event) { - if (!this.#isDropdownVisible) { - this.#openDropdown(event); - return; - } - this.#dropdown.firstChild?.focus(); - } - _moveToEnd(event) { - if (!this.#isDropdownVisible) { - this.#openDropdown(event); - return; - } - this.#dropdown.lastChild?.focus(); - } - #keyDown(event) { - ColorPicker._keyboardManager.exec(this, event); - } - #openDropdown(event) { - if (this.#isDropdownVisible) { - this.hideDropdown(); - return; - } - this.#dropdownWasFromKeyboard = event.detail === 0; - window.addEventListener("pointerdown", this.#boundPointerDown); - if (this.#dropdown) { - this.#dropdown.classList.remove("hidden"); - return; - } - const root = this.#dropdown = this.#getDropdownRoot(); - this.#button.append(root); - } - #pointerDown(event) { - if (this.#dropdown?.contains(event.target)) { - return; - } - this.hideDropdown(); - } - hideDropdown() { - this.#dropdown?.classList.add("hidden"); - window.removeEventListener("pointerdown", this.#boundPointerDown); - } - get #isDropdownVisible() { - return this.#dropdown && !this.#dropdown.classList.contains("hidden"); - } - _hideDropdownFromKeyboard() { - if (this.#isMainColorPicker) { - return; - } - if (!this.#isDropdownVisible) { - this.#editor?.unselect(); - return; - } - this.hideDropdown(); - this.#button.focus({ - preventScroll: true, - focusVisible: this.#dropdownWasFromKeyboard - }); - } - updateColor(color) { - if (this.#buttonSwatch) { - this.#buttonSwatch.style.backgroundColor = color; - } - if (!this.#dropdown) { - return; - } - const i = this.#uiManager.highlightColors.values(); - for (const child of this.#dropdown.children) { - child.setAttribute("aria-selected", i.next().value === color); - } - } - destroy() { - this.#button?.remove(); - this.#button = null; - this.#buttonSwatch = null; - this.#dropdown?.remove(); - this.#dropdown = null; - } -} - - -/***/ }), - -/***/ 310: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - - -// EXPORTS -__webpack_require__.d(__webpack_exports__, { - AnnotationEditor: () => (/* binding */ AnnotationEditor) -}); - -// EXTERNAL MODULE: ./src/display/editor/tools.js -var tools = __webpack_require__(830); -// EXTERNAL MODULE: ./src/shared/util.js -var util = __webpack_require__(292); -// EXTERNAL MODULE: ./src/display/display_utils.js -var display_utils = __webpack_require__(419); -;// CONCATENATED MODULE: ./src/display/editor/alt_text.js - -class AltText { - #altText = ""; - #altTextDecorative = false; - #altTextButton = null; - #altTextTooltip = null; - #altTextTooltipTimeout = null; - #altTextWasFromKeyBoard = false; - #editor = null; - static _l10nPromise = null; - constructor(editor) { - this.#editor = editor; - } - static initialize(l10nPromise) { - AltText._l10nPromise ||= l10nPromise; - } - async render() { - const altText = this.#altTextButton = document.createElement("button"); - altText.className = "altText"; - const msg = await AltText._l10nPromise.get("pdfjs-editor-alt-text-button-label"); - altText.textContent = msg; - altText.setAttribute("aria-label", msg); - altText.tabIndex = "0"; - altText.addEventListener("contextmenu", display_utils.noContextMenu); - altText.addEventListener("pointerdown", event => event.stopPropagation()); - const onClick = event => { - event.preventDefault(); - this.#editor._uiManager.editAltText(this.#editor); - }; - altText.addEventListener("click", onClick, { - capture: true - }); - altText.addEventListener("keydown", event => { - if (event.target === altText && event.key === "Enter") { - this.#altTextWasFromKeyBoard = true; - onClick(event); - } - }); - await this.#setState(); - return altText; - } - finish() { - if (!this.#altTextButton) { - return; - } - this.#altTextButton.focus({ - focusVisible: this.#altTextWasFromKeyBoard - }); - this.#altTextWasFromKeyBoard = false; - } - isEmpty() { - return !this.#altText && !this.#altTextDecorative; - } - get data() { - return { - altText: this.#altText, - decorative: this.#altTextDecorative - }; - } - set data({ - altText, - decorative - }) { - if (this.#altText === altText && this.#altTextDecorative === decorative) { - return; - } - this.#altText = altText; - this.#altTextDecorative = decorative; - this.#setState(); - } - toggle(enabled = false) { - if (!this.#altTextButton) { - return; - } - if (!enabled && this.#altTextTooltipTimeout) { - clearTimeout(this.#altTextTooltipTimeout); - this.#altTextTooltipTimeout = null; - } - this.#altTextButton.disabled = !enabled; - } - destroy() { - this.#altTextButton?.remove(); - this.#altTextButton = null; - this.#altTextTooltip = null; - } - async #setState() { - const button = this.#altTextButton; - if (!button) { - return; - } - if (!this.#altText && !this.#altTextDecorative) { - button.classList.remove("done"); - this.#altTextTooltip?.remove(); - return; - } - button.classList.add("done"); - AltText._l10nPromise.get("pdfjs-editor-alt-text-edit-button-label").then(msg => { - button.setAttribute("aria-label", msg); - }); - let tooltip = this.#altTextTooltip; - if (!tooltip) { - this.#altTextTooltip = tooltip = document.createElement("span"); - tooltip.className = "tooltip"; - tooltip.setAttribute("role", "tooltip"); - const id = tooltip.id = `alt-text-tooltip-${this.#editor.id}`; - button.setAttribute("aria-describedby", id); - const DELAY_TO_SHOW_TOOLTIP = 100; - button.addEventListener("mouseenter", () => { - this.#altTextTooltipTimeout = setTimeout(() => { - this.#altTextTooltipTimeout = null; - this.#altTextTooltip.classList.add("show"); - this.#editor._reportTelemetry({ - action: "alt_text_tooltip" - }); - }, DELAY_TO_SHOW_TOOLTIP); - }); - button.addEventListener("mouseleave", () => { - if (this.#altTextTooltipTimeout) { - clearTimeout(this.#altTextTooltipTimeout); - this.#altTextTooltipTimeout = null; - } - this.#altTextTooltip?.classList.remove("show"); - }); - } - tooltip.innerText = this.#altTextDecorative ? await AltText._l10nPromise.get("pdfjs-editor-alt-text-decorative-tooltip") : this.#altText; - if (!tooltip.parentNode) { - button.append(tooltip); - } - const element = this.#editor.getImageForAltText(); - element?.setAttribute("aria-describedby", tooltip.id); - } -} - -// EXTERNAL MODULE: ./src/display/editor/toolbar.js -var toolbar = __webpack_require__(362); -;// CONCATENATED MODULE: ./src/display/editor/editor.js - - - - - -class AnnotationEditor { - #allResizerDivs = null; - #altText = null; - #disabled = false; - #keepAspectRatio = false; - #resizersDiv = null; - #savedDimensions = null; - #boundFocusin = this.focusin.bind(this); - #boundFocusout = this.focusout.bind(this); - #editToolbar = null; - #focusedResizerName = ""; - #hasBeenClicked = false; - #initialPosition = null; - #isEditing = false; - #isInEditMode = false; - #isResizerEnabledForKeyboard = false; - #moveInDOMTimeout = null; - #prevDragX = 0; - #prevDragY = 0; - #telemetryTimeouts = null; - _initialOptions = Object.create(null); - _isVisible = true; - _uiManager = null; - _focusEventsAllowed = true; - _l10nPromise = null; - #isDraggable = false; - #zIndex = AnnotationEditor._zIndex++; - static _borderLineWidth = -1; - static _colorManager = new tools.ColorManager(); - static _zIndex = 1; - static _telemetryTimeout = 1000; - static get _resizerKeyboardManager() { - const resize = AnnotationEditor.prototype._resizeWithKeyboard; - const small = tools.AnnotationEditorUIManager.TRANSLATE_SMALL; - const big = tools.AnnotationEditorUIManager.TRANSLATE_BIG; - return (0,util.shadow)(this, "_resizerKeyboardManager", new tools.KeyboardManager([[["ArrowLeft", "mac+ArrowLeft"], resize, { - args: [-small, 0] - }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], resize, { - args: [-big, 0] - }], [["ArrowRight", "mac+ArrowRight"], resize, { - args: [small, 0] - }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], resize, { - args: [big, 0] - }], [["ArrowUp", "mac+ArrowUp"], resize, { - args: [0, -small] - }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], resize, { - args: [0, -big] - }], [["ArrowDown", "mac+ArrowDown"], resize, { - args: [0, small] - }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], resize, { - args: [0, big] - }], [["Escape", "mac+Escape"], AnnotationEditor.prototype._stopResizingWithKeyboard]])); - } - constructor(parameters) { - if (this.constructor === AnnotationEditor) { - (0,util.unreachable)("Cannot initialize AnnotationEditor."); - } - this.parent = parameters.parent; - this.id = parameters.id; - this.width = this.height = null; - this.pageIndex = parameters.parent.pageIndex; - this.name = parameters.name; - this.div = null; - this._uiManager = parameters.uiManager; - this.annotationElementId = null; - this._willKeepAspectRatio = false; - this._initialOptions.isCentered = parameters.isCentered; - this._structTreeParentId = null; - const { - rotation, - rawDims: { - pageWidth, - pageHeight, - pageX, - pageY - } - } = this.parent.viewport; - this.rotation = rotation; - this.pageRotation = (360 + rotation - this._uiManager.viewParameters.rotation) % 360; - this.pageDimensions = [pageWidth, pageHeight]; - this.pageTranslation = [pageX, pageY]; - const [width, height] = this.parentDimensions; - this.x = parameters.x / width; - this.y = parameters.y / height; - this.isAttachedToDOM = false; - this.deleted = false; - } - get editorType() { - return Object.getPrototypeOf(this).constructor._type; - } - static get _defaultLineColor() { - return (0,util.shadow)(this, "_defaultLineColor", this._colorManager.getHexCode("CanvasText")); - } - static deleteAnnotationElement(editor) { - const fakeEditor = new FakeEditor({ - id: editor.parent.getNextId(), - parent: editor.parent, - uiManager: editor._uiManager - }); - fakeEditor.annotationElementId = editor.annotationElementId; - fakeEditor.deleted = true; - fakeEditor._uiManager.addToAnnotationStorage(fakeEditor); - } - static initialize(l10n, _uiManager, options) { - AnnotationEditor._l10nPromise ||= new Map(["pdfjs-editor-alt-text-button-label", "pdfjs-editor-alt-text-edit-button-label", "pdfjs-editor-alt-text-decorative-tooltip", "pdfjs-editor-resizer-label-topLeft", "pdfjs-editor-resizer-label-topMiddle", "pdfjs-editor-resizer-label-topRight", "pdfjs-editor-resizer-label-middleRight", "pdfjs-editor-resizer-label-bottomRight", "pdfjs-editor-resizer-label-bottomMiddle", "pdfjs-editor-resizer-label-bottomLeft", "pdfjs-editor-resizer-label-middleLeft"].map(str => [str, l10n.get(str.replaceAll(/([A-Z])/g, c => `-${c.toLowerCase()}`))])); - if (options?.strings) { - for (const str of options.strings) { - AnnotationEditor._l10nPromise.set(str, l10n.get(str)); - } - } - if (AnnotationEditor._borderLineWidth !== -1) { - return; - } - const style = getComputedStyle(document.documentElement); - AnnotationEditor._borderLineWidth = parseFloat(style.getPropertyValue("--outline-width")) || 0; - } - static updateDefaultParams(_type, _value) {} - static get defaultPropertiesToUpdate() { - return []; - } - static isHandlingMimeForPasting(mime) { - return false; - } - static paste(item, parent) { - (0,util.unreachable)("Not implemented"); - } - get propertiesToUpdate() { - return []; - } - get _isDraggable() { - return this.#isDraggable; - } - set _isDraggable(value) { - this.#isDraggable = value; - this.div?.classList.toggle("draggable", value); - } - get isEnterHandled() { - return true; - } - center() { - const [pageWidth, pageHeight] = this.pageDimensions; - switch (this.parentRotation) { - case 90: - this.x -= this.height * pageHeight / (pageWidth * 2); - this.y += this.width * pageWidth / (pageHeight * 2); - break; - case 180: - this.x += this.width / 2; - this.y += this.height / 2; - break; - case 270: - this.x += this.height * pageHeight / (pageWidth * 2); - this.y -= this.width * pageWidth / (pageHeight * 2); - break; - default: - this.x -= this.width / 2; - this.y -= this.height / 2; - break; - } - this.fixAndSetPosition(); - } - addCommands(params) { - this._uiManager.addCommands(params); - } - get currentLayer() { - return this._uiManager.currentLayer; - } - setInBackground() { - this.div.style.zIndex = 0; - } - setInForeground() { - this.div.style.zIndex = this.#zIndex; - } - setParent(parent) { - if (parent !== null) { - this.pageIndex = parent.pageIndex; - this.pageDimensions = parent.pageDimensions; - } else { - this.#stopResizing(); - } - this.parent = parent; - } - focusin(event) { - if (!this._focusEventsAllowed) { - return; - } - if (!this.#hasBeenClicked) { - this.parent.setSelected(this); - } else { - this.#hasBeenClicked = false; - } - } - focusout(event) { - if (!this._focusEventsAllowed) { - return; - } - if (!this.isAttachedToDOM) { - return; - } - const target = event.relatedTarget; - if (target?.closest(`#${this.id}`)) { - return; - } - event.preventDefault(); - if (!this.parent?.isMultipleSelection) { - this.commitOrRemove(); - } - } - commitOrRemove() { - if (this.isEmpty()) { - this.remove(); - } else { - this.commit(); - } - } - commit() { - this.addToAnnotationStorage(); - } - addToAnnotationStorage() { - this._uiManager.addToAnnotationStorage(this); - } - setAt(x, y, tx, ty) { - const [width, height] = this.parentDimensions; - [tx, ty] = this.screenToPageTranslation(tx, ty); - this.x = (x + tx) / width; - this.y = (y + ty) / height; - this.fixAndSetPosition(); - } - #translate([width, height], x, y) { - [x, y] = this.screenToPageTranslation(x, y); - this.x += x / width; - this.y += y / height; - this.fixAndSetPosition(); - } - translate(x, y) { - this.#translate(this.parentDimensions, x, y); - } - translateInPage(x, y) { - this.#initialPosition ||= [this.x, this.y]; - this.#translate(this.pageDimensions, x, y); - this.div.scrollIntoView({ - block: "nearest" - }); - } - drag(tx, ty) { - this.#initialPosition ||= [this.x, this.y]; - const [parentWidth, parentHeight] = this.parentDimensions; - this.x += tx / parentWidth; - this.y += ty / parentHeight; - if (this.parent && (this.x < 0 || this.x > 1 || this.y < 0 || this.y > 1)) { - const { - x, - y - } = this.div.getBoundingClientRect(); - if (this.parent.findNewParent(this, x, y)) { - this.x -= Math.floor(this.x); - this.y -= Math.floor(this.y); - } - } - let { - x, - y - } = this; - const [bx, by] = this.getBaseTranslation(); - x += bx; - y += by; - this.div.style.left = `${(100 * x).toFixed(2)}%`; - this.div.style.top = `${(100 * y).toFixed(2)}%`; - this.div.scrollIntoView({ - block: "nearest" - }); - } - get _hasBeenMoved() { - return !!this.#initialPosition && (this.#initialPosition[0] !== this.x || this.#initialPosition[1] !== this.y); - } - getBaseTranslation() { - const [parentWidth, parentHeight] = this.parentDimensions; - const { - _borderLineWidth - } = AnnotationEditor; - const x = _borderLineWidth / parentWidth; - const y = _borderLineWidth / parentHeight; - switch (this.rotation) { - case 90: - return [-x, y]; - case 180: - return [x, y]; - case 270: - return [x, -y]; - default: - return [-x, -y]; - } - } - get _mustFixPosition() { - return true; - } - fixAndSetPosition(rotation = this.rotation) { - const [pageWidth, pageHeight] = this.pageDimensions; - let { - x, - y, - width, - height - } = this; - width *= pageWidth; - height *= pageHeight; - x *= pageWidth; - y *= pageHeight; - if (this._mustFixPosition) { - switch (rotation) { - case 0: - x = Math.max(0, Math.min(pageWidth - width, x)); - y = Math.max(0, Math.min(pageHeight - height, y)); - break; - case 90: - x = Math.max(0, Math.min(pageWidth - height, x)); - y = Math.min(pageHeight, Math.max(width, y)); - break; - case 180: - x = Math.min(pageWidth, Math.max(width, x)); - y = Math.min(pageHeight, Math.max(height, y)); - break; - case 270: - x = Math.min(pageWidth, Math.max(height, x)); - y = Math.max(0, Math.min(pageHeight - width, y)); - break; - } - } - this.x = x /= pageWidth; - this.y = y /= pageHeight; - const [bx, by] = this.getBaseTranslation(); - x += bx; - y += by; - const { - style - } = this.div; - style.left = `${(100 * x).toFixed(2)}%`; - style.top = `${(100 * y).toFixed(2)}%`; - this.moveInDOM(); - } - static #rotatePoint(x, y, angle) { - switch (angle) { - case 90: - return [y, -x]; - case 180: - return [-x, -y]; - case 270: - return [-y, x]; - default: - return [x, y]; - } - } - screenToPageTranslation(x, y) { - return AnnotationEditor.#rotatePoint(x, y, this.parentRotation); - } - pageTranslationToScreen(x, y) { - return AnnotationEditor.#rotatePoint(x, y, 360 - this.parentRotation); - } - #getRotationMatrix(rotation) { - switch (rotation) { - case 90: - { - const [pageWidth, pageHeight] = this.pageDimensions; - return [0, -pageWidth / pageHeight, pageHeight / pageWidth, 0]; - } - case 180: - return [-1, 0, 0, -1]; - case 270: - { - const [pageWidth, pageHeight] = this.pageDimensions; - return [0, pageWidth / pageHeight, -pageHeight / pageWidth, 0]; - } - default: - return [1, 0, 0, 1]; - } - } - get parentScale() { - return this._uiManager.viewParameters.realScale; - } - get parentRotation() { - return (this._uiManager.viewParameters.rotation + this.pageRotation) % 360; - } - get parentDimensions() { - const { - parentScale, - pageDimensions: [pageWidth, pageHeight] - } = this; - const scaledWidth = pageWidth * parentScale; - const scaledHeight = pageHeight * parentScale; - return util.FeatureTest.isCSSRoundSupported ? [Math.round(scaledWidth), Math.round(scaledHeight)] : [scaledWidth, scaledHeight]; - } - setDims(width, height) { - const [parentWidth, parentHeight] = this.parentDimensions; - this.div.style.width = `${(100 * width / parentWidth).toFixed(2)}%`; - if (!this.#keepAspectRatio) { - this.div.style.height = `${(100 * height / parentHeight).toFixed(2)}%`; - } - } - fixDims() { - const { - style - } = this.div; - const { - height, - width - } = style; - const widthPercent = width.endsWith("%"); - const heightPercent = !this.#keepAspectRatio && height.endsWith("%"); - if (widthPercent && heightPercent) { - return; - } - const [parentWidth, parentHeight] = this.parentDimensions; - if (!widthPercent) { - style.width = `${(100 * parseFloat(width) / parentWidth).toFixed(2)}%`; - } - if (!this.#keepAspectRatio && !heightPercent) { - style.height = `${(100 * parseFloat(height) / parentHeight).toFixed(2)}%`; - } - } - getInitialTranslation() { - return [0, 0]; - } - #createResizers() { - if (this.#resizersDiv) { - return; - } - this.#resizersDiv = document.createElement("div"); - this.#resizersDiv.classList.add("resizers"); - const classes = this._willKeepAspectRatio ? ["topLeft", "topRight", "bottomRight", "bottomLeft"] : ["topLeft", "topMiddle", "topRight", "middleRight", "bottomRight", "bottomMiddle", "bottomLeft", "middleLeft"]; - for (const name of classes) { - const div = document.createElement("div"); - this.#resizersDiv.append(div); - div.classList.add("resizer", name); - div.setAttribute("data-resizer-name", name); - div.addEventListener("pointerdown", this.#resizerPointerdown.bind(this, name)); - div.addEventListener("contextmenu", display_utils.noContextMenu); - div.tabIndex = -1; - } - this.div.prepend(this.#resizersDiv); - } - #resizerPointerdown(name, event) { - event.preventDefault(); - const { - isMac - } = util.FeatureTest.platform; - if (event.button !== 0 || event.ctrlKey && isMac) { - return; - } - this.#altText?.toggle(false); - const boundResizerPointermove = this.#resizerPointermove.bind(this, name); - const savedDraggable = this._isDraggable; - this._isDraggable = false; - const pointerMoveOptions = { - passive: true, - capture: true - }; - this.parent.togglePointerEvents(false); - window.addEventListener("pointermove", boundResizerPointermove, pointerMoveOptions); - window.addEventListener("contextmenu", display_utils.noContextMenu); - const savedX = this.x; - const savedY = this.y; - const savedWidth = this.width; - const savedHeight = this.height; - const savedParentCursor = this.parent.div.style.cursor; - const savedCursor = this.div.style.cursor; - this.div.style.cursor = this.parent.div.style.cursor = window.getComputedStyle(event.target).cursor; - const pointerUpCallback = () => { - this.parent.togglePointerEvents(true); - this.#altText?.toggle(true); - this._isDraggable = savedDraggable; - window.removeEventListener("pointerup", pointerUpCallback); - window.removeEventListener("blur", pointerUpCallback); - window.removeEventListener("pointermove", boundResizerPointermove, pointerMoveOptions); - window.removeEventListener("contextmenu", display_utils.noContextMenu); - this.parent.div.style.cursor = savedParentCursor; - this.div.style.cursor = savedCursor; - this.#addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight); - }; - window.addEventListener("pointerup", pointerUpCallback); - window.addEventListener("blur", pointerUpCallback); - } - #addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight) { - const newX = this.x; - const newY = this.y; - const newWidth = this.width; - const newHeight = this.height; - if (newX === savedX && newY === savedY && newWidth === savedWidth && newHeight === savedHeight) { - return; - } - this.addCommands({ - cmd: () => { - this.width = newWidth; - this.height = newHeight; - this.x = newX; - this.y = newY; - const [parentWidth, parentHeight] = this.parentDimensions; - this.setDims(parentWidth * newWidth, parentHeight * newHeight); - this.fixAndSetPosition(); - }, - undo: () => { - this.width = savedWidth; - this.height = savedHeight; - this.x = savedX; - this.y = savedY; - const [parentWidth, parentHeight] = this.parentDimensions; - this.setDims(parentWidth * savedWidth, parentHeight * savedHeight); - this.fixAndSetPosition(); - }, - mustExec: true - }); - } - #resizerPointermove(name, event) { - const [parentWidth, parentHeight] = this.parentDimensions; - const savedX = this.x; - const savedY = this.y; - const savedWidth = this.width; - const savedHeight = this.height; - const minWidth = AnnotationEditor.MIN_SIZE / parentWidth; - const minHeight = AnnotationEditor.MIN_SIZE / parentHeight; - const round = x => Math.round(x * 10000) / 10000; - const rotationMatrix = this.#getRotationMatrix(this.rotation); - const transf = (x, y) => [rotationMatrix[0] * x + rotationMatrix[2] * y, rotationMatrix[1] * x + rotationMatrix[3] * y]; - const invRotationMatrix = this.#getRotationMatrix(360 - this.rotation); - const invTransf = (x, y) => [invRotationMatrix[0] * x + invRotationMatrix[2] * y, invRotationMatrix[1] * x + invRotationMatrix[3] * y]; - let getPoint; - let getOpposite; - let isDiagonal = false; - let isHorizontal = false; - switch (name) { - case "topLeft": - isDiagonal = true; - getPoint = (w, h) => [0, 0]; - getOpposite = (w, h) => [w, h]; - break; - case "topMiddle": - getPoint = (w, h) => [w / 2, 0]; - getOpposite = (w, h) => [w / 2, h]; - break; - case "topRight": - isDiagonal = true; - getPoint = (w, h) => [w, 0]; - getOpposite = (w, h) => [0, h]; - break; - case "middleRight": - isHorizontal = true; - getPoint = (w, h) => [w, h / 2]; - getOpposite = (w, h) => [0, h / 2]; - break; - case "bottomRight": - isDiagonal = true; - getPoint = (w, h) => [w, h]; - getOpposite = (w, h) => [0, 0]; - break; - case "bottomMiddle": - getPoint = (w, h) => [w / 2, h]; - getOpposite = (w, h) => [w / 2, 0]; - break; - case "bottomLeft": - isDiagonal = true; - getPoint = (w, h) => [0, h]; - getOpposite = (w, h) => [w, 0]; - break; - case "middleLeft": - isHorizontal = true; - getPoint = (w, h) => [0, h / 2]; - getOpposite = (w, h) => [w, h / 2]; - break; - } - const point = getPoint(savedWidth, savedHeight); - const oppositePoint = getOpposite(savedWidth, savedHeight); - let transfOppositePoint = transf(...oppositePoint); - const oppositeX = round(savedX + transfOppositePoint[0]); - const oppositeY = round(savedY + transfOppositePoint[1]); - let ratioX = 1; - let ratioY = 1; - let [deltaX, deltaY] = this.screenToPageTranslation(event.movementX, event.movementY); - [deltaX, deltaY] = invTransf(deltaX / parentWidth, deltaY / parentHeight); - if (isDiagonal) { - const oldDiag = Math.hypot(savedWidth, savedHeight); - ratioX = ratioY = Math.max(Math.min(Math.hypot(oppositePoint[0] - point[0] - deltaX, oppositePoint[1] - point[1] - deltaY) / oldDiag, 1 / savedWidth, 1 / savedHeight), minWidth / savedWidth, minHeight / savedHeight); - } else if (isHorizontal) { - ratioX = Math.max(minWidth, Math.min(1, Math.abs(oppositePoint[0] - point[0] - deltaX))) / savedWidth; - } else { - ratioY = Math.max(minHeight, Math.min(1, Math.abs(oppositePoint[1] - point[1] - deltaY))) / savedHeight; - } - const newWidth = round(savedWidth * ratioX); - const newHeight = round(savedHeight * ratioY); - transfOppositePoint = transf(...getOpposite(newWidth, newHeight)); - const newX = oppositeX - transfOppositePoint[0]; - const newY = oppositeY - transfOppositePoint[1]; - this.width = newWidth; - this.height = newHeight; - this.x = newX; - this.y = newY; - this.setDims(parentWidth * newWidth, parentHeight * newHeight); - this.fixAndSetPosition(); - } - altTextFinish() { - this.#altText?.finish(); - } - async addEditToolbar() { - if (this.#editToolbar || this.#isInEditMode) { - return this.#editToolbar; - } - this.#editToolbar = new toolbar.EditorToolbar(this); - this.div.append(this.#editToolbar.render()); - if (this.#altText) { - this.#editToolbar.addAltTextButton(await this.#altText.render()); - } - return this.#editToolbar; - } - removeEditToolbar() { - if (!this.#editToolbar) { - return; - } - this.#editToolbar.remove(); - this.#editToolbar = null; - this.#altText?.destroy(); - } - getClientDimensions() { - return this.div.getBoundingClientRect(); - } - async addAltTextButton() { - if (this.#altText) { - return; - } - AltText.initialize(AnnotationEditor._l10nPromise); - this.#altText = new AltText(this); - await this.addEditToolbar(); - } - get altTextData() { - return this.#altText?.data; - } - set altTextData(data) { - if (!this.#altText) { - return; - } - this.#altText.data = data; - } - hasAltText() { - return !this.#altText?.isEmpty(); - } - render() { - this.div = document.createElement("div"); - this.div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360); - this.div.className = this.name; - this.div.setAttribute("id", this.id); - this.div.tabIndex = this.#disabled ? -1 : 0; - if (!this._isVisible) { - this.div.classList.add("hidden"); - } - this.setInForeground(); - this.div.addEventListener("focusin", this.#boundFocusin); - this.div.addEventListener("focusout", this.#boundFocusout); - const [parentWidth, parentHeight] = this.parentDimensions; - if (this.parentRotation % 180 !== 0) { - this.div.style.maxWidth = `${(100 * parentHeight / parentWidth).toFixed(2)}%`; - this.div.style.maxHeight = `${(100 * parentWidth / parentHeight).toFixed(2)}%`; - } - const [tx, ty] = this.getInitialTranslation(); - this.translate(tx, ty); - (0,tools.bindEvents)(this, this.div, ["pointerdown"]); - return this.div; - } - pointerdown(event) { - const { - isMac - } = util.FeatureTest.platform; - if (event.button !== 0 || event.ctrlKey && isMac) { - event.preventDefault(); - return; - } - this.#hasBeenClicked = true; - if (this._isDraggable) { - this.#setUpDragSession(event); - return; - } - this.#selectOnPointerEvent(event); - } - #selectOnPointerEvent(event) { - const { - isMac - } = util.FeatureTest.platform; - if (event.ctrlKey && !isMac || event.shiftKey || event.metaKey && isMac) { - this.parent.toggleSelected(this); - } else { - this.parent.setSelected(this); - } - } - #setUpDragSession(event) { - const isSelected = this._uiManager.isSelected(this); - this._uiManager.setUpDragSession(); - let pointerMoveOptions, pointerMoveCallback; - if (isSelected) { - this.div.classList.add("moving"); - pointerMoveOptions = { - passive: true, - capture: true - }; - this.#prevDragX = event.clientX; - this.#prevDragY = event.clientY; - pointerMoveCallback = e => { - const { - clientX: x, - clientY: y - } = e; - const [tx, ty] = this.screenToPageTranslation(x - this.#prevDragX, y - this.#prevDragY); - this.#prevDragX = x; - this.#prevDragY = y; - this._uiManager.dragSelectedEditors(tx, ty); - }; - window.addEventListener("pointermove", pointerMoveCallback, pointerMoveOptions); - } - const pointerUpCallback = () => { - window.removeEventListener("pointerup", pointerUpCallback); - window.removeEventListener("blur", pointerUpCallback); - if (isSelected) { - this.div.classList.remove("moving"); - window.removeEventListener("pointermove", pointerMoveCallback, pointerMoveOptions); - } - this.#hasBeenClicked = false; - if (!this._uiManager.endDragSession()) { - this.#selectOnPointerEvent(event); - } - }; - window.addEventListener("pointerup", pointerUpCallback); - window.addEventListener("blur", pointerUpCallback); - } - moveInDOM() { - if (this.#moveInDOMTimeout) { - clearTimeout(this.#moveInDOMTimeout); - } - this.#moveInDOMTimeout = setTimeout(() => { - this.#moveInDOMTimeout = null; - this.parent?.moveEditorInDOM(this); - }, 0); - } - _setParentAndPosition(parent, x, y) { - parent.changeParent(this); - this.x = x; - this.y = y; - this.fixAndSetPosition(); - } - getRect(tx, ty, rotation = this.rotation) { - const scale = this.parentScale; - const [pageWidth, pageHeight] = this.pageDimensions; - const [pageX, pageY] = this.pageTranslation; - const shiftX = tx / scale; - const shiftY = ty / scale; - const x = this.x * pageWidth; - const y = this.y * pageHeight; - const width = this.width * pageWidth; - const height = this.height * pageHeight; - switch (rotation) { - case 0: - return [x + shiftX + pageX, pageHeight - y - shiftY - height + pageY, x + shiftX + width + pageX, pageHeight - y - shiftY + pageY]; - case 90: - return [x + shiftY + pageX, pageHeight - y + shiftX + pageY, x + shiftY + height + pageX, pageHeight - y + shiftX + width + pageY]; - case 180: - return [x - shiftX - width + pageX, pageHeight - y + shiftY + pageY, x - shiftX + pageX, pageHeight - y + shiftY + height + pageY]; - case 270: - return [x - shiftY - height + pageX, pageHeight - y - shiftX - width + pageY, x - shiftY + pageX, pageHeight - y - shiftX + pageY]; - default: - throw new Error("Invalid rotation"); - } - } - getRectInCurrentCoords(rect, pageHeight) { - const [x1, y1, x2, y2] = rect; - const width = x2 - x1; - const height = y2 - y1; - switch (this.rotation) { - case 0: - return [x1, pageHeight - y2, width, height]; - case 90: - return [x1, pageHeight - y1, height, width]; - case 180: - return [x2, pageHeight - y1, width, height]; - case 270: - return [x2, pageHeight - y2, height, width]; - default: - throw new Error("Invalid rotation"); - } - } - onceAdded() {} - isEmpty() { - return false; - } - enableEditMode() { - this.#isInEditMode = true; - } - disableEditMode() { - this.#isInEditMode = false; - } - isInEditMode() { - return this.#isInEditMode; - } - shouldGetKeyboardEvents() { - return this.#isResizerEnabledForKeyboard; - } - needsToBeRebuilt() { - return this.div && !this.isAttachedToDOM; - } - rebuild() { - this.div?.addEventListener("focusin", this.#boundFocusin); - this.div?.addEventListener("focusout", this.#boundFocusout); - } - rotate(_angle) {} - serialize(isForCopying = false, context = null) { - (0,util.unreachable)("An editor must be serializable"); - } - static deserialize(data, parent, uiManager) { - const editor = new this.prototype.constructor({ - parent, - id: parent.getNextId(), - uiManager - }); - editor.rotation = data.rotation; - const [pageWidth, pageHeight] = editor.pageDimensions; - const [x, y, width, height] = editor.getRectInCurrentCoords(data.rect, pageHeight); - editor.x = x / pageWidth; - editor.y = y / pageHeight; - editor.width = width / pageWidth; - editor.height = height / pageHeight; - return editor; - } - get hasBeenModified() { - return !!this.annotationElementId && (this.deleted || this.serialize() !== null); - } - remove() { - this.div.removeEventListener("focusin", this.#boundFocusin); - this.div.removeEventListener("focusout", this.#boundFocusout); - if (!this.isEmpty()) { - this.commit(); - } - if (this.parent) { - this.parent.remove(this); - } else { - this._uiManager.removeEditor(this); - } - if (this.#moveInDOMTimeout) { - clearTimeout(this.#moveInDOMTimeout); - this.#moveInDOMTimeout = null; - } - this.#stopResizing(); - this.removeEditToolbar(); - if (this.#telemetryTimeouts) { - for (const timeout of this.#telemetryTimeouts.values()) { - clearTimeout(timeout); - } - this.#telemetryTimeouts = null; - } - this.parent = null; - } - get isResizable() { - return false; - } - makeResizable() { - if (this.isResizable) { - this.#createResizers(); - this.#resizersDiv.classList.remove("hidden"); - (0,tools.bindEvents)(this, this.div, ["keydown"]); - } - } - get toolbarPosition() { - return null; - } - keydown(event) { - if (!this.isResizable || event.target !== this.div || event.key !== "Enter") { - return; - } - this._uiManager.setSelected(this); - this.#savedDimensions = { - savedX: this.x, - savedY: this.y, - savedWidth: this.width, - savedHeight: this.height - }; - const children = this.#resizersDiv.children; - if (!this.#allResizerDivs) { - this.#allResizerDivs = Array.from(children); - const boundResizerKeydown = this.#resizerKeydown.bind(this); - const boundResizerBlur = this.#resizerBlur.bind(this); - for (const div of this.#allResizerDivs) { - const name = div.getAttribute("data-resizer-name"); - div.setAttribute("role", "spinbutton"); - div.addEventListener("keydown", boundResizerKeydown); - div.addEventListener("blur", boundResizerBlur); - div.addEventListener("focus", this.#resizerFocus.bind(this, name)); - AnnotationEditor._l10nPromise.get(`pdfjs-editor-resizer-label-${name}`).then(msg => div.setAttribute("aria-label", msg)); - } - } - const first = this.#allResizerDivs[0]; - let firstPosition = 0; - for (const div of children) { - if (div === first) { - break; - } - firstPosition++; - } - const nextFirstPosition = (360 - this.rotation + this.parentRotation) % 360 / 90 * (this.#allResizerDivs.length / 4); - if (nextFirstPosition !== firstPosition) { - if (nextFirstPosition < firstPosition) { - for (let i = 0; i < firstPosition - nextFirstPosition; i++) { - this.#resizersDiv.append(this.#resizersDiv.firstChild); - } - } else if (nextFirstPosition > firstPosition) { - for (let i = 0; i < nextFirstPosition - firstPosition; i++) { - this.#resizersDiv.firstChild.before(this.#resizersDiv.lastChild); - } - } - let i = 0; - for (const child of children) { - const div = this.#allResizerDivs[i++]; - const name = div.getAttribute("data-resizer-name"); - AnnotationEditor._l10nPromise.get(`pdfjs-editor-resizer-label-${name}`).then(msg => child.setAttribute("aria-label", msg)); - } - } - this.#setResizerTabIndex(0); - this.#isResizerEnabledForKeyboard = true; - this.#resizersDiv.firstChild.focus({ - focusVisible: true - }); - event.preventDefault(); - event.stopImmediatePropagation(); - } - #resizerKeydown(event) { - AnnotationEditor._resizerKeyboardManager.exec(this, event); - } - #resizerBlur(event) { - if (this.#isResizerEnabledForKeyboard && event.relatedTarget?.parentNode !== this.#resizersDiv) { - this.#stopResizing(); - } - } - #resizerFocus(name) { - this.#focusedResizerName = this.#isResizerEnabledForKeyboard ? name : ""; - } - #setResizerTabIndex(value) { - if (!this.#allResizerDivs) { - return; - } - for (const div of this.#allResizerDivs) { - div.tabIndex = value; - } - } - _resizeWithKeyboard(x, y) { - if (!this.#isResizerEnabledForKeyboard) { - return; - } - this.#resizerPointermove(this.#focusedResizerName, { - movementX: x, - movementY: y - }); - } - #stopResizing() { - this.#isResizerEnabledForKeyboard = false; - this.#setResizerTabIndex(-1); - if (this.#savedDimensions) { - const { - savedX, - savedY, - savedWidth, - savedHeight - } = this.#savedDimensions; - this.#addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight); - this.#savedDimensions = null; - } - } - _stopResizingWithKeyboard() { - this.#stopResizing(); - this.div.focus(); - } - select() { - this.makeResizable(); - this.div?.classList.add("selectedEditor"); - if (!this.#editToolbar) { - this.addEditToolbar().then(() => { - if (this.div?.classList.contains("selectedEditor")) { - this.#editToolbar?.show(); - } - }); - return; - } - this.#editToolbar?.show(); - } - unselect() { - this.#resizersDiv?.classList.add("hidden"); - this.div?.classList.remove("selectedEditor"); - if (this.div?.contains(document.activeElement)) { - this._uiManager.currentLayer.div.focus({ - preventScroll: true - }); - } - this.#editToolbar?.hide(); - } - updateParams(type, value) {} - disableEditing() {} - enableEditing() {} - enterInEditMode() {} - getImageForAltText() { - return null; - } - get contentDiv() { - return this.div; - } - get isEditing() { - return this.#isEditing; - } - set isEditing(value) { - this.#isEditing = value; - if (!this.parent) { - return; - } - if (value) { - this.parent.setSelected(this); - this.parent.setActiveEditor(this); - } else { - this.parent.setActiveEditor(null); - } - } - setAspectRatio(width, height) { - this.#keepAspectRatio = true; - const aspectRatio = width / height; - const { - style - } = this.div; - style.aspectRatio = aspectRatio; - style.height = "auto"; - } - static get MIN_SIZE() { - return 16; - } - static canCreateNewEmptyEditor() { - return true; - } - get telemetryInitialData() { - return { - action: "added" - }; - } - get telemetryFinalData() { - return null; - } - _reportTelemetry(data, mustWait = false) { - if (mustWait) { - this.#telemetryTimeouts ||= new Map(); - const { - action - } = data; - let timeout = this.#telemetryTimeouts.get(action); - if (timeout) { - clearTimeout(timeout); - } - timeout = setTimeout(() => { - this._reportTelemetry(data); - this.#telemetryTimeouts.delete(action); - if (this.#telemetryTimeouts.size === 0) { - this.#telemetryTimeouts = null; - } - }, AnnotationEditor._telemetryTimeout); - this.#telemetryTimeouts.set(action, timeout); - return; - } - data.type ||= this.editorType; - this._uiManager._eventBus.dispatch("reporttelemetry", { - source: this, - details: { - type: "editing", - data - } - }); - } - show(visible = this._isVisible) { - this.div.classList.toggle("hidden", !visible); - this._isVisible = visible; - } - enable() { - if (this.div) { - this.div.tabIndex = 0; - } - this.#disabled = false; - } - disable() { - if (this.div) { - this.div.tabIndex = -1; - } - this.#disabled = true; - } - renderAnnotationElement(annotation) { - let content = annotation.container.querySelector(".annotationContent"); - if (!content) { - content = document.createElement("div"); - content.classList.add("annotationContent", this.editorType); - annotation.container.prepend(content); - } else if (content.nodeName === "CANVAS") { - const canvas = content; - content = document.createElement("div"); - content.classList.add("annotationContent", this.editorType); - canvas.before(content); - } - return content; - } - resetAnnotationElement(annotation) { - const { - firstChild - } = annotation.container; - if (firstChild.nodeName === "DIV" && firstChild.classList.contains("annotationContent")) { - firstChild.remove(); - } - } -} -class FakeEditor extends AnnotationEditor { - constructor(params) { - super(params); - this.annotationElementId = params.annotationElementId; - this.deleted = true; - } - serialize() { - return { - id: this.annotationElementId, - deleted: true, - pageIndex: this.pageIndex - }; - } -} - - -/***/ }), - -/***/ 61: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ FreeOutliner: () => (/* binding */ FreeOutliner), -/* harmony export */ Outliner: () => (/* binding */ Outliner) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); - -class Outliner { - #box; - #verticalEdges = []; - #intervals = []; - constructor(boxes, borderWidth = 0, innerMargin = 0, isLTR = true) { - let minX = Infinity; - let maxX = -Infinity; - let minY = Infinity; - let maxY = -Infinity; - const NUMBER_OF_DIGITS = 4; - const EPSILON = 10 ** -NUMBER_OF_DIGITS; - for (const { - x, - y, - width, - height - } of boxes) { - const x1 = Math.floor((x - borderWidth) / EPSILON) * EPSILON; - const x2 = Math.ceil((x + width + borderWidth) / EPSILON) * EPSILON; - const y1 = Math.floor((y - borderWidth) / EPSILON) * EPSILON; - const y2 = Math.ceil((y + height + borderWidth) / EPSILON) * EPSILON; - const left = [x1, y1, y2, true]; - const right = [x2, y1, y2, false]; - this.#verticalEdges.push(left, right); - minX = Math.min(minX, x1); - maxX = Math.max(maxX, x2); - minY = Math.min(minY, y1); - maxY = Math.max(maxY, y2); - } - const bboxWidth = maxX - minX + 2 * innerMargin; - const bboxHeight = maxY - minY + 2 * innerMargin; - const shiftedMinX = minX - innerMargin; - const shiftedMinY = minY - innerMargin; - const lastEdge = this.#verticalEdges.at(isLTR ? -1 : -2); - const lastPoint = [lastEdge[0], lastEdge[2]]; - for (const edge of this.#verticalEdges) { - const [x, y1, y2] = edge; - edge[0] = (x - shiftedMinX) / bboxWidth; - edge[1] = (y1 - shiftedMinY) / bboxHeight; - edge[2] = (y2 - shiftedMinY) / bboxHeight; - } - this.#box = { - x: shiftedMinX, - y: shiftedMinY, - width: bboxWidth, - height: bboxHeight, - lastPoint - }; - } - getOutlines() { - this.#verticalEdges.sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2]); - const outlineVerticalEdges = []; - for (const edge of this.#verticalEdges) { - if (edge[3]) { - outlineVerticalEdges.push(...this.#breakEdge(edge)); - this.#insert(edge); - } else { - this.#remove(edge); - outlineVerticalEdges.push(...this.#breakEdge(edge)); - } - } - return this.#getOutlines(outlineVerticalEdges); - } - #getOutlines(outlineVerticalEdges) { - const edges = []; - const allEdges = new Set(); - for (const edge of outlineVerticalEdges) { - const [x, y1, y2] = edge; - edges.push([x, y1, edge], [x, y2, edge]); - } - edges.sort((a, b) => a[1] - b[1] || a[0] - b[0]); - for (let i = 0, ii = edges.length; i < ii; i += 2) { - const edge1 = edges[i][2]; - const edge2 = edges[i + 1][2]; - edge1.push(edge2); - edge2.push(edge1); - allEdges.add(edge1); - allEdges.add(edge2); - } - const outlines = []; - let outline; - while (allEdges.size > 0) { - const edge = allEdges.values().next().value; - let [x, y1, y2, edge1, edge2] = edge; - allEdges.delete(edge); - let lastPointX = x; - let lastPointY = y1; - outline = [x, y2]; - outlines.push(outline); - while (true) { - let e; - if (allEdges.has(edge1)) { - e = edge1; - } else if (allEdges.has(edge2)) { - e = edge2; - } else { - break; - } - allEdges.delete(e); - [x, y1, y2, edge1, edge2] = e; - if (lastPointX !== x) { - outline.push(lastPointX, lastPointY, x, lastPointY === y1 ? y1 : y2); - lastPointX = x; - } - lastPointY = lastPointY === y1 ? y2 : y1; - } - outline.push(lastPointX, lastPointY); - } - return new HighlightOutline(outlines, this.#box); - } - #binarySearch(y) { - const array = this.#intervals; - let start = 0; - let end = array.length - 1; - while (start <= end) { - const middle = start + end >> 1; - const y1 = array[middle][0]; - if (y1 === y) { - return middle; - } - if (y1 < y) { - start = middle + 1; - } else { - end = middle - 1; - } - } - return end + 1; - } - #insert([, y1, y2]) { - const index = this.#binarySearch(y1); - this.#intervals.splice(index, 0, [y1, y2]); - } - #remove([, y1, y2]) { - const index = this.#binarySearch(y1); - for (let i = index; i < this.#intervals.length; i++) { - const [start, end] = this.#intervals[i]; - if (start !== y1) { - break; - } - if (start === y1 && end === y2) { - this.#intervals.splice(i, 1); - return; - } - } - for (let i = index - 1; i >= 0; i--) { - const [start, end] = this.#intervals[i]; - if (start !== y1) { - break; - } - if (start === y1 && end === y2) { - this.#intervals.splice(i, 1); - return; - } - } - } - #breakEdge(edge) { - const [x, y1, y2] = edge; - const results = [[x, y1, y2]]; - const index = this.#binarySearch(y2); - for (let i = 0; i < index; i++) { - const [start, end] = this.#intervals[i]; - for (let j = 0, jj = results.length; j < jj; j++) { - const [, y3, y4] = results[j]; - if (end <= y3 || y4 <= start) { - continue; - } - if (y3 >= start) { - if (y4 > end) { - results[j][1] = end; - } else { - if (jj === 1) { - return []; - } - results.splice(j, 1); - j--; - jj--; - } - continue; - } - results[j][2] = start; - if (y4 > end) { - results.push([x, end, y4]); - } - } - } - return results; - } -} -class Outline { - toSVGPath() { - throw new Error("Abstract method `toSVGPath` must be implemented."); - } - get box() { - throw new Error("Abstract getter `box` must be implemented."); - } - serialize(_bbox, _rotation) { - throw new Error("Abstract method `serialize` must be implemented."); - } - get free() { - return this instanceof FreeHighlightOutline; - } -} -class HighlightOutline extends Outline { - #box; - #outlines; - constructor(outlines, box) { - super(); - this.#outlines = outlines; - this.#box = box; - } - toSVGPath() { - const buffer = []; - for (const polygon of this.#outlines) { - let [prevX, prevY] = polygon; - buffer.push(`M${prevX} ${prevY}`); - for (let i = 2; i < polygon.length; i += 2) { - const x = polygon[i]; - const y = polygon[i + 1]; - if (x === prevX) { - buffer.push(`V${y}`); - prevY = y; - } else if (y === prevY) { - buffer.push(`H${x}`); - prevX = x; - } - } - buffer.push("Z"); - } - return buffer.join(" "); - } - serialize([blX, blY, trX, trY], _rotation) { - const outlines = []; - const width = trX - blX; - const height = trY - blY; - for (const outline of this.#outlines) { - const points = new Array(outline.length); - for (let i = 0; i < outline.length; i += 2) { - points[i] = blX + outline[i] * width; - points[i + 1] = trY - outline[i + 1] * height; - } - outlines.push(points); - } - return outlines; - } - get box() { - return this.#box; - } -} -class FreeOutliner { - #box; - #bottom = []; - #innerMargin; - #isLTR; - #top = []; - #last = new Float64Array(18); - #lastX; - #lastY; - #min; - #min_dist; - #scaleFactor; - #thickness; - #points = []; - static #MIN_DIST = 8; - static #MIN_DIFF = 2; - static #MIN = FreeOutliner.#MIN_DIST + FreeOutliner.#MIN_DIFF; - constructor({ - x, - y - }, box, scaleFactor, thickness, isLTR, innerMargin = 0) { - this.#box = box; - this.#thickness = thickness * scaleFactor; - this.#isLTR = isLTR; - this.#last.set([NaN, NaN, NaN, NaN, x, y], 6); - this.#innerMargin = innerMargin; - this.#min_dist = FreeOutliner.#MIN_DIST * scaleFactor; - this.#min = FreeOutliner.#MIN * scaleFactor; - this.#scaleFactor = scaleFactor; - this.#points.push(x, y); - } - get free() { - return true; - } - isEmpty() { - return isNaN(this.#last[8]); - } - #getLastCoords() { - const lastTop = this.#last.subarray(4, 6); - const lastBottom = this.#last.subarray(16, 18); - const [x, y, width, height] = this.#box; - return [(this.#lastX + (lastTop[0] - lastBottom[0]) / 2 - x) / width, (this.#lastY + (lastTop[1] - lastBottom[1]) / 2 - y) / height, (this.#lastX + (lastBottom[0] - lastTop[0]) / 2 - x) / width, (this.#lastY + (lastBottom[1] - lastTop[1]) / 2 - y) / height]; - } - add({ - x, - y - }) { - this.#lastX = x; - this.#lastY = y; - const [layerX, layerY, layerWidth, layerHeight] = this.#box; - let [x1, y1, x2, y2] = this.#last.subarray(8, 12); - const diffX = x - x2; - const diffY = y - y2; - const d = Math.hypot(diffX, diffY); - if (d < this.#min) { - return false; - } - const diffD = d - this.#min_dist; - const K = diffD / d; - const shiftX = K * diffX; - const shiftY = K * diffY; - let x0 = x1; - let y0 = y1; - x1 = x2; - y1 = y2; - x2 += shiftX; - y2 += shiftY; - this.#points?.push(x, y); - const nX = -shiftY / diffD; - const nY = shiftX / diffD; - const thX = nX * this.#thickness; - const thY = nY * this.#thickness; - this.#last.set(this.#last.subarray(2, 8), 0); - this.#last.set([x2 + thX, y2 + thY], 4); - this.#last.set(this.#last.subarray(14, 18), 12); - this.#last.set([x2 - thX, y2 - thY], 16); - if (isNaN(this.#last[6])) { - if (this.#top.length === 0) { - this.#last.set([x1 + thX, y1 + thY], 2); - this.#top.push(NaN, NaN, NaN, NaN, (x1 + thX - layerX) / layerWidth, (y1 + thY - layerY) / layerHeight); - this.#last.set([x1 - thX, y1 - thY], 14); - this.#bottom.push(NaN, NaN, NaN, NaN, (x1 - thX - layerX) / layerWidth, (y1 - thY - layerY) / layerHeight); - } - this.#last.set([x0, y0, x1, y1, x2, y2], 6); - return !this.isEmpty(); - } - this.#last.set([x0, y0, x1, y1, x2, y2], 6); - const angle = Math.abs(Math.atan2(y0 - y1, x0 - x1) - Math.atan2(shiftY, shiftX)); - if (angle < Math.PI / 2) { - [x1, y1, x2, y2] = this.#last.subarray(2, 6); - this.#top.push(NaN, NaN, NaN, NaN, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); - [x1, y1, x0, y0] = this.#last.subarray(14, 18); - this.#bottom.push(NaN, NaN, NaN, NaN, ((x0 + x1) / 2 - layerX) / layerWidth, ((y0 + y1) / 2 - layerY) / layerHeight); - return true; - } - [x0, y0, x1, y1, x2, y2] = this.#last.subarray(0, 6); - this.#top.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); - [x2, y2, x1, y1, x0, y0] = this.#last.subarray(12, 18); - this.#bottom.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); - return true; - } - toSVGPath() { - if (this.isEmpty()) { - return ""; - } - const top = this.#top; - const bottom = this.#bottom; - const lastTop = this.#last.subarray(4, 6); - const lastBottom = this.#last.subarray(16, 18); - const [x, y, width, height] = this.#box; - const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords(); - if (isNaN(this.#last[6]) && !this.isEmpty()) { - return `M${(this.#last[2] - x) / width} ${(this.#last[3] - y) / height} L${(this.#last[4] - x) / width} ${(this.#last[5] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(this.#last[16] - x) / width} ${(this.#last[17] - y) / height} L${(this.#last[14] - x) / width} ${(this.#last[15] - y) / height} Z`; - } - const buffer = []; - buffer.push(`M${top[4]} ${top[5]}`); - for (let i = 6; i < top.length; i += 6) { - if (isNaN(top[i])) { - buffer.push(`L${top[i + 4]} ${top[i + 5]}`); - } else { - buffer.push(`C${top[i]} ${top[i + 1]} ${top[i + 2]} ${top[i + 3]} ${top[i + 4]} ${top[i + 5]}`); - } - } - buffer.push(`L${(lastTop[0] - x) / width} ${(lastTop[1] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(lastBottom[0] - x) / width} ${(lastBottom[1] - y) / height}`); - for (let i = bottom.length - 6; i >= 6; i -= 6) { - if (isNaN(bottom[i])) { - buffer.push(`L${bottom[i + 4]} ${bottom[i + 5]}`); - } else { - buffer.push(`C${bottom[i]} ${bottom[i + 1]} ${bottom[i + 2]} ${bottom[i + 3]} ${bottom[i + 4]} ${bottom[i + 5]}`); - } - } - buffer.push(`L${bottom[4]} ${bottom[5]} Z`); - return buffer.join(" "); - } - getOutlines() { - const top = this.#top; - const bottom = this.#bottom; - const last = this.#last; - const lastTop = last.subarray(4, 6); - const lastBottom = last.subarray(16, 18); - const [layerX, layerY, layerWidth, layerHeight] = this.#box; - const points = new Float64Array((this.#points?.length ?? 0) + 2); - for (let i = 0, ii = points.length - 2; i < ii; i += 2) { - points[i] = (this.#points[i] - layerX) / layerWidth; - points[i + 1] = (this.#points[i + 1] - layerY) / layerHeight; - } - points[points.length - 2] = (this.#lastX - layerX) / layerWidth; - points[points.length - 1] = (this.#lastY - layerY) / layerHeight; - const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords(); - if (isNaN(last[6]) && !this.isEmpty()) { - const outline = new Float64Array(36); - outline.set([NaN, NaN, NaN, NaN, (last[2] - layerX) / layerWidth, (last[3] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[4] - layerX) / layerWidth, (last[5] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (last[16] - layerX) / layerWidth, (last[17] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[14] - layerX) / layerWidth, (last[15] - layerY) / layerHeight], 0); - return new FreeHighlightOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR); - } - const outline = new Float64Array(this.#top.length + 24 + this.#bottom.length); - let N = top.length; - for (let i = 0; i < N; i += 2) { - if (isNaN(top[i])) { - outline[i] = outline[i + 1] = NaN; - continue; - } - outline[i] = top[i]; - outline[i + 1] = top[i + 1]; - } - outline.set([NaN, NaN, NaN, NaN, (lastTop[0] - layerX) / layerWidth, (lastTop[1] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (lastBottom[0] - layerX) / layerWidth, (lastBottom[1] - layerY) / layerHeight], N); - N += 24; - for (let i = bottom.length - 6; i >= 6; i -= 6) { - for (let j = 0; j < 6; j += 2) { - if (isNaN(bottom[i + j])) { - outline[N] = outline[N + 1] = NaN; - N += 2; - continue; - } - outline[N] = bottom[i + j]; - outline[N + 1] = bottom[i + j + 1]; - N += 2; - } - } - outline.set([NaN, NaN, NaN, NaN, bottom[4], bottom[5]], N); - return new FreeHighlightOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR); - } -} -class FreeHighlightOutline extends Outline { - #box; - #bbox = null; - #innerMargin; - #isLTR; - #points; - #scaleFactor; - #outline; - constructor(outline, points, box, scaleFactor, innerMargin, isLTR) { - super(); - this.#outline = outline; - this.#points = points; - this.#box = box; - this.#scaleFactor = scaleFactor; - this.#innerMargin = innerMargin; - this.#isLTR = isLTR; - this.#computeMinMax(isLTR); - const { - x, - y, - width, - height - } = this.#bbox; - for (let i = 0, ii = outline.length; i < ii; i += 2) { - outline[i] = (outline[i] - x) / width; - outline[i + 1] = (outline[i + 1] - y) / height; - } - for (let i = 0, ii = points.length; i < ii; i += 2) { - points[i] = (points[i] - x) / width; - points[i + 1] = (points[i + 1] - y) / height; - } - } - toSVGPath() { - const buffer = [`M${this.#outline[4]} ${this.#outline[5]}`]; - for (let i = 6, ii = this.#outline.length; i < ii; i += 6) { - if (isNaN(this.#outline[i])) { - buffer.push(`L${this.#outline[i + 4]} ${this.#outline[i + 5]}`); - continue; - } - buffer.push(`C${this.#outline[i]} ${this.#outline[i + 1]} ${this.#outline[i + 2]} ${this.#outline[i + 3]} ${this.#outline[i + 4]} ${this.#outline[i + 5]}`); - } - buffer.push("Z"); - return buffer.join(" "); - } - serialize([blX, blY, trX, trY], rotation) { - const width = trX - blX; - const height = trY - blY; - let outline; - let points; - switch (rotation) { - case 0: - outline = this.#rescale(this.#outline, blX, trY, width, -height); - points = this.#rescale(this.#points, blX, trY, width, -height); - break; - case 90: - outline = this.#rescaleAndSwap(this.#outline, blX, blY, width, height); - points = this.#rescaleAndSwap(this.#points, blX, blY, width, height); - break; - case 180: - outline = this.#rescale(this.#outline, trX, blY, -width, height); - points = this.#rescale(this.#points, trX, blY, -width, height); - break; - case 270: - outline = this.#rescaleAndSwap(this.#outline, trX, trY, -width, -height); - points = this.#rescaleAndSwap(this.#points, trX, trY, -width, -height); - break; - } - return { - outline: Array.from(outline), - points: [Array.from(points)] - }; - } - #rescale(src, tx, ty, sx, sy) { - const dest = new Float64Array(src.length); - for (let i = 0, ii = src.length; i < ii; i += 2) { - dest[i] = tx + src[i] * sx; - dest[i + 1] = ty + src[i + 1] * sy; - } - return dest; - } - #rescaleAndSwap(src, tx, ty, sx, sy) { - const dest = new Float64Array(src.length); - for (let i = 0, ii = src.length; i < ii; i += 2) { - dest[i] = tx + src[i + 1] * sx; - dest[i + 1] = ty + src[i] * sy; - } - return dest; - } - #computeMinMax(isLTR) { - const outline = this.#outline; - let lastX = outline[4]; - let lastY = outline[5]; - let minX = lastX; - let minY = lastY; - let maxX = lastX; - let maxY = lastY; - let lastPointX = lastX; - let lastPointY = lastY; - const ltrCallback = isLTR ? Math.max : Math.min; - for (let i = 6, ii = outline.length; i < ii; i += 6) { - if (isNaN(outline[i])) { - minX = Math.min(minX, outline[i + 4]); - minY = Math.min(minY, outline[i + 5]); - maxX = Math.max(maxX, outline[i + 4]); - maxY = Math.max(maxY, outline[i + 5]); - if (lastPointY < outline[i + 5]) { - lastPointX = outline[i + 4]; - lastPointY = outline[i + 5]; - } else if (lastPointY === outline[i + 5]) { - lastPointX = ltrCallback(lastPointX, outline[i + 4]); - } - } else { - const bbox = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.Util.bezierBoundingBox(lastX, lastY, ...outline.slice(i, i + 6)); - minX = Math.min(minX, bbox[0]); - minY = Math.min(minY, bbox[1]); - maxX = Math.max(maxX, bbox[2]); - maxY = Math.max(maxY, bbox[3]); - if (lastPointY < bbox[3]) { - lastPointX = bbox[2]; - lastPointY = bbox[3]; - } else if (lastPointY === bbox[3]) { - lastPointX = ltrCallback(lastPointX, bbox[2]); - } - } - lastX = outline[i + 4]; - lastY = outline[i + 5]; - } - const x = minX - this.#innerMargin, - y = minY - this.#innerMargin, - width = maxX - minX + 2 * this.#innerMargin, - height = maxY - minY + 2 * this.#innerMargin; - this.#bbox = { - x, - y, - width, - height, - lastPoint: [lastPointX, lastPointY] - }; - } - get box() { - return this.#bbox; - } - getNewOutline(thickness, innerMargin) { - const { - x, - y, - width, - height - } = this.#bbox; - const [layerX, layerY, layerWidth, layerHeight] = this.#box; - const sx = width * layerWidth; - const sy = height * layerHeight; - const tx = x * layerWidth + layerX; - const ty = y * layerHeight + layerY; - const outliner = new FreeOutliner({ - x: this.#points[0] * sx + tx, - y: this.#points[1] * sy + ty - }, this.#box, this.#scaleFactor, thickness, this.#isLTR, innerMargin ?? this.#innerMargin); - for (let i = 2; i < this.#points.length; i += 2) { - outliner.add({ - x: this.#points[i] * sx + tx, - y: this.#points[i + 1] * sy + ty - }); - } - return outliner.getOutlines(); - } -} - - -/***/ }), - -/***/ 362: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ EditorToolbar: () => (/* binding */ EditorToolbar), -/* harmony export */ HighlightToolbar: () => (/* binding */ HighlightToolbar) -/* harmony export */ }); -/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(419); - -class EditorToolbar { - #toolbar = null; - #colorPicker = null; - #editor; - #buttons = null; - constructor(editor) { - this.#editor = editor; - } - render() { - const editToolbar = this.#toolbar = document.createElement("div"); - editToolbar.className = "editToolbar"; - editToolbar.setAttribute("role", "toolbar"); - editToolbar.addEventListener("contextmenu", _display_utils_js__WEBPACK_IMPORTED_MODULE_0__.noContextMenu); - editToolbar.addEventListener("pointerdown", EditorToolbar.#pointerDown); - const buttons = this.#buttons = document.createElement("div"); - buttons.className = "buttons"; - editToolbar.append(buttons); - const position = this.#editor.toolbarPosition; - if (position) { - const { - style - } = editToolbar; - const x = this.#editor._uiManager.direction === "ltr" ? 1 - position[0] : position[0]; - style.insetInlineEnd = `${100 * x}%`; - style.top = `calc(${100 * position[1]}% + var(--editor-toolbar-vert-offset))`; - } - this.#addDeleteButton(); - return editToolbar; - } - static #pointerDown(e) { - e.stopPropagation(); - } - #focusIn(e) { - this.#editor._focusEventsAllowed = false; - e.preventDefault(); - e.stopPropagation(); - } - #focusOut(e) { - this.#editor._focusEventsAllowed = true; - e.preventDefault(); - e.stopPropagation(); - } - #addListenersToElement(element) { - element.addEventListener("focusin", this.#focusIn.bind(this), { - capture: true - }); - element.addEventListener("focusout", this.#focusOut.bind(this), { - capture: true - }); - element.addEventListener("contextmenu", _display_utils_js__WEBPACK_IMPORTED_MODULE_0__.noContextMenu); - } - hide() { - this.#toolbar.classList.add("hidden"); - this.#colorPicker?.hideDropdown(); - } - show() { - this.#toolbar.classList.remove("hidden"); - } - #addDeleteButton() { - const button = document.createElement("button"); - button.className = "delete"; - button.tabIndex = 0; - button.setAttribute("data-l10n-id", `pdfjs-editor-remove-${this.#editor.editorType}-button`); - this.#addListenersToElement(button); - button.addEventListener("click", e => { - this.#editor._uiManager.delete(); - }); - this.#buttons.append(button); - } - get #divider() { - const divider = document.createElement("div"); - divider.className = "divider"; - return divider; - } - addAltTextButton(button) { - this.#addListenersToElement(button); - this.#buttons.prepend(button, this.#divider); - } - addColorPicker(colorPicker) { - this.#colorPicker = colorPicker; - const button = colorPicker.renderButton(); - this.#addListenersToElement(button); - this.#buttons.prepend(button, this.#divider); - } - remove() { - this.#toolbar.remove(); - this.#colorPicker?.destroy(); - this.#colorPicker = null; - } -} -class HighlightToolbar { - #buttons = null; - #toolbar = null; - #uiManager; - constructor(uiManager) { - this.#uiManager = uiManager; - } - #render() { - const editToolbar = this.#toolbar = document.createElement("div"); - editToolbar.className = "editToolbar"; - editToolbar.setAttribute("role", "toolbar"); - editToolbar.addEventListener("contextmenu", _display_utils_js__WEBPACK_IMPORTED_MODULE_0__.noContextMenu); - const buttons = this.#buttons = document.createElement("div"); - buttons.className = "buttons"; - editToolbar.append(buttons); - this.#addHighlightButton(); - return editToolbar; - } - #getLastPoint(boxes, isLTR) { - let lastY = 0; - let lastX = 0; - for (const box of boxes) { - const y = box.y + box.height; - if (y < lastY) { - continue; - } - const x = box.x + (isLTR ? box.width : 0); - if (y > lastY) { - lastX = x; - lastY = y; - continue; - } - if (isLTR) { - if (x > lastX) { - lastX = x; - } - } else if (x < lastX) { - lastX = x; - } - } - return [isLTR ? 1 - lastX : lastX, lastY]; - } - show(parent, boxes, isLTR) { - const [x, y] = this.#getLastPoint(boxes, isLTR); - const { - style - } = this.#toolbar ||= this.#render(); - parent.append(this.#toolbar); - style.insetInlineEnd = `${100 * x}%`; - style.top = `calc(${100 * y}% + var(--editor-toolbar-vert-offset))`; - } - hide() { - this.#toolbar.remove(); - } - #addHighlightButton() { - const button = document.createElement("button"); - button.className = "highlightButton"; - button.tabIndex = 0; - button.setAttribute("data-l10n-id", `pdfjs-highlight-floating-button1`); - const span = document.createElement("span"); - button.append(span); - span.className = "visuallyHidden"; - span.setAttribute("data-l10n-id", "pdfjs-highlight-floating-button-label"); - button.addEventListener("contextmenu", _display_utils_js__WEBPACK_IMPORTED_MODULE_0__.noContextMenu); - button.addEventListener("click", () => { - this.#uiManager.highlightSelection("floating_button"); - }); - this.#buttons.append(button); - } -} - - -/***/ }), - -/***/ 830: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AnnotationEditorUIManager: () => (/* binding */ AnnotationEditorUIManager), -/* harmony export */ ColorManager: () => (/* binding */ ColorManager), -/* harmony export */ KeyboardManager: () => (/* binding */ KeyboardManager), -/* harmony export */ bindEvents: () => (/* binding */ bindEvents), -/* harmony export */ opacityToHex: () => (/* binding */ opacityToHex) -/* harmony export */ }); -/* unused harmony export CommandManager */ -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(419); -/* harmony import */ var _toolbar_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(362); - - - -function bindEvents(obj, element, names) { - for (const name of names) { - element.addEventListener(name, obj[name].bind(obj)); - } -} -function opacityToHex(opacity) { - return Math.round(Math.min(255, Math.max(1, 255 * opacity))).toString(16).padStart(2, "0"); -} -class IdManager { - #id = 0; - constructor() {} - get id() { - return `${_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorPrefix}${this.#id++}`; - } -} -class ImageManager { - #baseId = (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.getUuid)(); - #id = 0; - #cache = null; - static get _isSVGFittingCanvas() { - const svg = `data:image/svg+xml;charset=UTF-8,`; - const canvas = new OffscreenCanvas(1, 3); - const ctx = canvas.getContext("2d"); - const image = new Image(); - image.src = svg; - const promise = image.decode().then(() => { - ctx.drawImage(image, 0, 0, 1, 1, 0, 0, 1, 3); - return new Uint32Array(ctx.getImageData(0, 0, 1, 1).data.buffer)[0] === 0; - }); - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "_isSVGFittingCanvas", promise); - } - async #get(key, rawData) { - this.#cache ||= new Map(); - let data = this.#cache.get(key); - if (data === null) { - return null; - } - if (data?.bitmap) { - data.refCounter += 1; - return data; - } - try { - data ||= { - bitmap: null, - id: `image_${this.#baseId}_${this.#id++}`, - refCounter: 0, - isSvg: false - }; - let image; - if (typeof rawData === "string") { - data.url = rawData; - image = await (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.fetchData)(rawData, "blob"); - } else { - image = data.file = rawData; - } - if (image.type === "image/svg+xml") { - const mustRemoveAspectRatioPromise = ImageManager._isSVGFittingCanvas; - const fileReader = new FileReader(); - const imageElement = new Image(); - const imagePromise = new Promise((resolve, reject) => { - imageElement.onload = () => { - data.bitmap = imageElement; - data.isSvg = true; - resolve(); - }; - fileReader.onload = async () => { - const url = data.svgUrl = fileReader.result; - imageElement.src = (await mustRemoveAspectRatioPromise) ? `${url}#svgView(preserveAspectRatio(none))` : url; - }; - imageElement.onerror = fileReader.onerror = reject; - }); - fileReader.readAsDataURL(image); - await imagePromise; - } else { - data.bitmap = await createImageBitmap(image); - } - data.refCounter = 1; - } catch (e) { - console.error(e); - data = null; - } - this.#cache.set(key, data); - if (data) { - this.#cache.set(data.id, data); - } - return data; - } - async getFromFile(file) { - const { - lastModified, - name, - size, - type - } = file; - return this.#get(`${lastModified}_${name}_${size}_${type}`, file); - } - async getFromUrl(url) { - return this.#get(url, url); - } - async getFromId(id) { - this.#cache ||= new Map(); - const data = this.#cache.get(id); - if (!data) { - return null; - } - if (data.bitmap) { - data.refCounter += 1; - return data; - } - if (data.file) { - return this.getFromFile(data.file); - } - return this.getFromUrl(data.url); - } - getSvgUrl(id) { - const data = this.#cache.get(id); - if (!data?.isSvg) { - return null; - } - return data.svgUrl; - } - deleteId(id) { - this.#cache ||= new Map(); - const data = this.#cache.get(id); - if (!data) { - return; - } - data.refCounter -= 1; - if (data.refCounter !== 0) { - return; - } - data.bitmap = null; - } - isValidId(id) { - return id.startsWith(`image_${this.#baseId}_`); - } -} -class CommandManager { - #commands = []; - #locked = false; - #maxSize; - #position = -1; - constructor(maxSize = 128) { - this.#maxSize = maxSize; - } - add({ - cmd, - undo, - post, - mustExec, - type = NaN, - overwriteIfSameType = false, - keepUndo = false - }) { - if (mustExec) { - cmd(); - } - if (this.#locked) { - return; - } - const save = { - cmd, - undo, - post, - type - }; - if (this.#position === -1) { - if (this.#commands.length > 0) { - this.#commands.length = 0; - } - this.#position = 0; - this.#commands.push(save); - return; - } - if (overwriteIfSameType && this.#commands[this.#position].type === type) { - if (keepUndo) { - save.undo = this.#commands[this.#position].undo; - } - this.#commands[this.#position] = save; - return; - } - const next = this.#position + 1; - if (next === this.#maxSize) { - this.#commands.splice(0, 1); - } else { - this.#position = next; - if (next < this.#commands.length) { - this.#commands.splice(next); - } - } - this.#commands.push(save); - } - undo() { - if (this.#position === -1) { - return; - } - this.#locked = true; - const { - undo, - post - } = this.#commands[this.#position]; - undo(); - post?.(); - this.#locked = false; - this.#position -= 1; - } - redo() { - if (this.#position < this.#commands.length - 1) { - this.#position += 1; - this.#locked = true; - const { - cmd, - post - } = this.#commands[this.#position]; - cmd(); - post?.(); - this.#locked = false; - } - } - hasSomethingToUndo() { - return this.#position !== -1; - } - hasSomethingToRedo() { - return this.#position < this.#commands.length - 1; - } - destroy() { - this.#commands = null; - } -} -class KeyboardManager { - constructor(callbacks) { - this.buffer = []; - this.callbacks = new Map(); - this.allKeys = new Set(); - const { - isMac - } = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FeatureTest.platform; - for (const [keys, callback, options = {}] of callbacks) { - for (const key of keys) { - const isMacKey = key.startsWith("mac+"); - if (isMac && isMacKey) { - this.callbacks.set(key.slice(4), { - callback, - options - }); - this.allKeys.add(key.split("+").at(-1)); - } else if (!isMac && !isMacKey) { - this.callbacks.set(key, { - callback, - options - }); - this.allKeys.add(key.split("+").at(-1)); - } - } - } - } - #serialize(event) { - if (event.altKey) { - this.buffer.push("alt"); - } - if (event.ctrlKey) { - this.buffer.push("ctrl"); - } - if (event.metaKey) { - this.buffer.push("meta"); - } - if (event.shiftKey) { - this.buffer.push("shift"); - } - this.buffer.push(event.key); - const str = this.buffer.join("+"); - this.buffer.length = 0; - return str; - } - exec(self, event) { - if (!this.allKeys.has(event.key)) { - return; - } - const info = this.callbacks.get(this.#serialize(event)); - if (!info) { - return; - } - const { - callback, - options: { - bubbles = false, - args = [], - checker = null - } - } = info; - if (checker && !checker(self, event)) { - return; - } - callback.bind(self, ...args, event)(); - if (!bubbles) { - event.stopPropagation(); - event.preventDefault(); - } - } -} -class ColorManager { - static _colorsMapping = new Map([["CanvasText", [0, 0, 0]], ["Canvas", [255, 255, 255]]]); - get _colors() { - const colors = new Map([["CanvasText", null], ["Canvas", null]]); - (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.getColorValues)(colors); - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "_colors", colors); - } - convert(color) { - const rgb = (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.getRGB)(color); - if (!window.matchMedia("(forced-colors: active)").matches) { - return rgb; - } - for (const [name, RGB] of this._colors) { - if (RGB.every((x, i) => x === rgb[i])) { - return ColorManager._colorsMapping.get(name); - } - } - return rgb; - } - getHexCode(name) { - const rgb = this._colors.get(name); - if (!rgb) { - return name; - } - return _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.Util.makeHexColor(...rgb); - } -} -class AnnotationEditorUIManager { - #activeEditor = null; - #allEditors = new Map(); - #allLayers = new Map(); - #altTextManager = null; - #annotationStorage = null; - #changedExistingAnnotations = null; - #commandManager = new CommandManager(); - #currentPageIndex = 0; - #deletedAnnotationsElementIds = new Set(); - #draggingEditors = null; - #editorTypes = null; - #editorsToRescale = new Set(); - #enableHighlightFloatingButton = false; - #filterFactory = null; - #focusMainContainerTimeoutId = null; - #highlightColors = null; - #highlightWhenShiftUp = false; - #highlightToolbar = null; - #idManager = new IdManager(); - #isEnabled = false; - #isWaiting = false; - #lastActiveElement = null; - #mainHighlightColorPicker = null; - #mlManager = null; - #mode = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE; - #selectedEditors = new Set(); - #selectedTextNode = null; - #pageColors = null; - #showAllStates = null; - #boundBlur = this.blur.bind(this); - #boundFocus = this.focus.bind(this); - #boundCopy = this.copy.bind(this); - #boundCut = this.cut.bind(this); - #boundPaste = this.paste.bind(this); - #boundKeydown = this.keydown.bind(this); - #boundKeyup = this.keyup.bind(this); - #boundOnEditingAction = this.onEditingAction.bind(this); - #boundOnPageChanging = this.onPageChanging.bind(this); - #boundOnScaleChanging = this.onScaleChanging.bind(this); - #boundSelectionChange = this.#selectionChange.bind(this); - #boundOnRotationChanging = this.onRotationChanging.bind(this); - #previousStates = { - isEditing: false, - isEmpty: true, - hasSomethingToUndo: false, - hasSomethingToRedo: false, - hasSelectedEditor: false, - hasSelectedText: false - }; - #translation = [0, 0]; - #translationTimeoutId = null; - #container = null; - #viewer = null; - static TRANSLATE_SMALL = 1; - static TRANSLATE_BIG = 10; - static get _keyboardManager() { - const proto = AnnotationEditorUIManager.prototype; - const arrowChecker = self => self.#container.contains(document.activeElement) && document.activeElement.tagName !== "BUTTON" && self.hasSomethingToControl(); - const textInputChecker = (_self, { - target: el - }) => { - if (el instanceof HTMLInputElement) { - const { - type - } = el; - return type !== "text" && type !== "number"; - } - return true; - }; - const small = this.TRANSLATE_SMALL; - const big = this.TRANSLATE_BIG; - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "_keyboardManager", new KeyboardManager([[["ctrl+a", "mac+meta+a"], proto.selectAll, { - checker: textInputChecker - }], [["ctrl+z", "mac+meta+z"], proto.undo, { - checker: textInputChecker - }], [["ctrl+y", "ctrl+shift+z", "mac+meta+shift+z", "ctrl+shift+Z", "mac+meta+shift+Z"], proto.redo, { - checker: textInputChecker - }], [["Backspace", "alt+Backspace", "ctrl+Backspace", "shift+Backspace", "mac+Backspace", "mac+alt+Backspace", "mac+ctrl+Backspace", "Delete", "ctrl+Delete", "shift+Delete", "mac+Delete"], proto.delete, { - checker: textInputChecker - }], [["Enter", "mac+Enter"], proto.addNewEditorFromKeyboard, { - checker: (self, { - target: el - }) => !(el instanceof HTMLButtonElement) && self.#container.contains(el) && !self.isEnterHandled - }], [[" ", "mac+ "], proto.addNewEditorFromKeyboard, { - checker: (self, { - target: el - }) => !(el instanceof HTMLButtonElement) && self.#container.contains(document.activeElement) - }], [["Escape", "mac+Escape"], proto.unselectAll], [["ArrowLeft", "mac+ArrowLeft"], proto.translateSelectedEditors, { - args: [-small, 0], - checker: arrowChecker - }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], proto.translateSelectedEditors, { - args: [-big, 0], - checker: arrowChecker - }], [["ArrowRight", "mac+ArrowRight"], proto.translateSelectedEditors, { - args: [small, 0], - checker: arrowChecker - }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], proto.translateSelectedEditors, { - args: [big, 0], - checker: arrowChecker - }], [["ArrowUp", "mac+ArrowUp"], proto.translateSelectedEditors, { - args: [0, -small], - checker: arrowChecker - }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], proto.translateSelectedEditors, { - args: [0, -big], - checker: arrowChecker - }], [["ArrowDown", "mac+ArrowDown"], proto.translateSelectedEditors, { - args: [0, small], - checker: arrowChecker - }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], proto.translateSelectedEditors, { - args: [0, big], - checker: arrowChecker - }]])); - } - constructor(container, viewer, altTextManager, eventBus, pdfDocument, pageColors, highlightColors, enableHighlightFloatingButton, mlManager) { - this.#container = container; - this.#viewer = viewer; - this.#altTextManager = altTextManager; - this._eventBus = eventBus; - this._eventBus._on("editingaction", this.#boundOnEditingAction); - this._eventBus._on("pagechanging", this.#boundOnPageChanging); - this._eventBus._on("scalechanging", this.#boundOnScaleChanging); - this._eventBus._on("rotationchanging", this.#boundOnRotationChanging); - this.#addSelectionListener(); - this.#addKeyboardManager(); - this.#annotationStorage = pdfDocument.annotationStorage; - this.#filterFactory = pdfDocument.filterFactory; - this.#pageColors = pageColors; - this.#highlightColors = highlightColors || null; - this.#enableHighlightFloatingButton = enableHighlightFloatingButton; - this.#mlManager = mlManager || null; - this.viewParameters = { - realScale: _display_utils_js__WEBPACK_IMPORTED_MODULE_1__.PixelsPerInch.PDF_TO_CSS_UNITS, - rotation: 0 - }; - this.isShiftKeyDown = false; - } - destroy() { - this.#removeKeyboardManager(); - this.#removeFocusManager(); - this._eventBus._off("editingaction", this.#boundOnEditingAction); - this._eventBus._off("pagechanging", this.#boundOnPageChanging); - this._eventBus._off("scalechanging", this.#boundOnScaleChanging); - this._eventBus._off("rotationchanging", this.#boundOnRotationChanging); - for (const layer of this.#allLayers.values()) { - layer.destroy(); - } - this.#allLayers.clear(); - this.#allEditors.clear(); - this.#editorsToRescale.clear(); - this.#activeEditor = null; - this.#selectedEditors.clear(); - this.#commandManager.destroy(); - this.#altTextManager?.destroy(); - this.#highlightToolbar?.hide(); - this.#highlightToolbar = null; - if (this.#focusMainContainerTimeoutId) { - clearTimeout(this.#focusMainContainerTimeoutId); - this.#focusMainContainerTimeoutId = null; - } - if (this.#translationTimeoutId) { - clearTimeout(this.#translationTimeoutId); - this.#translationTimeoutId = null; - } - this.#removeSelectionListener(); - } - async mlGuess(data) { - return this.#mlManager?.guess(data) || null; - } - get hasMLManager() { - return !!this.#mlManager; - } - get hcmFilter() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "hcmFilter", this.#pageColors ? this.#filterFactory.addHCMFilter(this.#pageColors.foreground, this.#pageColors.background) : "none"); - } - get direction() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "direction", getComputedStyle(this.#container).direction); - } - get highlightColors() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "highlightColors", this.#highlightColors ? new Map(this.#highlightColors.split(",").map(pair => pair.split("=").map(x => x.trim()))) : null); - } - get highlightColorNames() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "highlightColorNames", this.highlightColors ? new Map(Array.from(this.highlightColors, e => e.reverse())) : null); - } - setMainHighlightColorPicker(colorPicker) { - this.#mainHighlightColorPicker = colorPicker; - } - editAltText(editor) { - this.#altTextManager?.editAltText(this, editor); - } - onPageChanging({ - pageNumber - }) { - this.#currentPageIndex = pageNumber - 1; - } - focusMainContainer() { - this.#container.focus(); - } - findParent(x, y) { - for (const layer of this.#allLayers.values()) { - const { - x: layerX, - y: layerY, - width, - height - } = layer.div.getBoundingClientRect(); - if (x >= layerX && x <= layerX + width && y >= layerY && y <= layerY + height) { - return layer; - } - } - return null; - } - disableUserSelect(value = false) { - this.#viewer.classList.toggle("noUserSelect", value); - } - addShouldRescale(editor) { - this.#editorsToRescale.add(editor); - } - removeShouldRescale(editor) { - this.#editorsToRescale.delete(editor); - } - onScaleChanging({ - scale - }) { - this.commitOrRemove(); - this.viewParameters.realScale = scale * _display_utils_js__WEBPACK_IMPORTED_MODULE_1__.PixelsPerInch.PDF_TO_CSS_UNITS; - for (const editor of this.#editorsToRescale) { - editor.onScaleChanging(); - } - } - onRotationChanging({ - pagesRotation - }) { - this.commitOrRemove(); - this.viewParameters.rotation = pagesRotation; - } - #getAnchorElementForSelection({ - anchorNode - }) { - return anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode; - } - highlightSelection(methodOfCreation = "") { - const selection = document.getSelection(); - if (!selection || selection.isCollapsed) { - return; - } - const { - anchorNode, - anchorOffset, - focusNode, - focusOffset - } = selection; - const text = selection.toString(); - const anchorElement = this.#getAnchorElementForSelection(selection); - const textLayer = anchorElement.closest(".textLayer"); - const boxes = this.getSelectionBoxes(textLayer); - if (!boxes) { - return; - } - selection.empty(); - if (this.#mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) { - this._eventBus.dispatch("showannotationeditorui", { - source: this, - mode: _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT - }); - this.showAllEditors("highlight", true, true); - } - for (const layer of this.#allLayers.values()) { - if (layer.hasTextLayer(textLayer)) { - layer.createAndAddNewEditor({ - x: 0, - y: 0 - }, false, { - methodOfCreation, - boxes, - anchorNode, - anchorOffset, - focusNode, - focusOffset, - text - }); - break; - } - } - } - #displayHighlightToolbar() { - const selection = document.getSelection(); - if (!selection || selection.isCollapsed) { - return; - } - const anchorElement = this.#getAnchorElementForSelection(selection); - const textLayer = anchorElement.closest(".textLayer"); - const boxes = this.getSelectionBoxes(textLayer); - if (!boxes) { - return; - } - this.#highlightToolbar ||= new _toolbar_js__WEBPACK_IMPORTED_MODULE_2__.HighlightToolbar(this); - this.#highlightToolbar.show(textLayer, boxes, this.direction === "ltr"); - } - addToAnnotationStorage(editor) { - if (!editor.isEmpty() && this.#annotationStorage && !this.#annotationStorage.has(editor.id)) { - this.#annotationStorage.setValue(editor.id, editor); - } - } - #selectionChange() { - const selection = document.getSelection(); - if (!selection || selection.isCollapsed) { - if (this.#selectedTextNode) { - this.#highlightToolbar?.hide(); - this.#selectedTextNode = null; - this.#dispatchUpdateStates({ - hasSelectedText: false - }); - } - return; - } - const { - anchorNode - } = selection; - if (anchorNode === this.#selectedTextNode) { - return; - } - const anchorElement = this.#getAnchorElementForSelection(selection); - const textLayer = anchorElement.closest(".textLayer"); - if (!textLayer) { - if (this.#selectedTextNode) { - this.#highlightToolbar?.hide(); - this.#selectedTextNode = null; - this.#dispatchUpdateStates({ - hasSelectedText: false - }); - } - return; - } - this.#highlightToolbar?.hide(); - this.#selectedTextNode = anchorNode; - this.#dispatchUpdateStates({ - hasSelectedText: true - }); - if (this.#mode !== _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT && this.#mode !== _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) { - return; - } - if (this.#mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT) { - this.showAllEditors("highlight", true, true); - } - this.#highlightWhenShiftUp = this.isShiftKeyDown; - if (!this.isShiftKeyDown) { - const pointerup = e => { - if (e.type === "pointerup" && e.button !== 0) { - return; - } - window.removeEventListener("pointerup", pointerup); - window.removeEventListener("blur", pointerup); - if (e.type === "pointerup") { - this.#onSelectEnd("main_toolbar"); - } - }; - window.addEventListener("pointerup", pointerup); - window.addEventListener("blur", pointerup); - } - } - #onSelectEnd(methodOfCreation = "") { - if (this.#mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT) { - this.highlightSelection(methodOfCreation); - } else if (this.#enableHighlightFloatingButton) { - this.#displayHighlightToolbar(); - } - } - #addSelectionListener() { - document.addEventListener("selectionchange", this.#boundSelectionChange); - } - #removeSelectionListener() { - document.removeEventListener("selectionchange", this.#boundSelectionChange); - } - #addFocusManager() { - window.addEventListener("focus", this.#boundFocus); - window.addEventListener("blur", this.#boundBlur); - } - #removeFocusManager() { - window.removeEventListener("focus", this.#boundFocus); - window.removeEventListener("blur", this.#boundBlur); - } - blur() { - this.isShiftKeyDown = false; - if (this.#highlightWhenShiftUp) { - this.#highlightWhenShiftUp = false; - this.#onSelectEnd("main_toolbar"); - } - if (!this.hasSelection) { - return; - } - const { - activeElement - } = document; - for (const editor of this.#selectedEditors) { - if (editor.div.contains(activeElement)) { - this.#lastActiveElement = [editor, activeElement]; - editor._focusEventsAllowed = false; - break; - } - } - } - focus() { - if (!this.#lastActiveElement) { - return; - } - const [lastEditor, lastActiveElement] = this.#lastActiveElement; - this.#lastActiveElement = null; - lastActiveElement.addEventListener("focusin", () => { - lastEditor._focusEventsAllowed = true; - }, { - once: true - }); - lastActiveElement.focus(); - } - #addKeyboardManager() { - window.addEventListener("keydown", this.#boundKeydown); - window.addEventListener("keyup", this.#boundKeyup); - } - #removeKeyboardManager() { - window.removeEventListener("keydown", this.#boundKeydown); - window.removeEventListener("keyup", this.#boundKeyup); - } - #addCopyPasteListeners() { - document.addEventListener("copy", this.#boundCopy); - document.addEventListener("cut", this.#boundCut); - document.addEventListener("paste", this.#boundPaste); - } - #removeCopyPasteListeners() { - document.removeEventListener("copy", this.#boundCopy); - document.removeEventListener("cut", this.#boundCut); - document.removeEventListener("paste", this.#boundPaste); - } - addEditListeners() { - this.#addKeyboardManager(); - this.#addCopyPasteListeners(); - } - removeEditListeners() { - this.#removeKeyboardManager(); - this.#removeCopyPasteListeners(); - } - copy(event) { - event.preventDefault(); - this.#activeEditor?.commitOrRemove(); - if (!this.hasSelection) { - return; - } - const editors = []; - for (const editor of this.#selectedEditors) { - const serialized = editor.serialize(true); - if (serialized) { - editors.push(serialized); - } - } - if (editors.length === 0) { - return; - } - event.clipboardData.setData("application/pdfjs", JSON.stringify(editors)); - } - cut(event) { - this.copy(event); - this.delete(); - } - paste(event) { - event.preventDefault(); - const { - clipboardData - } = event; - for (const item of clipboardData.items) { - for (const editorType of this.#editorTypes) { - if (editorType.isHandlingMimeForPasting(item.type)) { - editorType.paste(item, this.currentLayer); - return; - } - } - } - let data = clipboardData.getData("application/pdfjs"); - if (!data) { - return; - } - try { - data = JSON.parse(data); - } catch (ex) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`paste: "${ex.message}".`); - return; - } - if (!Array.isArray(data)) { - return; - } - this.unselectAll(); - const layer = this.currentLayer; - try { - const newEditors = []; - for (const editor of data) { - const deserializedEditor = layer.deserialize(editor); - if (!deserializedEditor) { - return; - } - newEditors.push(deserializedEditor); - } - const cmd = () => { - for (const editor of newEditors) { - this.#addEditorToLayer(editor); - } - this.#selectEditors(newEditors); - }; - const undo = () => { - for (const editor of newEditors) { - editor.remove(); - } - }; - this.addCommands({ - cmd, - undo, - mustExec: true - }); - } catch (ex) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`paste: "${ex.message}".`); - } - } - keydown(event) { - if (!this.isShiftKeyDown && event.key === "Shift") { - this.isShiftKeyDown = true; - } - if (this.#mode !== _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE && !this.isEditorHandlingKeyboard) { - AnnotationEditorUIManager._keyboardManager.exec(this, event); - } - } - keyup(event) { - if (this.isShiftKeyDown && event.key === "Shift") { - this.isShiftKeyDown = false; - if (this.#highlightWhenShiftUp) { - this.#highlightWhenShiftUp = false; - this.#onSelectEnd("main_toolbar"); - } - } - } - onEditingAction({ - name - }) { - switch (name) { - case "undo": - case "redo": - case "delete": - case "selectAll": - this[name](); - break; - case "highlightSelection": - this.highlightSelection("context_menu"); - break; - } - } - #dispatchUpdateStates(details) { - const hasChanged = Object.entries(details).some(([key, value]) => this.#previousStates[key] !== value); - if (hasChanged) { - this._eventBus.dispatch("annotationeditorstateschanged", { - source: this, - details: Object.assign(this.#previousStates, details) - }); - if (this.#mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT && details.hasSelectedEditor === false) { - this.#dispatchUpdateUI([[_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_FREE, true]]); - } - } - } - #dispatchUpdateUI(details) { - this._eventBus.dispatch("annotationeditorparamschanged", { - source: this, - details - }); - } - setEditingState(isEditing) { - if (isEditing) { - this.#addFocusManager(); - this.#addCopyPasteListeners(); - this.#dispatchUpdateStates({ - isEditing: this.#mode !== _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE, - isEmpty: this.#isEmpty(), - hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(), - hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(), - hasSelectedEditor: false - }); - } else { - this.#removeFocusManager(); - this.#removeCopyPasteListeners(); - this.#dispatchUpdateStates({ - isEditing: false - }); - this.disableUserSelect(false); - } - } - registerEditorTypes(types) { - if (this.#editorTypes) { - return; - } - this.#editorTypes = types; - for (const editorType of this.#editorTypes) { - this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate); - } - } - getId() { - return this.#idManager.id; - } - get currentLayer() { - return this.#allLayers.get(this.#currentPageIndex); - } - getLayer(pageIndex) { - return this.#allLayers.get(pageIndex); - } - get currentPageIndex() { - return this.#currentPageIndex; - } - addLayer(layer) { - this.#allLayers.set(layer.pageIndex, layer); - if (this.#isEnabled) { - layer.enable(); - } else { - layer.disable(); - } - } - removeLayer(layer) { - this.#allLayers.delete(layer.pageIndex); - } - updateMode(mode, editId = null, isFromKeyboard = false) { - if (this.#mode === mode) { - return; - } - this.#mode = mode; - if (mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) { - this.setEditingState(false); - this.#disableAll(); - return; - } - this.setEditingState(true); - this.#enableAll(); - this.unselectAll(); - for (const layer of this.#allLayers.values()) { - layer.updateMode(mode); - } - if (!editId && isFromKeyboard) { - this.addNewEditorFromKeyboard(); - return; - } - if (!editId) { - return; - } - for (const editor of this.#allEditors.values()) { - if (editor.annotationElementId === editId) { - this.setSelected(editor); - editor.enterInEditMode(); - break; - } - } - } - addNewEditorFromKeyboard() { - if (this.currentLayer.canCreateNewEmptyEditor()) { - this.currentLayer.addNewEditor(); - } - } - updateToolbar(mode) { - if (mode === this.#mode) { - return; - } - this._eventBus.dispatch("switchannotationeditormode", { - source: this, - mode - }); - } - updateParams(type, value) { - if (!this.#editorTypes) { - return; - } - switch (type) { - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.CREATE: - this.currentLayer.addNewEditor(); - return; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR: - this.#mainHighlightColorPicker?.updateColor(value); - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL: - this._eventBus.dispatch("reporttelemetry", { - source: this, - details: { - type: "editing", - data: { - type: "highlight", - action: "toggle_visibility" - } - } - }); - (this.#showAllStates ||= new Map()).set(type, value); - this.showAllEditors("highlight", value); - break; - } - for (const editor of this.#selectedEditors) { - editor.updateParams(type, value); - } - for (const editorType of this.#editorTypes) { - editorType.updateDefaultParams(type, value); - } - } - showAllEditors(type, visible, updateButton = false) { - for (const editor of this.#allEditors.values()) { - if (editor.editorType === type) { - editor.show(visible); - } - } - const state = this.#showAllStates?.get(_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL) ?? true; - if (state !== visible) { - this.#dispatchUpdateUI([[_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL, visible]]); - } - } - enableWaiting(mustWait = false) { - if (this.#isWaiting === mustWait) { - return; - } - this.#isWaiting = mustWait; - for (const layer of this.#allLayers.values()) { - if (mustWait) { - layer.disableClick(); - } else { - layer.enableClick(); - } - layer.div.classList.toggle("waiting", mustWait); - } - } - #enableAll() { - if (!this.#isEnabled) { - this.#isEnabled = true; - for (const layer of this.#allLayers.values()) { - layer.enable(); - } - for (const editor of this.#allEditors.values()) { - editor.enable(); - } - } - } - #disableAll() { - this.unselectAll(); - if (this.#isEnabled) { - this.#isEnabled = false; - for (const layer of this.#allLayers.values()) { - layer.disable(); - } - for (const editor of this.#allEditors.values()) { - editor.disable(); - } - } - } - getEditors(pageIndex) { - const editors = []; - for (const editor of this.#allEditors.values()) { - if (editor.pageIndex === pageIndex) { - editors.push(editor); - } - } - return editors; - } - getEditor(id) { - return this.#allEditors.get(id); - } - addEditor(editor) { - this.#allEditors.set(editor.id, editor); - } - removeEditor(editor) { - if (editor.div.contains(document.activeElement)) { - if (this.#focusMainContainerTimeoutId) { - clearTimeout(this.#focusMainContainerTimeoutId); - } - this.#focusMainContainerTimeoutId = setTimeout(() => { - this.focusMainContainer(); - this.#focusMainContainerTimeoutId = null; - }, 0); - } - this.#allEditors.delete(editor.id); - this.unselect(editor); - if (!editor.annotationElementId || !this.#deletedAnnotationsElementIds.has(editor.annotationElementId)) { - this.#annotationStorage?.remove(editor.id); - } - } - addDeletedAnnotationElement(editor) { - this.#deletedAnnotationsElementIds.add(editor.annotationElementId); - this.addChangedExistingAnnotation(editor); - editor.deleted = true; - } - isDeletedAnnotationElement(annotationElementId) { - return this.#deletedAnnotationsElementIds.has(annotationElementId); - } - removeDeletedAnnotationElement(editor) { - this.#deletedAnnotationsElementIds.delete(editor.annotationElementId); - this.removeChangedExistingAnnotation(editor); - editor.deleted = false; - } - #addEditorToLayer(editor) { - const layer = this.#allLayers.get(editor.pageIndex); - if (layer) { - layer.addOrRebuild(editor); - } else { - this.addEditor(editor); - this.addToAnnotationStorage(editor); - } - } - setActiveEditor(editor) { - if (this.#activeEditor === editor) { - return; - } - this.#activeEditor = editor; - if (editor) { - this.#dispatchUpdateUI(editor.propertiesToUpdate); - } - } - get #lastSelectedEditor() { - let ed = null; - for (ed of this.#selectedEditors) {} - return ed; - } - updateUI(editor) { - if (this.#lastSelectedEditor === editor) { - this.#dispatchUpdateUI(editor.propertiesToUpdate); - } - } - toggleSelected(editor) { - if (this.#selectedEditors.has(editor)) { - this.#selectedEditors.delete(editor); - editor.unselect(); - this.#dispatchUpdateStates({ - hasSelectedEditor: this.hasSelection - }); - return; - } - this.#selectedEditors.add(editor); - editor.select(); - this.#dispatchUpdateUI(editor.propertiesToUpdate); - this.#dispatchUpdateStates({ - hasSelectedEditor: true - }); - } - setSelected(editor) { - for (const ed of this.#selectedEditors) { - if (ed !== editor) { - ed.unselect(); - } - } - this.#selectedEditors.clear(); - this.#selectedEditors.add(editor); - editor.select(); - this.#dispatchUpdateUI(editor.propertiesToUpdate); - this.#dispatchUpdateStates({ - hasSelectedEditor: true - }); - } - isSelected(editor) { - return this.#selectedEditors.has(editor); - } - get firstSelectedEditor() { - return this.#selectedEditors.values().next().value; - } - unselect(editor) { - editor.unselect(); - this.#selectedEditors.delete(editor); - this.#dispatchUpdateStates({ - hasSelectedEditor: this.hasSelection - }); - } - get hasSelection() { - return this.#selectedEditors.size !== 0; - } - get isEnterHandled() { - return this.#selectedEditors.size === 1 && this.firstSelectedEditor.isEnterHandled; - } - undo() { - this.#commandManager.undo(); - this.#dispatchUpdateStates({ - hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(), - hasSomethingToRedo: true, - isEmpty: this.#isEmpty() - }); - } - redo() { - this.#commandManager.redo(); - this.#dispatchUpdateStates({ - hasSomethingToUndo: true, - hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(), - isEmpty: this.#isEmpty() - }); - } - addCommands(params) { - this.#commandManager.add(params); - this.#dispatchUpdateStates({ - hasSomethingToUndo: true, - hasSomethingToRedo: false, - isEmpty: this.#isEmpty() - }); - } - #isEmpty() { - if (this.#allEditors.size === 0) { - return true; - } - if (this.#allEditors.size === 1) { - for (const editor of this.#allEditors.values()) { - return editor.isEmpty(); - } - } - return false; - } - delete() { - this.commitOrRemove(); - if (!this.hasSelection) { - return; - } - const editors = [...this.#selectedEditors]; - const cmd = () => { - for (const editor of editors) { - editor.remove(); - } - }; - const undo = () => { - for (const editor of editors) { - this.#addEditorToLayer(editor); - } - }; - this.addCommands({ - cmd, - undo, - mustExec: true - }); - } - commitOrRemove() { - this.#activeEditor?.commitOrRemove(); - } - hasSomethingToControl() { - return this.#activeEditor || this.hasSelection; - } - #selectEditors(editors) { - for (const editor of this.#selectedEditors) { - editor.unselect(); - } - this.#selectedEditors.clear(); - for (const editor of editors) { - if (editor.isEmpty()) { - continue; - } - this.#selectedEditors.add(editor); - editor.select(); - } - this.#dispatchUpdateStates({ - hasSelectedEditor: this.hasSelection - }); - } - selectAll() { - for (const editor of this.#selectedEditors) { - editor.commit(); - } - this.#selectEditors(this.#allEditors.values()); - } - unselectAll() { - if (this.#activeEditor) { - this.#activeEditor.commitOrRemove(); - if (this.#mode !== _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) { - return; - } - } - if (!this.hasSelection) { - return; - } - for (const editor of this.#selectedEditors) { - editor.unselect(); - } - this.#selectedEditors.clear(); - this.#dispatchUpdateStates({ - hasSelectedEditor: false - }); - } - translateSelectedEditors(x, y, noCommit = false) { - if (!noCommit) { - this.commitOrRemove(); - } - if (!this.hasSelection) { - return; - } - this.#translation[0] += x; - this.#translation[1] += y; - const [totalX, totalY] = this.#translation; - const editors = [...this.#selectedEditors]; - const TIME_TO_WAIT = 1000; - if (this.#translationTimeoutId) { - clearTimeout(this.#translationTimeoutId); - } - this.#translationTimeoutId = setTimeout(() => { - this.#translationTimeoutId = null; - this.#translation[0] = this.#translation[1] = 0; - this.addCommands({ - cmd: () => { - for (const editor of editors) { - if (this.#allEditors.has(editor.id)) { - editor.translateInPage(totalX, totalY); - } - } - }, - undo: () => { - for (const editor of editors) { - if (this.#allEditors.has(editor.id)) { - editor.translateInPage(-totalX, -totalY); - } - } - }, - mustExec: false - }); - }, TIME_TO_WAIT); - for (const editor of editors) { - editor.translateInPage(x, y); - } - } - setUpDragSession() { - if (!this.hasSelection) { - return; - } - this.disableUserSelect(true); - this.#draggingEditors = new Map(); - for (const editor of this.#selectedEditors) { - this.#draggingEditors.set(editor, { - savedX: editor.x, - savedY: editor.y, - savedPageIndex: editor.pageIndex, - newX: 0, - newY: 0, - newPageIndex: -1 - }); - } - } - endDragSession() { - if (!this.#draggingEditors) { - return false; - } - this.disableUserSelect(false); - const map = this.#draggingEditors; - this.#draggingEditors = null; - let mustBeAddedInUndoStack = false; - for (const [{ - x, - y, - pageIndex - }, value] of map) { - value.newX = x; - value.newY = y; - value.newPageIndex = pageIndex; - mustBeAddedInUndoStack ||= x !== value.savedX || y !== value.savedY || pageIndex !== value.savedPageIndex; - } - if (!mustBeAddedInUndoStack) { - return false; - } - const move = (editor, x, y, pageIndex) => { - if (this.#allEditors.has(editor.id)) { - const parent = this.#allLayers.get(pageIndex); - if (parent) { - editor._setParentAndPosition(parent, x, y); - } else { - editor.pageIndex = pageIndex; - editor.x = x; - editor.y = y; - } - } - }; - this.addCommands({ - cmd: () => { - for (const [editor, { - newX, - newY, - newPageIndex - }] of map) { - move(editor, newX, newY, newPageIndex); - } - }, - undo: () => { - for (const [editor, { - savedX, - savedY, - savedPageIndex - }] of map) { - move(editor, savedX, savedY, savedPageIndex); - } - }, - mustExec: true - }); - return true; - } - dragSelectedEditors(tx, ty) { - if (!this.#draggingEditors) { - return; - } - for (const editor of this.#draggingEditors.keys()) { - editor.drag(tx, ty); - } - } - rebuild(editor) { - if (editor.parent === null) { - const parent = this.getLayer(editor.pageIndex); - if (parent) { - parent.changeParent(editor); - parent.addOrRebuild(editor); - } else { - this.addEditor(editor); - this.addToAnnotationStorage(editor); - editor.rebuild(); - } - } else { - editor.parent.addOrRebuild(editor); - } - } - get isEditorHandlingKeyboard() { - return this.getActive()?.shouldGetKeyboardEvents() || this.#selectedEditors.size === 1 && this.firstSelectedEditor.shouldGetKeyboardEvents(); - } - isActive(editor) { - return this.#activeEditor === editor; - } - getActive() { - return this.#activeEditor; - } - getMode() { - return this.#mode; - } - get imageManager() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "imageManager", new ImageManager()); - } - getSelectionBoxes(textLayer) { - if (!textLayer) { - return null; - } - const selection = document.getSelection(); - for (let i = 0, ii = selection.rangeCount; i < ii; i++) { - if (!textLayer.contains(selection.getRangeAt(i).commonAncestorContainer)) { - return null; - } - } - const { - x: layerX, - y: layerY, - width: parentWidth, - height: parentHeight - } = textLayer.getBoundingClientRect(); - let rotator; - switch (textLayer.getAttribute("data-main-rotation")) { - case "90": - rotator = (x, y, w, h) => ({ - x: (y - layerY) / parentHeight, - y: 1 - (x + w - layerX) / parentWidth, - width: h / parentHeight, - height: w / parentWidth - }); - break; - case "180": - rotator = (x, y, w, h) => ({ - x: 1 - (x + w - layerX) / parentWidth, - y: 1 - (y + h - layerY) / parentHeight, - width: w / parentWidth, - height: h / parentHeight - }); - break; - case "270": - rotator = (x, y, w, h) => ({ - x: 1 - (y + h - layerY) / parentHeight, - y: (x - layerX) / parentWidth, - width: h / parentHeight, - height: w / parentWidth - }); - break; - default: - rotator = (x, y, w, h) => ({ - x: (x - layerX) / parentWidth, - y: (y - layerY) / parentHeight, - width: w / parentWidth, - height: h / parentHeight - }); - break; - } - const boxes = []; - for (let i = 0, ii = selection.rangeCount; i < ii; i++) { - const range = selection.getRangeAt(i); - if (range.collapsed) { - continue; - } - for (const { - x, - y, - width, - height - } of range.getClientRects()) { - if (width === 0 || height === 0) { - continue; - } - boxes.push(rotator(x, y, width, height)); - } - } - return boxes.length === 0 ? null : boxes; - } - addChangedExistingAnnotation({ - annotationElementId, - id - }) { - (this.#changedExistingAnnotations ||= new Map()).set(annotationElementId, id); - } - removeChangedExistingAnnotation({ - annotationElementId - }) { - this.#changedExistingAnnotations?.delete(annotationElementId); - } - renderAnnotationElement(annotation) { - const editorId = this.#changedExistingAnnotations?.get(annotation.data.id); - if (!editorId) { - return; - } - const editor = this.#annotationStorage.getRawValue(editorId); - if (!editor) { - return; - } - if (this.#mode === _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE && !editor.hasBeenModified) { - return; - } - editor.renderAnnotationElement(annotation); - } -} - - -/***/ }), - -/***/ 94: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFFetchStream: () => (/* binding */ PDFFetchStream) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _network_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(490); - - -function createFetchOptions(headers, withCredentials, abortController) { - return { - method: "GET", - headers, - signal: abortController.signal, - mode: "cors", - credentials: withCredentials ? "include" : "same-origin", - redirect: "follow" - }; -} -function createHeaders(httpHeaders) { - const headers = new Headers(); - for (const property in httpHeaders) { - const value = httpHeaders[property]; - if (value === undefined) { - continue; - } - headers.append(property, value); - } - return headers; -} -function getArrayBuffer(val) { - if (val instanceof Uint8Array) { - return val.buffer; - } - if (val instanceof ArrayBuffer) { - return val; - } - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`getArrayBuffer - unexpected data format: ${val}`); - return new Uint8Array(val).buffer; -} -class PDFFetchStream { - constructor(source) { - this.source = source; - this.isHttp = /^https?:/i.test(source.url); - this.httpHeaders = this.isHttp && source.httpHeaders || {}; - this._fullRequestReader = null; - this._rangeRequestReaders = []; - } - get _progressiveDataLength() { - return this._fullRequestReader?._loaded ?? 0; - } - getFullReader() { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!this._fullRequestReader, "PDFFetchStream.getFullReader can only be called once."); - this._fullRequestReader = new PDFFetchStreamReader(this); - return this._fullRequestReader; - } - getRangeReader(begin, end) { - if (end <= this._progressiveDataLength) { - return null; - } - const reader = new PDFFetchStreamRangeReader(this, begin, end); - this._rangeRequestReaders.push(reader); - return reader; - } - cancelAllRequests(reason) { - this._fullRequestReader?.cancel(reason); - for (const reader of this._rangeRequestReaders.slice(0)) { - reader.cancel(reason); - } - } -} -class PDFFetchStreamReader { - constructor(stream) { - this._stream = stream; - this._reader = null; - this._loaded = 0; - this._filename = null; - const source = stream.source; - this._withCredentials = source.withCredentials || false; - this._contentLength = source.length; - this._headersCapability = Promise.withResolvers(); - this._disableRange = source.disableRange || false; - this._rangeChunkSize = source.rangeChunkSize; - if (!this._rangeChunkSize && !this._disableRange) { - this._disableRange = true; - } - this._abortController = new AbortController(); - this._isStreamingSupported = !source.disableStream; - this._isRangeSupported = !source.disableRange; - this._headers = createHeaders(this._stream.httpHeaders); - const url = source.url; - fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(response => { - if (!(0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateResponseStatus)(response.status)) { - throw (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.createResponseStatusError)(response.status, url); - } - this._reader = response.body.getReader(); - this._headersCapability.resolve(); - const getResponseHeader = name => response.headers.get(name); - const { - allowRangeRequests, - suggestedLength - } = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateRangeRequestCapabilities)({ - getResponseHeader, - isHttp: this._stream.isHttp, - rangeChunkSize: this._rangeChunkSize, - disableRange: this._disableRange - }); - this._isRangeSupported = allowRangeRequests; - this._contentLength = suggestedLength || this._contentLength; - this._filename = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.extractFilenameFromHeader)(getResponseHeader); - if (!this._isStreamingSupported && this._isRangeSupported) { - this.cancel(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException("Streaming is disabled.")); - } - }).catch(this._headersCapability.reject); - this.onProgress = null; - } - get headersReady() { - return this._headersCapability.promise; - } - get filename() { - return this._filename; - } - get contentLength() { - return this._contentLength; - } - get isRangeSupported() { - return this._isRangeSupported; - } - get isStreamingSupported() { - return this._isStreamingSupported; - } - async read() { - await this._headersCapability.promise; - const { - value, - done - } = await this._reader.read(); - if (done) { - return { - value, - done - }; - } - this._loaded += value.byteLength; - this.onProgress?.({ - loaded: this._loaded, - total: this._contentLength - }); - return { - value: getArrayBuffer(value), - done: false - }; - } - cancel(reason) { - this._reader?.cancel(reason); - this._abortController.abort(); - } -} -class PDFFetchStreamRangeReader { - constructor(stream, begin, end) { - this._stream = stream; - this._reader = null; - this._loaded = 0; - const source = stream.source; - this._withCredentials = source.withCredentials || false; - this._readCapability = Promise.withResolvers(); - this._isStreamingSupported = !source.disableStream; - this._abortController = new AbortController(); - this._headers = createHeaders(this._stream.httpHeaders); - this._headers.append("Range", `bytes=${begin}-${end - 1}`); - const url = source.url; - fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(response => { - if (!(0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateResponseStatus)(response.status)) { - throw (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.createResponseStatusError)(response.status, url); - } - this._readCapability.resolve(); - this._reader = response.body.getReader(); - }).catch(this._readCapability.reject); - this.onProgress = null; - } - get isStreamingSupported() { - return this._isStreamingSupported; - } - async read() { - await this._readCapability.promise; - const { - value, - done - } = await this._reader.read(); - if (done) { - return { - value, - done - }; - } - this._loaded += value.byteLength; - this.onProgress?.({ - loaded: this._loaded - }); - return { - value: getArrayBuffer(value), - done: false - }; - } - cancel(reason) { - this._reader?.cancel(reason); - this._abortController.abort(); - } -} - - -/***/ }), - -/***/ 10: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ FontFaceObject: () => (/* binding */ FontFaceObject), -/* harmony export */ FontLoader: () => (/* binding */ FontLoader) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); - -class FontLoader { - #systemFonts = new Set(); - constructor({ - ownerDocument = globalThis.document, - styleElement = null - }) { - this._document = ownerDocument; - this.nativeFontFaces = new Set(); - this.styleElement = null; - this.loadingRequests = []; - this.loadTestFontId = 0; - } - addNativeFontFace(nativeFontFace) { - this.nativeFontFaces.add(nativeFontFace); - this._document.fonts.add(nativeFontFace); - } - removeNativeFontFace(nativeFontFace) { - this.nativeFontFaces.delete(nativeFontFace); - this._document.fonts.delete(nativeFontFace); - } - insertRule(rule) { - if (!this.styleElement) { - this.styleElement = this._document.createElement("style"); - this._document.documentElement.getElementsByTagName("head")[0].append(this.styleElement); - } - const styleSheet = this.styleElement.sheet; - styleSheet.insertRule(rule, styleSheet.cssRules.length); - } - clear() { - for (const nativeFontFace of this.nativeFontFaces) { - this._document.fonts.delete(nativeFontFace); - } - this.nativeFontFaces.clear(); - this.#systemFonts.clear(); - if (this.styleElement) { - this.styleElement.remove(); - this.styleElement = null; - } - } - async loadSystemFont({ - systemFontInfo: info, - _inspectFont - }) { - if (!info || this.#systemFonts.has(info.loadedName)) { - return; - } - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!this.disableFontFace, "loadSystemFont shouldn't be called when `disableFontFace` is set."); - if (this.isFontLoadingAPISupported) { - const { - loadedName, - src, - style - } = info; - const fontFace = new FontFace(loadedName, src, style); - this.addNativeFontFace(fontFace); - try { - await fontFace.load(); - this.#systemFonts.add(loadedName); - _inspectFont?.(info); - } catch { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Cannot load system font: ${info.baseFontName}, installing it could help to improve PDF rendering.`); - this.removeNativeFontFace(fontFace); - } - return; - } - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Not implemented: loadSystemFont without the Font Loading API."); - } - async bind(font) { - if (font.attached || font.missingFile && !font.systemFontInfo) { - return; - } - font.attached = true; - if (font.systemFontInfo) { - await this.loadSystemFont(font); - return; - } - if (this.isFontLoadingAPISupported) { - const nativeFontFace = font.createNativeFontFace(); - if (nativeFontFace) { - this.addNativeFontFace(nativeFontFace); - try { - await nativeFontFace.loaded; - } catch (ex) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Failed to load font '${nativeFontFace.family}': '${ex}'.`); - font.disableFontFace = true; - throw ex; - } - } - return; - } - const rule = font.createFontFaceRule(); - if (rule) { - this.insertRule(rule); - if (this.isSyncFontLoadingSupported) { - return; - } - await new Promise(resolve => { - const request = this._queueLoadingCallback(resolve); - this._prepareFontLoadEvent(font, request); - }); - } - } - get isFontLoadingAPISupported() { - const hasFonts = !!this._document?.fonts; - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "isFontLoadingAPISupported", hasFonts); - } - get isSyncFontLoadingSupported() { - let supported = false; - if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS) { - supported = true; - } else if (typeof navigator !== "undefined" && typeof navigator?.userAgent === "string" && /Mozilla\/5.0.*?rv:\d+.*? Gecko/.test(navigator.userAgent)) { - supported = true; - } - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "isSyncFontLoadingSupported", supported); - } - _queueLoadingCallback(callback) { - function completeRequest() { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!request.done, "completeRequest() cannot be called twice."); - request.done = true; - while (loadingRequests.length > 0 && loadingRequests[0].done) { - const otherRequest = loadingRequests.shift(); - setTimeout(otherRequest.callback, 0); - } - } - const { - loadingRequests - } = this; - const request = { - done: false, - complete: completeRequest, - callback - }; - loadingRequests.push(request); - return request; - } - get _loadTestFont() { - const testFont = atob("T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA" + "FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA" + "ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA" + "AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1" + "AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD" + "6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM" + "AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D" + "IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA" + "AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA" + "AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB" + "AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY" + "AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA" + "AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA" + "AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC" + "AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3" + "Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj" + "FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA=="); - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "_loadTestFont", testFont); - } - _prepareFontLoadEvent(font, request) { - function int32(data, offset) { - return data.charCodeAt(offset) << 24 | data.charCodeAt(offset + 1) << 16 | data.charCodeAt(offset + 2) << 8 | data.charCodeAt(offset + 3) & 0xff; - } - function spliceString(s, offset, remove, insert) { - const chunk1 = s.substring(0, offset); - const chunk2 = s.substring(offset + remove); - return chunk1 + insert + chunk2; - } - let i, ii; - const canvas = this._document.createElement("canvas"); - canvas.width = 1; - canvas.height = 1; - const ctx = canvas.getContext("2d"); - let called = 0; - function isFontReady(name, callback) { - if (++called > 30) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)("Load test font never loaded."); - callback(); - return; - } - ctx.font = "30px " + name; - ctx.fillText(".", 0, 20); - const imageData = ctx.getImageData(0, 0, 1, 1); - if (imageData.data[3] > 0) { - callback(); - return; - } - setTimeout(isFontReady.bind(null, name, callback)); - } - const loadTestFontId = `lt${Date.now()}${this.loadTestFontId++}`; - let data = this._loadTestFont; - const COMMENT_OFFSET = 976; - data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, loadTestFontId); - const CFF_CHECKSUM_OFFSET = 16; - const XXXX_VALUE = 0x58585858; - let checksum = int32(data, CFF_CHECKSUM_OFFSET); - for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) { - checksum = checksum - XXXX_VALUE + int32(loadTestFontId, i) | 0; - } - if (i < loadTestFontId.length) { - checksum = checksum - XXXX_VALUE + int32(loadTestFontId + "XXX", i) | 0; - } - data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.string32)(checksum)); - const url = `url(data:font/opentype;base64,${btoa(data)});`; - const rule = `@font-face {font-family:"${loadTestFontId}";src:${url}}`; - this.insertRule(rule); - const div = this._document.createElement("div"); - div.style.visibility = "hidden"; - div.style.width = div.style.height = "10px"; - div.style.position = "absolute"; - div.style.top = div.style.left = "0px"; - for (const name of [font.loadedName, loadTestFontId]) { - const span = this._document.createElement("span"); - span.textContent = "Hi"; - span.style.fontFamily = name; - div.append(span); - } - this._document.body.append(div); - isFontReady(loadTestFontId, () => { - div.remove(); - request.complete(); - }); - } -} -class FontFaceObject { - constructor(translatedData, { - disableFontFace = false, - ignoreErrors = false, - inspectFont = null - }) { - this.compiledGlyphs = Object.create(null); - for (const i in translatedData) { - this[i] = translatedData[i]; - } - this.disableFontFace = disableFontFace === true; - this.ignoreErrors = ignoreErrors === true; - this._inspectFont = inspectFont; - } - createNativeFontFace() { - if (!this.data || this.disableFontFace) { - return null; - } - let nativeFontFace; - if (!this.cssFontInfo) { - nativeFontFace = new FontFace(this.loadedName, this.data, {}); - } else { - const css = { - weight: this.cssFontInfo.fontWeight - }; - if (this.cssFontInfo.italicAngle) { - css.style = `oblique ${this.cssFontInfo.italicAngle}deg`; - } - nativeFontFace = new FontFace(this.cssFontInfo.fontFamily, this.data, css); - } - this._inspectFont?.(this); - return nativeFontFace; - } - createFontFaceRule() { - if (!this.data || this.disableFontFace) { - return null; - } - const data = (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.bytesToString)(this.data); - const url = `url(data:${this.mimetype};base64,${btoa(data)});`; - let rule; - if (!this.cssFontInfo) { - rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`; - } else { - let css = `font-weight: ${this.cssFontInfo.fontWeight};`; - if (this.cssFontInfo.italicAngle) { - css += `font-style: oblique ${this.cssFontInfo.italicAngle}deg;`; - } - rule = `@font-face {font-family:"${this.cssFontInfo.fontFamily}";${css}src:${url}}`; - } - this._inspectFont?.(this, url); - return rule; - } - getPathGenerator(objs, character) { - if (this.compiledGlyphs[character] !== undefined) { - return this.compiledGlyphs[character]; - } - let cmds; - try { - cmds = objs.get(this.loadedName + "_path_" + character); - } catch (ex) { - if (!this.ignoreErrors) { - throw ex; - } - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`getPathGenerator - ignoring character: "${ex}".`); - } - if (!Array.isArray(cmds) || cmds.length === 0) { - return this.compiledGlyphs[character] = function (c, size) {}; - } - const commands = []; - for (let i = 0, ii = cmds.length; i < ii;) { - switch (cmds[i++]) { - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.BEZIER_CURVE_TO: - { - const [a, b, c, d, e, f] = cmds.slice(i, i + 6); - commands.push(ctx => ctx.bezierCurveTo(a, b, c, d, e, f)); - i += 6; - } - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.MOVE_TO: - { - const [a, b] = cmds.slice(i, i + 2); - commands.push(ctx => ctx.moveTo(a, b)); - i += 2; - } - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.LINE_TO: - { - const [a, b] = cmds.slice(i, i + 2); - commands.push(ctx => ctx.lineTo(a, b)); - i += 2; - } - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.QUADRATIC_CURVE_TO: - { - const [a, b, c, d] = cmds.slice(i, i + 4); - commands.push(ctx => ctx.quadraticCurveTo(a, b, c, d)); - i += 4; - } - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.RESTORE: - commands.push(ctx => ctx.restore()); - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.SAVE: - commands.push(ctx => ctx.save()); - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.SCALE: - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(commands.length === 2, "Scale command is only valid at the third position."); - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.TRANSFORM: - { - const [a, b, c, d, e, f] = cmds.slice(i, i + 6); - commands.push(ctx => ctx.transform(a, b, c, d, e, f)); - i += 6; - } - break; - case _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FontRenderOps.TRANSLATE: - { - const [a, b] = cmds.slice(i, i + 2); - commands.push(ctx => ctx.translate(a, b)); - i += 2; - } - break; - } - } - return this.compiledGlyphs[character] = function glyphDrawer(ctx, size) { - commands[0](ctx); - commands[1](ctx); - ctx.scale(size, -size); - for (let i = 2, ii = commands.length; i < ii; i++) { - commands[i](ctx); - } - }; - } -} - - -/***/ }), - -/***/ 62: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ Metadata: () => (/* binding */ Metadata) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); - -class Metadata { - #metadataMap; - #data; - constructor({ - parsedData, - rawData - }) { - this.#metadataMap = parsedData; - this.#data = rawData; - } - getRaw() { - return this.#data; - } - get(name) { - return this.#metadataMap.get(name) ?? null; - } - getAll() { - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.objectFromMap)(this.#metadataMap); - } - has(name) { - return this.#metadataMap.has(name); - } -} - - -/***/ }), - -/***/ 457: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFNetworkStream: () => (/* binding */ PDFNetworkStream) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _network_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(490); - - -const OK_RESPONSE = 200; -const PARTIAL_CONTENT_RESPONSE = 206; -function getArrayBuffer(xhr) { - const data = xhr.response; - if (typeof data !== "string") { - return data; - } - return (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.stringToBytes)(data).buffer; -} -class NetworkManager { - constructor(url, args = {}) { - this.url = url; - this.isHttp = /^https?:/i.test(url); - this.httpHeaders = this.isHttp && args.httpHeaders || Object.create(null); - this.withCredentials = args.withCredentials || false; - this.currXhrId = 0; - this.pendingRequests = Object.create(null); - } - requestRange(begin, end, listeners) { - const args = { - begin, - end - }; - for (const prop in listeners) { - args[prop] = listeners[prop]; - } - return this.request(args); - } - requestFull(listeners) { - return this.request(listeners); - } - request(args) { - const xhr = new XMLHttpRequest(); - const xhrId = this.currXhrId++; - const pendingRequest = this.pendingRequests[xhrId] = { - xhr - }; - xhr.open("GET", this.url); - xhr.withCredentials = this.withCredentials; - for (const property in this.httpHeaders) { - const value = this.httpHeaders[property]; - if (value === undefined) { - continue; - } - xhr.setRequestHeader(property, value); - } - if (this.isHttp && "begin" in args && "end" in args) { - xhr.setRequestHeader("Range", `bytes=${args.begin}-${args.end - 1}`); - pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE; - } else { - pendingRequest.expectedStatus = OK_RESPONSE; - } - xhr.responseType = "arraybuffer"; - if (args.onError) { - xhr.onerror = function (evt) { - args.onError(xhr.status); - }; - } - xhr.onreadystatechange = this.onStateChange.bind(this, xhrId); - xhr.onprogress = this.onProgress.bind(this, xhrId); - pendingRequest.onHeadersReceived = args.onHeadersReceived; - pendingRequest.onDone = args.onDone; - pendingRequest.onError = args.onError; - pendingRequest.onProgress = args.onProgress; - xhr.send(null); - return xhrId; - } - onProgress(xhrId, evt) { - const pendingRequest = this.pendingRequests[xhrId]; - if (!pendingRequest) { - return; - } - pendingRequest.onProgress?.(evt); - } - onStateChange(xhrId, evt) { - const pendingRequest = this.pendingRequests[xhrId]; - if (!pendingRequest) { - return; - } - const xhr = pendingRequest.xhr; - if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) { - pendingRequest.onHeadersReceived(); - delete pendingRequest.onHeadersReceived; - } - if (xhr.readyState !== 4) { - return; - } - if (!(xhrId in this.pendingRequests)) { - return; - } - delete this.pendingRequests[xhrId]; - if (xhr.status === 0 && this.isHttp) { - pendingRequest.onError?.(xhr.status); - return; - } - const xhrStatus = xhr.status || OK_RESPONSE; - const ok_response_on_range_request = xhrStatus === OK_RESPONSE && pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE; - if (!ok_response_on_range_request && xhrStatus !== pendingRequest.expectedStatus) { - pendingRequest.onError?.(xhr.status); - return; - } - const chunk = getArrayBuffer(xhr); - if (xhrStatus === PARTIAL_CONTENT_RESPONSE) { - const rangeHeader = xhr.getResponseHeader("Content-Range"); - const matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); - pendingRequest.onDone({ - begin: parseInt(matches[1], 10), - chunk - }); - } else if (chunk) { - pendingRequest.onDone({ - begin: 0, - chunk - }); - } else { - pendingRequest.onError?.(xhr.status); - } - } - getRequestXhr(xhrId) { - return this.pendingRequests[xhrId].xhr; - } - isPendingRequest(xhrId) { - return xhrId in this.pendingRequests; - } - abortRequest(xhrId) { - const xhr = this.pendingRequests[xhrId].xhr; - delete this.pendingRequests[xhrId]; - xhr.abort(); - } -} -class PDFNetworkStream { - constructor(source) { - this._source = source; - this._manager = new NetworkManager(source.url, { - httpHeaders: source.httpHeaders, - withCredentials: source.withCredentials - }); - this._rangeChunkSize = source.rangeChunkSize; - this._fullRequestReader = null; - this._rangeRequestReaders = []; - } - _onRangeRequestReaderClosed(reader) { - const i = this._rangeRequestReaders.indexOf(reader); - if (i >= 0) { - this._rangeRequestReaders.splice(i, 1); - } - } - getFullReader() { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!this._fullRequestReader, "PDFNetworkStream.getFullReader can only be called once."); - this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this._manager, this._source); - return this._fullRequestReader; - } - getRangeReader(begin, end) { - const reader = new PDFNetworkStreamRangeRequestReader(this._manager, begin, end); - reader.onClosed = this._onRangeRequestReaderClosed.bind(this); - this._rangeRequestReaders.push(reader); - return reader; - } - cancelAllRequests(reason) { - this._fullRequestReader?.cancel(reason); - for (const reader of this._rangeRequestReaders.slice(0)) { - reader.cancel(reason); - } - } -} -class PDFNetworkStreamFullRequestReader { - constructor(manager, source) { - this._manager = manager; - const args = { - onHeadersReceived: this._onHeadersReceived.bind(this), - onDone: this._onDone.bind(this), - onError: this._onError.bind(this), - onProgress: this._onProgress.bind(this) - }; - this._url = source.url; - this._fullRequestId = manager.requestFull(args); - this._headersReceivedCapability = Promise.withResolvers(); - this._disableRange = source.disableRange || false; - this._contentLength = source.length; - this._rangeChunkSize = source.rangeChunkSize; - if (!this._rangeChunkSize && !this._disableRange) { - this._disableRange = true; - } - this._isStreamingSupported = false; - this._isRangeSupported = false; - this._cachedChunks = []; - this._requests = []; - this._done = false; - this._storedError = undefined; - this._filename = null; - this.onProgress = null; - } - _onHeadersReceived() { - const fullRequestXhrId = this._fullRequestId; - const fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId); - const getResponseHeader = name => fullRequestXhr.getResponseHeader(name); - const { - allowRangeRequests, - suggestedLength - } = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateRangeRequestCapabilities)({ - getResponseHeader, - isHttp: this._manager.isHttp, - rangeChunkSize: this._rangeChunkSize, - disableRange: this._disableRange - }); - if (allowRangeRequests) { - this._isRangeSupported = true; - } - this._contentLength = suggestedLength || this._contentLength; - this._filename = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.extractFilenameFromHeader)(getResponseHeader); - if (this._isRangeSupported) { - this._manager.abortRequest(fullRequestXhrId); - } - this._headersReceivedCapability.resolve(); - } - _onDone(data) { - if (data) { - if (this._requests.length > 0) { - const requestCapability = this._requests.shift(); - requestCapability.resolve({ - value: data.chunk, - done: false - }); - } else { - this._cachedChunks.push(data.chunk); - } - } - this._done = true; - if (this._cachedChunks.length > 0) { - return; - } - for (const requestCapability of this._requests) { - requestCapability.resolve({ - value: undefined, - done: true - }); - } - this._requests.length = 0; - } - _onError(status) { - this._storedError = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.createResponseStatusError)(status, this._url); - this._headersReceivedCapability.reject(this._storedError); - for (const requestCapability of this._requests) { - requestCapability.reject(this._storedError); - } - this._requests.length = 0; - this._cachedChunks.length = 0; - } - _onProgress(evt) { - this.onProgress?.({ - loaded: evt.loaded, - total: evt.lengthComputable ? evt.total : this._contentLength - }); - } - get filename() { - return this._filename; - } - get isRangeSupported() { - return this._isRangeSupported; - } - get isStreamingSupported() { - return this._isStreamingSupported; - } - get contentLength() { - return this._contentLength; - } - get headersReady() { - return this._headersReceivedCapability.promise; - } - async read() { - if (this._storedError) { - throw this._storedError; - } - if (this._cachedChunks.length > 0) { - const chunk = this._cachedChunks.shift(); - return { - value: chunk, - done: false - }; - } - if (this._done) { - return { - value: undefined, - done: true - }; - } - const requestCapability = Promise.withResolvers(); - this._requests.push(requestCapability); - return requestCapability.promise; - } - cancel(reason) { - this._done = true; - this._headersReceivedCapability.reject(reason); - for (const requestCapability of this._requests) { - requestCapability.resolve({ - value: undefined, - done: true - }); - } - this._requests.length = 0; - if (this._manager.isPendingRequest(this._fullRequestId)) { - this._manager.abortRequest(this._fullRequestId); - } - this._fullRequestReader = null; - } -} -class PDFNetworkStreamRangeRequestReader { - constructor(manager, begin, end) { - this._manager = manager; - const args = { - onDone: this._onDone.bind(this), - onError: this._onError.bind(this), - onProgress: this._onProgress.bind(this) - }; - this._url = manager.url; - this._requestId = manager.requestRange(begin, end, args); - this._requests = []; - this._queuedChunk = null; - this._done = false; - this._storedError = undefined; - this.onProgress = null; - this.onClosed = null; - } - _close() { - this.onClosed?.(this); - } - _onDone(data) { - const chunk = data.chunk; - if (this._requests.length > 0) { - const requestCapability = this._requests.shift(); - requestCapability.resolve({ - value: chunk, - done: false - }); - } else { - this._queuedChunk = chunk; - } - this._done = true; - for (const requestCapability of this._requests) { - requestCapability.resolve({ - value: undefined, - done: true - }); - } - this._requests.length = 0; - this._close(); - } - _onError(status) { - this._storedError = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.createResponseStatusError)(status, this._url); - for (const requestCapability of this._requests) { - requestCapability.reject(this._storedError); - } - this._requests.length = 0; - this._queuedChunk = null; - } - _onProgress(evt) { - if (!this.isStreamingSupported) { - this.onProgress?.({ - loaded: evt.loaded - }); - } - } - get isStreamingSupported() { - return false; - } - async read() { - if (this._storedError) { - throw this._storedError; - } - if (this._queuedChunk !== null) { - const chunk = this._queuedChunk; - this._queuedChunk = null; - return { - value: chunk, - done: false - }; - } - if (this._done) { - return { - value: undefined, - done: true - }; - } - const requestCapability = Promise.withResolvers(); - this._requests.push(requestCapability); - return requestCapability.promise; - } - cancel(reason) { - this._done = true; - for (const requestCapability of this._requests) { - requestCapability.resolve({ - value: undefined, - done: true - }); - } - this._requests.length = 0; - if (this._manager.isPendingRequest(this._requestId)) { - this._manager.abortRequest(this._requestId); - } - this._close(); - } -} - - -/***/ }), - -/***/ 490: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - - -// EXPORTS -__webpack_require__.d(__webpack_exports__, { - createResponseStatusError: () => (/* binding */ createResponseStatusError), - extractFilenameFromHeader: () => (/* binding */ extractFilenameFromHeader), - validateRangeRequestCapabilities: () => (/* binding */ validateRangeRequestCapabilities), - validateResponseStatus: () => (/* binding */ validateResponseStatus) -}); - -// EXTERNAL MODULE: ./src/shared/util.js -var util = __webpack_require__(292); -;// CONCATENATED MODULE: ./src/display/content_disposition.js - -function getFilenameFromContentDispositionHeader(contentDisposition) { - let needsEncodingFixup = true; - let tmp = toParamRegExp("filename\\*", "i").exec(contentDisposition); - if (tmp) { - tmp = tmp[1]; - let filename = rfc2616unquote(tmp); - filename = unescape(filename); - filename = rfc5987decode(filename); - filename = rfc2047decode(filename); - return fixupEncoding(filename); - } - tmp = rfc2231getparam(contentDisposition); - if (tmp) { - const filename = rfc2047decode(tmp); - return fixupEncoding(filename); - } - tmp = toParamRegExp("filename", "i").exec(contentDisposition); - if (tmp) { - tmp = tmp[1]; - let filename = rfc2616unquote(tmp); - filename = rfc2047decode(filename); - return fixupEncoding(filename); - } - function toParamRegExp(attributePattern, flags) { - return new RegExp("(?:^|;)\\s*" + attributePattern + "\\s*=\\s*" + "(" + '[^";\\s][^;\\s]*' + "|" + '"(?:[^"\\\\]|\\\\"?)+"?' + ")", flags); - } - function textdecode(encoding, value) { - if (encoding) { - if (!/^[\x00-\xFF]+$/.test(value)) { - return value; - } - try { - const decoder = new TextDecoder(encoding, { - fatal: true - }); - const buffer = (0,util.stringToBytes)(value); - value = decoder.decode(buffer); - needsEncodingFixup = false; - } catch {} - } - return value; - } - function fixupEncoding(value) { - if (needsEncodingFixup && /[\x80-\xff]/.test(value)) { - value = textdecode("utf-8", value); - if (needsEncodingFixup) { - value = textdecode("iso-8859-1", value); - } - } - return value; - } - function rfc2231getparam(contentDispositionStr) { - const matches = []; - let match; - const iter = toParamRegExp("filename\\*((?!0\\d)\\d+)(\\*?)", "ig"); - while ((match = iter.exec(contentDispositionStr)) !== null) { - let [, n, quot, part] = match; - n = parseInt(n, 10); - if (n in matches) { - if (n === 0) { - break; - } - continue; - } - matches[n] = [quot, part]; - } - const parts = []; - for (let n = 0; n < matches.length; ++n) { - if (!(n in matches)) { - break; - } - let [quot, part] = matches[n]; - part = rfc2616unquote(part); - if (quot) { - part = unescape(part); - if (n === 0) { - part = rfc5987decode(part); - } - } - parts.push(part); - } - return parts.join(""); - } - function rfc2616unquote(value) { - if (value.startsWith('"')) { - const parts = value.slice(1).split('\\"'); - for (let i = 0; i < parts.length; ++i) { - const quotindex = parts[i].indexOf('"'); - if (quotindex !== -1) { - parts[i] = parts[i].slice(0, quotindex); - parts.length = i + 1; - } - parts[i] = parts[i].replaceAll(/\\(.)/g, "$1"); - } - value = parts.join('"'); - } - return value; - } - function rfc5987decode(extvalue) { - const encodingend = extvalue.indexOf("'"); - if (encodingend === -1) { - return extvalue; - } - const encoding = extvalue.slice(0, encodingend); - const langvalue = extvalue.slice(encodingend + 1); - const value = langvalue.replace(/^[^']*'/, ""); - return textdecode(encoding, value); - } - function rfc2047decode(value) { - if (!value.startsWith("=?") || /[\x00-\x19\x80-\xff]/.test(value)) { - return value; - } - return value.replaceAll(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g, function (matches, charset, encoding, text) { - if (encoding === "q" || encoding === "Q") { - text = text.replaceAll("_", " "); - text = text.replaceAll(/=([0-9a-fA-F]{2})/g, function (match, hex) { - return String.fromCharCode(parseInt(hex, 16)); - }); - return textdecode(charset, text); - } - try { - text = atob(text); - } catch {} - return textdecode(charset, text); - }); - } - return ""; -} - -// EXTERNAL MODULE: ./src/display/display_utils.js -var display_utils = __webpack_require__(419); -;// CONCATENATED MODULE: ./src/display/network_utils.js - - - -function validateRangeRequestCapabilities({ - getResponseHeader, - isHttp, - rangeChunkSize, - disableRange -}) { - const returnValues = { - allowRangeRequests: false, - suggestedLength: undefined - }; - const length = parseInt(getResponseHeader("Content-Length"), 10); - if (!Number.isInteger(length)) { - return returnValues; - } - returnValues.suggestedLength = length; - if (length <= 2 * rangeChunkSize) { - return returnValues; - } - if (disableRange || !isHttp) { - return returnValues; - } - if (getResponseHeader("Accept-Ranges") !== "bytes") { - return returnValues; - } - const contentEncoding = getResponseHeader("Content-Encoding") || "identity"; - if (contentEncoding !== "identity") { - return returnValues; - } - returnValues.allowRangeRequests = true; - return returnValues; -} -function extractFilenameFromHeader(getResponseHeader) { - const contentDisposition = getResponseHeader("Content-Disposition"); - if (contentDisposition) { - let filename = getFilenameFromContentDispositionHeader(contentDisposition); - if (filename.includes("%")) { - try { - filename = decodeURIComponent(filename); - } catch {} - } - if ((0,display_utils.isPdfFile)(filename)) { - return filename; - } - } - return null; -} -function createResponseStatusError(status, url) { - if (status === 404 || status === 0 && url.startsWith("file:")) { - return new util.MissingPDFException('Missing PDF "' + url + '".'); - } - return new util.UnexpectedResponseException(`Unexpected server response (${status}) while retrieving PDF "${url}".`, status); -} -function validateResponseStatus(status) { - return status === 200 || status === 206; -} - - -/***/ }), - -/***/ 786: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFNodeStream: () => (/* binding */ PDFNodeStream) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _network_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(490); - - -let fs, http, https, url; -if (_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.isNodeJS) { - fs = await import( /*webpackIgnore: true*/"fs"); - http = await import( /*webpackIgnore: true*/"http"); - https = await import( /*webpackIgnore: true*/"https"); - url = await import( /*webpackIgnore: true*/"url"); -} -const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//; -function parseUrl(sourceUrl) { - const parsedUrl = url.parse(sourceUrl); - if (parsedUrl.protocol === "file:" || parsedUrl.host) { - return parsedUrl; - } - if (/^[a-z]:[/\\]/i.test(sourceUrl)) { - return url.parse(`file:///${sourceUrl}`); - } - if (!parsedUrl.host) { - parsedUrl.protocol = "file:"; - } - return parsedUrl; -} -class PDFNodeStream { - constructor(source) { - this.source = source; - this.url = parseUrl(source.url); - this.isHttp = this.url.protocol === "http:" || this.url.protocol === "https:"; - this.isFsUrl = this.url.protocol === "file:"; - this.httpHeaders = this.isHttp && source.httpHeaders || {}; - this._fullRequestReader = null; - this._rangeRequestReaders = []; - } - get _progressiveDataLength() { - return this._fullRequestReader?._loaded ?? 0; - } - getFullReader() { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!this._fullRequestReader, "PDFNodeStream.getFullReader can only be called once."); - this._fullRequestReader = this.isFsUrl ? new PDFNodeStreamFsFullReader(this) : new PDFNodeStreamFullReader(this); - return this._fullRequestReader; - } - getRangeReader(start, end) { - if (end <= this._progressiveDataLength) { - return null; - } - const rangeReader = this.isFsUrl ? new PDFNodeStreamFsRangeReader(this, start, end) : new PDFNodeStreamRangeReader(this, start, end); - this._rangeRequestReaders.push(rangeReader); - return rangeReader; - } - cancelAllRequests(reason) { - this._fullRequestReader?.cancel(reason); - for (const reader of this._rangeRequestReaders.slice(0)) { - reader.cancel(reason); - } - } -} -class BaseFullReader { - constructor(stream) { - this._url = stream.url; - this._done = false; - this._storedError = null; - this.onProgress = null; - const source = stream.source; - this._contentLength = source.length; - this._loaded = 0; - this._filename = null; - this._disableRange = source.disableRange || false; - this._rangeChunkSize = source.rangeChunkSize; - if (!this._rangeChunkSize && !this._disableRange) { - this._disableRange = true; - } - this._isStreamingSupported = !source.disableStream; - this._isRangeSupported = !source.disableRange; - this._readableStream = null; - this._readCapability = Promise.withResolvers(); - this._headersCapability = Promise.withResolvers(); - } - get headersReady() { - return this._headersCapability.promise; - } - get filename() { - return this._filename; - } - get contentLength() { - return this._contentLength; - } - get isRangeSupported() { - return this._isRangeSupported; - } - get isStreamingSupported() { - return this._isStreamingSupported; - } - async read() { - await this._readCapability.promise; - if (this._done) { - return { - value: undefined, - done: true - }; - } - if (this._storedError) { - throw this._storedError; - } - const chunk = this._readableStream.read(); - if (chunk === null) { - this._readCapability = Promise.withResolvers(); - return this.read(); - } - this._loaded += chunk.length; - this.onProgress?.({ - loaded: this._loaded, - total: this._contentLength - }); - const buffer = new Uint8Array(chunk).buffer; - return { - value: buffer, - done: false - }; - } - cancel(reason) { - if (!this._readableStream) { - this._error(reason); - return; - } - this._readableStream.destroy(reason); - } - _error(reason) { - this._storedError = reason; - this._readCapability.resolve(); - } - _setReadableStream(readableStream) { - this._readableStream = readableStream; - readableStream.on("readable", () => { - this._readCapability.resolve(); - }); - readableStream.on("end", () => { - readableStream.destroy(); - this._done = true; - this._readCapability.resolve(); - }); - readableStream.on("error", reason => { - this._error(reason); - }); - if (!this._isStreamingSupported && this._isRangeSupported) { - this._error(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException("streaming is disabled")); - } - if (this._storedError) { - this._readableStream.destroy(this._storedError); - } - } -} -class BaseRangeReader { - constructor(stream) { - this._url = stream.url; - this._done = false; - this._storedError = null; - this.onProgress = null; - this._loaded = 0; - this._readableStream = null; - this._readCapability = Promise.withResolvers(); - const source = stream.source; - this._isStreamingSupported = !source.disableStream; - } - get isStreamingSupported() { - return this._isStreamingSupported; - } - async read() { - await this._readCapability.promise; - if (this._done) { - return { - value: undefined, - done: true - }; - } - if (this._storedError) { - throw this._storedError; - } - const chunk = this._readableStream.read(); - if (chunk === null) { - this._readCapability = Promise.withResolvers(); - return this.read(); - } - this._loaded += chunk.length; - this.onProgress?.({ - loaded: this._loaded - }); - const buffer = new Uint8Array(chunk).buffer; - return { - value: buffer, - done: false - }; - } - cancel(reason) { - if (!this._readableStream) { - this._error(reason); - return; - } - this._readableStream.destroy(reason); - } - _error(reason) { - this._storedError = reason; - this._readCapability.resolve(); - } - _setReadableStream(readableStream) { - this._readableStream = readableStream; - readableStream.on("readable", () => { - this._readCapability.resolve(); - }); - readableStream.on("end", () => { - readableStream.destroy(); - this._done = true; - this._readCapability.resolve(); - }); - readableStream.on("error", reason => { - this._error(reason); - }); - if (this._storedError) { - this._readableStream.destroy(this._storedError); - } - } -} -function createRequestOptions(parsedUrl, headers) { - return { - protocol: parsedUrl.protocol, - auth: parsedUrl.auth, - host: parsedUrl.hostname, - port: parsedUrl.port, - path: parsedUrl.path, - method: "GET", - headers - }; -} -class PDFNodeStreamFullReader extends BaseFullReader { - constructor(stream) { - super(stream); - const handleResponse = response => { - if (response.statusCode === 404) { - const error = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException(`Missing PDF "${this._url}".`); - this._storedError = error; - this._headersCapability.reject(error); - return; - } - this._headersCapability.resolve(); - this._setReadableStream(response); - const getResponseHeader = name => this._readableStream.headers[name.toLowerCase()]; - const { - allowRangeRequests, - suggestedLength - } = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.validateRangeRequestCapabilities)({ - getResponseHeader, - isHttp: stream.isHttp, - rangeChunkSize: this._rangeChunkSize, - disableRange: this._disableRange - }); - this._isRangeSupported = allowRangeRequests; - this._contentLength = suggestedLength || this._contentLength; - this._filename = (0,_network_utils_js__WEBPACK_IMPORTED_MODULE_1__.extractFilenameFromHeader)(getResponseHeader); - }; - this._request = null; - if (this._url.protocol === "http:") { - this._request = http.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse); - } else { - this._request = https.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse); - } - this._request.on("error", reason => { - this._storedError = reason; - this._headersCapability.reject(reason); - }); - this._request.end(); - } -} -class PDFNodeStreamRangeReader extends BaseRangeReader { - constructor(stream, start, end) { - super(stream); - this._httpHeaders = {}; - for (const property in stream.httpHeaders) { - const value = stream.httpHeaders[property]; - if (value === undefined) { - continue; - } - this._httpHeaders[property] = value; - } - this._httpHeaders.Range = `bytes=${start}-${end - 1}`; - const handleResponse = response => { - if (response.statusCode === 404) { - const error = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException(`Missing PDF "${this._url}".`); - this._storedError = error; - return; - } - this._setReadableStream(response); - }; - this._request = null; - if (this._url.protocol === "http:") { - this._request = http.request(createRequestOptions(this._url, this._httpHeaders), handleResponse); - } else { - this._request = https.request(createRequestOptions(this._url, this._httpHeaders), handleResponse); - } - this._request.on("error", reason => { - this._storedError = reason; - }); - this._request.end(); - } -} -class PDFNodeStreamFsFullReader extends BaseFullReader { - constructor(stream) { - super(stream); - let path = decodeURIComponent(this._url.path); - if (fileUriRegex.test(this._url.href)) { - path = path.replace(/^\//, ""); - } - fs.promises.lstat(path).then(stat => { - this._contentLength = stat.size; - this._setReadableStream(fs.createReadStream(path)); - this._headersCapability.resolve(); - }, error => { - if (error.code === "ENOENT") { - error = new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException(`Missing PDF "${path}".`); - } - this._storedError = error; - this._headersCapability.reject(error); - }); - } -} -class PDFNodeStreamFsRangeReader extends BaseRangeReader { - constructor(stream, start, end) { - super(stream); - let path = decodeURIComponent(this._url.path); - if (fileUriRegex.test(this._url.href)) { - path = path.replace(/^\//, ""); - } - this._setReadableStream(fs.createReadStream(path, { - start, - end: end - 1 - })); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }, 1); - -/***/ }), - -/***/ 573: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ NodeCMapReaderFactory: () => (/* binding */ NodeCMapReaderFactory), -/* harmony export */ NodeCanvasFactory: () => (/* binding */ NodeCanvasFactory), -/* harmony export */ NodeFilterFactory: () => (/* binding */ NodeFilterFactory), -/* harmony export */ NodeStandardFontDataFactory: () => (/* binding */ NodeStandardFontDataFactory) -/* harmony export */ }); -/* harmony import */ var _base_factory_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(583); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(292); - - -let fs, canvas, path2d; -if (_shared_util_js__WEBPACK_IMPORTED_MODULE_1__.isNodeJS) { - fs = await import( /*webpackIgnore: true*/"fs"); - try { - canvas = await import( /*webpackIgnore: true*/"canvas"); - } catch {} - try { - path2d = await import( /*webpackIgnore: true*/"path2d"); - } catch {} -} -const fetchData = function (url) { - return fs.promises.readFile(url).then(data => new Uint8Array(data)); -}; -class NodeFilterFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseFilterFactory {} -class NodeCanvasFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseCanvasFactory { - _createCanvas(width, height) { - return canvas.createCanvas(width, height); - } -} -class NodeCMapReaderFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseCMapReaderFactory { - _fetchData(url, compressionType) { - return fetchData(url).then(data => ({ - cMapData: data, - compressionType - })); - } -} -class NodeStandardFontDataFactory extends _base_factory_js__WEBPACK_IMPORTED_MODULE_0__.BaseStandardFontDataFactory { - _fetchData(url) { - return fetchData(url); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }, 1); - -/***/ }), - -/***/ 626: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ OptionalContentConfig: () => (/* binding */ OptionalContentConfig) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _shared_murmurhash3_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(651); - - -const INTERNAL = Symbol("INTERNAL"); -class OptionalContentGroup { - #isDisplay = false; - #isPrint = false; - #userSet = false; - #visible = true; - constructor(renderingIntent, { - name, - intent, - usage - }) { - this.#isDisplay = !!(renderingIntent & _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.DISPLAY); - this.#isPrint = !!(renderingIntent & _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.PRINT); - this.name = name; - this.intent = intent; - this.usage = usage; - } - get visible() { - if (this.#userSet) { - return this.#visible; - } - if (!this.#visible) { - return false; - } - const { - print, - view - } = this.usage; - if (this.#isDisplay) { - return view?.viewState !== "OFF"; - } else if (this.#isPrint) { - return print?.printState !== "OFF"; - } - return true; - } - _setVisible(internal, visible, userSet = false) { - if (internal !== INTERNAL) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)("Internal method `_setVisible` called."); - } - this.#userSet = userSet; - this.#visible = visible; - } -} -class OptionalContentConfig { - #cachedGetHash = null; - #groups = new Map(); - #initialHash = null; - #order = null; - constructor(data, renderingIntent = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.RenderingIntentFlag.DISPLAY) { - this.renderingIntent = renderingIntent; - this.name = null; - this.creator = null; - if (data === null) { - return; - } - this.name = data.name; - this.creator = data.creator; - this.#order = data.order; - for (const group of data.groups) { - this.#groups.set(group.id, new OptionalContentGroup(renderingIntent, group)); - } - if (data.baseState === "OFF") { - for (const group of this.#groups.values()) { - group._setVisible(INTERNAL, false); - } - } - for (const on of data.on) { - this.#groups.get(on)._setVisible(INTERNAL, true); - } - for (const off of data.off) { - this.#groups.get(off)._setVisible(INTERNAL, false); - } - this.#initialHash = this.getHash(); - } - #evaluateVisibilityExpression(array) { - const length = array.length; - if (length < 2) { - return true; - } - const operator = array[0]; - for (let i = 1; i < length; i++) { - const element = array[i]; - let state; - if (Array.isArray(element)) { - state = this.#evaluateVisibilityExpression(element); - } else if (this.#groups.has(element)) { - state = this.#groups.get(element).visible; - } else { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${element}`); - return true; - } - switch (operator) { - case "And": - if (!state) { - return false; - } - break; - case "Or": - if (state) { - return true; - } - break; - case "Not": - return !state; - default: - return true; - } - } - return operator === "And"; - } - isVisible(group) { - if (this.#groups.size === 0) { - return true; - } - if (!group) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.info)("Optional content group not defined."); - return true; - } - if (group.type === "OCG") { - if (!this.#groups.has(group.id)) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${group.id}`); - return true; - } - return this.#groups.get(group.id).visible; - } else if (group.type === "OCMD") { - if (group.expression) { - return this.#evaluateVisibilityExpression(group.expression); - } - if (!group.policy || group.policy === "AnyOn") { - for (const id of group.ids) { - if (!this.#groups.has(id)) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${id}`); - return true; - } - if (this.#groups.get(id).visible) { - return true; - } - } - return false; - } else if (group.policy === "AllOn") { - for (const id of group.ids) { - if (!this.#groups.has(id)) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${id}`); - return true; - } - if (!this.#groups.get(id).visible) { - return false; - } - } - return true; - } else if (group.policy === "AnyOff") { - for (const id of group.ids) { - if (!this.#groups.has(id)) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${id}`); - return true; - } - if (!this.#groups.get(id).visible) { - return true; - } - } - return false; - } else if (group.policy === "AllOff") { - for (const id of group.ids) { - if (!this.#groups.has(id)) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${id}`); - return true; - } - if (this.#groups.get(id).visible) { - return false; - } - } - return true; - } - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Unknown optional content policy ${group.policy}.`); - return true; - } - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Unknown group type ${group.type}.`); - return true; - } - setVisibility(id, visible = true) { - const group = this.#groups.get(id); - if (!group) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.warn)(`Optional content group not found: ${id}`); - return; - } - group._setVisible(INTERNAL, !!visible, true); - this.#cachedGetHash = null; - } - setOCGState({ - state, - preserveRB - }) { - let operator; - for (const elem of state) { - switch (elem) { - case "ON": - case "OFF": - case "Toggle": - operator = elem; - continue; - } - const group = this.#groups.get(elem); - if (!group) { - continue; - } - switch (operator) { - case "ON": - group._setVisible(INTERNAL, true); - break; - case "OFF": - group._setVisible(INTERNAL, false); - break; - case "Toggle": - group._setVisible(INTERNAL, !group.visible); - break; - } - } - this.#cachedGetHash = null; - } - get hasInitialVisibility() { - return this.#initialHash === null || this.getHash() === this.#initialHash; - } - getOrder() { - if (!this.#groups.size) { - return null; - } - if (this.#order) { - return this.#order.slice(); - } - return [...this.#groups.keys()]; - } - getGroups() { - return this.#groups.size > 0 ? (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.objectFromMap)(this.#groups) : null; - } - getGroup(id) { - return this.#groups.get(id) || null; - } - getHash() { - if (this.#cachedGetHash !== null) { - return this.#cachedGetHash; - } - const hash = new _shared_murmurhash3_js__WEBPACK_IMPORTED_MODULE_1__.MurmurHash3_64(); - for (const [id, group] of this.#groups) { - hash.update(`${id}:${group.visible}`); - } - return this.#cachedGetHash = hash.hexdigest(); - } -} - - -/***/ }), - -/***/ 814: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ cleanupTextLayer: () => (/* binding */ cleanupTextLayer), -/* harmony export */ renderTextLayer: () => (/* binding */ renderTextLayer), -/* harmony export */ updateTextLayer: () => (/* binding */ updateTextLayer) -/* harmony export */ }); -/* unused harmony export TextLayerRenderTask */ -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(419); - - -const MAX_TEXT_DIVS_TO_RENDER = 100000; -const DEFAULT_FONT_SIZE = 30; -const DEFAULT_FONT_ASCENT = 0.8; -const ascentCache = new Map(); -let _canvasContext = null; -function getCtx() { - if (!_canvasContext) { - const canvas = document.createElement("canvas"); - canvas.className = "hiddenCanvasElement"; - document.body.append(canvas); - _canvasContext = canvas.getContext("2d", { - alpha: false - }); - } - return _canvasContext; -} -function cleanupTextLayer() { - _canvasContext?.canvas.remove(); - _canvasContext = null; -} -function getAscent(fontFamily) { - const cachedAscent = ascentCache.get(fontFamily); - if (cachedAscent) { - return cachedAscent; - } - const ctx = getCtx(); - const savedFont = ctx.font; - ctx.canvas.width = ctx.canvas.height = DEFAULT_FONT_SIZE; - ctx.font = `${DEFAULT_FONT_SIZE}px ${fontFamily}`; - const metrics = ctx.measureText(""); - let ascent = metrics.fontBoundingBoxAscent; - let descent = Math.abs(metrics.fontBoundingBoxDescent); - if (ascent) { - const ratio = ascent / (ascent + descent); - ascentCache.set(fontFamily, ratio); - ctx.canvas.width = ctx.canvas.height = 0; - ctx.font = savedFont; - return ratio; - } - ctx.strokeStyle = "red"; - ctx.clearRect(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE); - ctx.strokeText("g", 0, 0); - let pixels = ctx.getImageData(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE).data; - descent = 0; - for (let i = pixels.length - 1 - 3; i >= 0; i -= 4) { - if (pixels[i] > 0) { - descent = Math.ceil(i / 4 / DEFAULT_FONT_SIZE); - break; - } - } - ctx.clearRect(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE); - ctx.strokeText("A", 0, DEFAULT_FONT_SIZE); - pixels = ctx.getImageData(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE).data; - ascent = 0; - for (let i = 0, ii = pixels.length; i < ii; i += 4) { - if (pixels[i] > 0) { - ascent = DEFAULT_FONT_SIZE - Math.floor(i / 4 / DEFAULT_FONT_SIZE); - break; - } - } - ctx.canvas.width = ctx.canvas.height = 0; - ctx.font = savedFont; - if (ascent) { - const ratio = ascent / (ascent + descent); - ascentCache.set(fontFamily, ratio); - return ratio; - } - ascentCache.set(fontFamily, DEFAULT_FONT_ASCENT); - return DEFAULT_FONT_ASCENT; -} -function appendText(task, geom, styles) { - const textDiv = document.createElement("span"); - const textDivProperties = { - angle: 0, - canvasWidth: 0, - hasText: geom.str !== "", - hasEOL: geom.hasEOL, - fontSize: 0 - }; - task._textDivs.push(textDiv); - const tx = _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.Util.transform(task._transform, geom.transform); - let angle = Math.atan2(tx[1], tx[0]); - const style = styles[geom.fontName]; - if (style.vertical) { - angle += Math.PI / 2; - } - const fontFamily = task._fontInspectorEnabled && style.fontSubstitution || style.fontFamily; - const fontHeight = Math.hypot(tx[2], tx[3]); - const fontAscent = fontHeight * getAscent(fontFamily); - let left, top; - if (angle === 0) { - left = tx[4]; - top = tx[5] - fontAscent; - } else { - left = tx[4] + fontAscent * Math.sin(angle); - top = tx[5] - fontAscent * Math.cos(angle); - } - const scaleFactorStr = "calc(var(--scale-factor)*"; - const divStyle = textDiv.style; - if (task._container === task._rootContainer) { - divStyle.left = `${(100 * left / task._pageWidth).toFixed(2)}%`; - divStyle.top = `${(100 * top / task._pageHeight).toFixed(2)}%`; - } else { - divStyle.left = `${scaleFactorStr}${left.toFixed(2)}px)`; - divStyle.top = `${scaleFactorStr}${top.toFixed(2)}px)`; - } - divStyle.fontSize = `${scaleFactorStr}${fontHeight.toFixed(2)}px)`; - divStyle.fontFamily = fontFamily; - textDivProperties.fontSize = fontHeight; - textDiv.setAttribute("role", "presentation"); - textDiv.textContent = geom.str; - textDiv.dir = geom.dir; - if (task._fontInspectorEnabled) { - textDiv.dataset.fontName = style.fontSubstitutionLoadedName || geom.fontName; - } - if (angle !== 0) { - textDivProperties.angle = angle * (180 / Math.PI); - } - let shouldScaleText = false; - if (geom.str.length > 1) { - shouldScaleText = true; - } else if (geom.str !== " " && geom.transform[0] !== geom.transform[3]) { - const absScaleX = Math.abs(geom.transform[0]), - absScaleY = Math.abs(geom.transform[3]); - if (absScaleX !== absScaleY && Math.max(absScaleX, absScaleY) / Math.min(absScaleX, absScaleY) > 1.5) { - shouldScaleText = true; - } - } - if (shouldScaleText) { - textDivProperties.canvasWidth = style.vertical ? geom.height : geom.width; - } - task._textDivProperties.set(textDiv, textDivProperties); - if (task._isReadableStream) { - task._layoutText(textDiv); - } -} -function layout(params) { - const { - div, - scale, - properties, - ctx, - prevFontSize, - prevFontFamily - } = params; - const { - style - } = div; - let transform = ""; - if (properties.canvasWidth !== 0 && properties.hasText) { - const { - fontFamily - } = style; - const { - canvasWidth, - fontSize - } = properties; - if (prevFontSize !== fontSize || prevFontFamily !== fontFamily) { - ctx.font = `${fontSize * scale}px ${fontFamily}`; - params.prevFontSize = fontSize; - params.prevFontFamily = fontFamily; - } - const { - width - } = ctx.measureText(div.textContent); - if (width > 0) { - transform = `scaleX(${canvasWidth * scale / width})`; - } - } - if (properties.angle !== 0) { - transform = `rotate(${properties.angle}deg) ${transform}`; - } - if (transform.length > 0) { - style.transform = transform; - } -} -function render(task) { - if (task._canceled) { - return; - } - const textDivs = task._textDivs; - const capability = task._capability; - const textDivsLength = textDivs.length; - if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) { - capability.resolve(); - return; - } - if (!task._isReadableStream) { - for (const textDiv of textDivs) { - task._layoutText(textDiv); - } - } - capability.resolve(); -} -class TextLayerRenderTask { - constructor({ - textContentSource, - container, - viewport, - textDivs, - textDivProperties, - textContentItemsStr - }) { - this._textContentSource = textContentSource; - this._isReadableStream = textContentSource instanceof ReadableStream; - this._container = this._rootContainer = container; - this._textDivs = textDivs || []; - this._textContentItemsStr = textContentItemsStr || []; - this._fontInspectorEnabled = !!globalThis.FontInspector?.enabled; - this._reader = null; - this._textDivProperties = textDivProperties || new WeakMap(); - this._canceled = false; - this._capability = Promise.withResolvers(); - this._layoutTextParams = { - prevFontSize: null, - prevFontFamily: null, - div: null, - scale: viewport.scale * (globalThis.devicePixelRatio || 1), - properties: null, - ctx: getCtx() - }; - const { - pageWidth, - pageHeight, - pageX, - pageY - } = viewport.rawDims; - this._transform = [1, 0, 0, -1, -pageX, pageY + pageHeight]; - this._pageWidth = pageWidth; - this._pageHeight = pageHeight; - (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.setLayerDimensions)(container, viewport); - this._capability.promise.finally(() => { - this._layoutTextParams = null; - }).catch(() => {}); - } - get promise() { - return this._capability.promise; - } - cancel() { - this._canceled = true; - if (this._reader) { - this._reader.cancel(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException("TextLayer task cancelled.")).catch(() => {}); - this._reader = null; - } - this._capability.reject(new _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException("TextLayer task cancelled.")); - } - _processItems(items, styleCache) { - for (const item of items) { - if (item.str === undefined) { - if (item.type === "beginMarkedContentProps" || item.type === "beginMarkedContent") { - const parent = this._container; - this._container = document.createElement("span"); - this._container.classList.add("markedContent"); - if (item.id !== null) { - this._container.setAttribute("id", `${item.id}`); - } - parent.append(this._container); - } else if (item.type === "endMarkedContent") { - this._container = this._container.parentNode; - } - continue; - } - this._textContentItemsStr.push(item.str); - appendText(this, item, styleCache); - } - } - _layoutText(textDiv) { - const textDivProperties = this._layoutTextParams.properties = this._textDivProperties.get(textDiv); - this._layoutTextParams.div = textDiv; - layout(this._layoutTextParams); - if (textDivProperties.hasText) { - this._container.append(textDiv); - } - if (textDivProperties.hasEOL) { - const br = document.createElement("br"); - br.setAttribute("role", "presentation"); - this._container.append(br); - } - } - _render() { - const { - promise, - resolve, - reject - } = Promise.withResolvers(); - let styleCache = Object.create(null); - if (this._isReadableStream) { - const pump = () => { - this._reader.read().then(({ - value, - done - }) => { - if (done) { - resolve(); - return; - } - Object.assign(styleCache, value.styles); - this._processItems(value.items, styleCache); - pump(); - }, reject); - }; - this._reader = this._textContentSource.getReader(); - pump(); - } else if (this._textContentSource) { - const { - items, - styles - } = this._textContentSource; - this._processItems(items, styles); - resolve(); - } else { - throw new Error('No "textContentSource" parameter specified.'); - } - promise.then(() => { - styleCache = null; - render(this); - }, this._capability.reject); - } -} -function renderTextLayer(params) { - const task = new TextLayerRenderTask(params); - task._render(); - return task; -} -function updateTextLayer({ - container, - viewport, - textDivs, - textDivProperties, - mustRotate = true, - mustRescale = true -}) { - if (mustRotate) { - (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.setLayerDimensions)(container, { - rotation: viewport.rotation - }); - } - if (mustRescale) { - const ctx = getCtx(); - const scale = viewport.scale * (globalThis.devicePixelRatio || 1); - const params = { - prevFontSize: null, - prevFontFamily: null, - div: null, - scale, - properties: null, - ctx - }; - for (const div of textDivs) { - params.properties = textDivProperties.get(div); - params.div = div; - layout(params); - } - } -} - - -/***/ }), - -/***/ 585: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFDataTransportStream: () => (/* binding */ PDFDataTransportStream) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _display_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(419); - - -class PDFDataTransportStream { - constructor(pdfDataRangeTransport, { - disableRange = false, - disableStream = false - }) { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(pdfDataRangeTransport, 'PDFDataTransportStream - missing required "pdfDataRangeTransport" argument.'); - const { - length, - initialData, - progressiveDone, - contentDispositionFilename - } = pdfDataRangeTransport; - this._queuedChunks = []; - this._progressiveDone = progressiveDone; - this._contentDispositionFilename = contentDispositionFilename; - if (initialData?.length > 0) { - const buffer = initialData instanceof Uint8Array && initialData.byteLength === initialData.buffer.byteLength ? initialData.buffer : new Uint8Array(initialData).buffer; - this._queuedChunks.push(buffer); - } - this._pdfDataRangeTransport = pdfDataRangeTransport; - this._isStreamingSupported = !disableStream; - this._isRangeSupported = !disableRange; - this._contentLength = length; - this._fullRequestReader = null; - this._rangeReaders = []; - pdfDataRangeTransport.addRangeListener((begin, chunk) => { - this._onReceiveData({ - begin, - chunk - }); - }); - pdfDataRangeTransport.addProgressListener((loaded, total) => { - this._onProgress({ - loaded, - total - }); - }); - pdfDataRangeTransport.addProgressiveReadListener(chunk => { - this._onReceiveData({ - chunk - }); - }); - pdfDataRangeTransport.addProgressiveDoneListener(() => { - this._onProgressiveDone(); - }); - pdfDataRangeTransport.transportReady(); - } - _onReceiveData({ - begin, - chunk - }) { - const buffer = chunk instanceof Uint8Array && chunk.byteLength === chunk.buffer.byteLength ? chunk.buffer : new Uint8Array(chunk).buffer; - if (begin === undefined) { - if (this._fullRequestReader) { - this._fullRequestReader._enqueue(buffer); - } else { - this._queuedChunks.push(buffer); - } - } else { - const found = this._rangeReaders.some(function (rangeReader) { - if (rangeReader._begin !== begin) { - return false; - } - rangeReader._enqueue(buffer); - return true; - }); - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(found, "_onReceiveData - no `PDFDataTransportStreamRangeReader` instance found."); - } - } - get _progressiveDataLength() { - return this._fullRequestReader?._loaded ?? 0; - } - _onProgress(evt) { - if (evt.total === undefined) { - this._rangeReaders[0]?.onProgress?.({ - loaded: evt.loaded - }); - } else { - this._fullRequestReader?.onProgress?.({ - loaded: evt.loaded, - total: evt.total - }); - } - } - _onProgressiveDone() { - this._fullRequestReader?.progressiveDone(); - this._progressiveDone = true; - } - _removeRangeReader(reader) { - const i = this._rangeReaders.indexOf(reader); - if (i >= 0) { - this._rangeReaders.splice(i, 1); - } - } - getFullReader() { - (0,_shared_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(!this._fullRequestReader, "PDFDataTransportStream.getFullReader can only be called once."); - const queuedChunks = this._queuedChunks; - this._queuedChunks = null; - return new PDFDataTransportStreamReader(this, queuedChunks, this._progressiveDone, this._contentDispositionFilename); - } - getRangeReader(begin, end) { - if (end <= this._progressiveDataLength) { - return null; - } - const reader = new PDFDataTransportStreamRangeReader(this, begin, end); - this._pdfDataRangeTransport.requestDataRange(begin, end); - this._rangeReaders.push(reader); - return reader; - } - cancelAllRequests(reason) { - this._fullRequestReader?.cancel(reason); - for (const reader of this._rangeReaders.slice(0)) { - reader.cancel(reason); - } - this._pdfDataRangeTransport.abort(); - } -} -class PDFDataTransportStreamReader { - constructor(stream, queuedChunks, progressiveDone = false, contentDispositionFilename = null) { - this._stream = stream; - this._done = progressiveDone || false; - this._filename = (0,_display_utils_js__WEBPACK_IMPORTED_MODULE_1__.isPdfFile)(contentDispositionFilename) ? contentDispositionFilename : null; - this._queuedChunks = queuedChunks || []; - this._loaded = 0; - for (const chunk of this._queuedChunks) { - this._loaded += chunk.byteLength; - } - this._requests = []; - this._headersReady = Promise.resolve(); - stream._fullRequestReader = this; - this.onProgress = null; - } - _enqueue(chunk) { - if (this._done) { - return; - } - if (this._requests.length > 0) { - const requestCapability = this._requests.shift(); - requestCapability.resolve({ - value: chunk, - done: false - }); - } else { - this._queuedChunks.push(chunk); - } - this._loaded += chunk.byteLength; - } - get headersReady() { - return this._headersReady; - } - get filename() { - return this._filename; - } - get isRangeSupported() { - return this._stream._isRangeSupported; - } - get isStreamingSupported() { - return this._stream._isStreamingSupported; - } - get contentLength() { - return this._stream._contentLength; - } - async read() { - if (this._queuedChunks.length > 0) { - const chunk = this._queuedChunks.shift(); - return { - value: chunk, - done: false - }; - } - if (this._done) { - return { - value: undefined, - done: true - }; - } - const requestCapability = Promise.withResolvers(); - this._requests.push(requestCapability); - return requestCapability.promise; - } - cancel(reason) { - this._done = true; - for (const requestCapability of this._requests) { - requestCapability.resolve({ - value: undefined, - done: true - }); - } - this._requests.length = 0; - } - progressiveDone() { - if (this._done) { - return; - } - this._done = true; - } -} -class PDFDataTransportStreamRangeReader { - constructor(stream, begin, end) { - this._stream = stream; - this._begin = begin; - this._end = end; - this._queuedChunk = null; - this._requests = []; - this._done = false; - this.onProgress = null; - } - _enqueue(chunk) { - if (this._done) { - return; - } - if (this._requests.length === 0) { - this._queuedChunk = chunk; - } else { - const requestsCapability = this._requests.shift(); - requestsCapability.resolve({ - value: chunk, - done: false - }); - for (const requestCapability of this._requests) { - requestCapability.resolve({ - value: undefined, - done: true - }); - } - this._requests.length = 0; - } - this._done = true; - this._stream._removeRangeReader(this); - } - get isStreamingSupported() { - return false; - } - async read() { - if (this._queuedChunk) { - const chunk = this._queuedChunk; - this._queuedChunk = null; - return { - value: chunk, - done: false - }; - } - if (this._done) { - return { - value: undefined, - done: true - }; - } - const requestCapability = Promise.withResolvers(); - this._requests.push(requestCapability); - return requestCapability.promise; - } - cancel(reason) { - this._done = true; - for (const requestCapability of this._requests) { - requestCapability.resolve({ - value: undefined, - done: true - }); - } - this._requests.length = 0; - this._stream._removeRangeReader(this); - } -} - - -/***/ }), - -/***/ 164: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ GlobalWorkerOptions: () => (/* binding */ GlobalWorkerOptions) -/* harmony export */ }); -class GlobalWorkerOptions { - static #port = null; - static #src = ""; - static get workerPort() { - return this.#port; - } - static set workerPort(val) { - if (!(typeof Worker !== "undefined" && val instanceof Worker) && val !== null) { - throw new Error("Invalid `workerPort` type."); - } - this.#port = val; - } - static get workerSrc() { - return this.#src; - } - static set workerSrc(val) { - if (typeof val !== "string") { - throw new Error("Invalid `workerSrc` type."); - } - this.#src = val; - } -} - - -/***/ }), - -/***/ 284: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ XfaLayer: () => (/* binding */ XfaLayer) -/* harmony export */ }); -/* harmony import */ var _xfa_text_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(50); - -class XfaLayer { - static setupStorage(html, id, element, storage, intent) { - const storedData = storage.getValue(id, { - value: null - }); - switch (element.name) { - case "textarea": - if (storedData.value !== null) { - html.textContent = storedData.value; - } - if (intent === "print") { - break; - } - html.addEventListener("input", event => { - storage.setValue(id, { - value: event.target.value - }); - }); - break; - case "input": - if (element.attributes.type === "radio" || element.attributes.type === "checkbox") { - if (storedData.value === element.attributes.xfaOn) { - html.setAttribute("checked", true); - } else if (storedData.value === element.attributes.xfaOff) { - html.removeAttribute("checked"); - } - if (intent === "print") { - break; - } - html.addEventListener("change", event => { - storage.setValue(id, { - value: event.target.checked ? event.target.getAttribute("xfaOn") : event.target.getAttribute("xfaOff") - }); - }); - } else { - if (storedData.value !== null) { - html.setAttribute("value", storedData.value); - } - if (intent === "print") { - break; - } - html.addEventListener("input", event => { - storage.setValue(id, { - value: event.target.value - }); - }); - } - break; - case "select": - if (storedData.value !== null) { - html.setAttribute("value", storedData.value); - for (const option of element.children) { - if (option.attributes.value === storedData.value) { - option.attributes.selected = true; - } else if (option.attributes.hasOwnProperty("selected")) { - delete option.attributes.selected; - } - } - } - html.addEventListener("input", event => { - const options = event.target.options; - const value = options.selectedIndex === -1 ? "" : options[options.selectedIndex].value; - storage.setValue(id, { - value - }); - }); - break; - } - } - static setAttributes({ - html, - element, - storage = null, - intent, - linkService - }) { - const { - attributes - } = element; - const isHTMLAnchorElement = html instanceof HTMLAnchorElement; - if (attributes.type === "radio") { - attributes.name = `${attributes.name}-${intent}`; - } - for (const [key, value] of Object.entries(attributes)) { - if (value === null || value === undefined) { - continue; - } - switch (key) { - case "class": - if (value.length) { - html.setAttribute(key, value.join(" ")); - } - break; - case "dataId": - break; - case "id": - html.setAttribute("data-element-id", value); - break; - case "style": - Object.assign(html.style, value); - break; - case "textContent": - html.textContent = value; - break; - default: - if (!isHTMLAnchorElement || key !== "href" && key !== "newWindow") { - html.setAttribute(key, value); - } - } - } - if (isHTMLAnchorElement) { - linkService.addLinkAttributes(html, attributes.href, attributes.newWindow); - } - if (storage && attributes.dataId) { - this.setupStorage(html, attributes.dataId, element, storage); - } - } - static render(parameters) { - const storage = parameters.annotationStorage; - const linkService = parameters.linkService; - const root = parameters.xfaHtml; - const intent = parameters.intent || "display"; - const rootHtml = document.createElement(root.name); - if (root.attributes) { - this.setAttributes({ - html: rootHtml, - element: root, - intent, - linkService - }); - } - const isNotForRichText = intent !== "richText"; - const rootDiv = parameters.div; - rootDiv.append(rootHtml); - if (parameters.viewport) { - const transform = `matrix(${parameters.viewport.transform.join(",")})`; - rootDiv.style.transform = transform; - } - if (isNotForRichText) { - rootDiv.setAttribute("class", "xfaLayer xfaFont"); - } - const textDivs = []; - if (root.children.length === 0) { - if (root.value) { - const node = document.createTextNode(root.value); - rootHtml.append(node); - if (isNotForRichText && _xfa_text_js__WEBPACK_IMPORTED_MODULE_0__.XfaText.shouldBuildText(root.name)) { - textDivs.push(node); - } - } - return { - textDivs - }; - } - const stack = [[root, -1, rootHtml]]; - while (stack.length > 0) { - const [parent, i, html] = stack.at(-1); - if (i + 1 === parent.children.length) { - stack.pop(); - continue; - } - const child = parent.children[++stack.at(-1)[1]]; - if (child === null) { - continue; - } - const { - name - } = child; - if (name === "#text") { - const node = document.createTextNode(child.value); - textDivs.push(node); - html.append(node); - continue; - } - const childHtml = child?.attributes?.xmlns ? document.createElementNS(child.attributes.xmlns, name) : document.createElement(name); - html.append(childHtml); - if (child.attributes) { - this.setAttributes({ - html: childHtml, - element: child, - storage, - intent, - linkService - }); - } - if (child.children?.length > 0) { - stack.push([child, -1, childHtml]); - } else if (child.value) { - const node = document.createTextNode(child.value); - if (isNotForRichText && _xfa_text_js__WEBPACK_IMPORTED_MODULE_0__.XfaText.shouldBuildText(name)) { - textDivs.push(node); - } - childHtml.append(node); - } - } - for (const el of rootDiv.querySelectorAll(".xfaNonInteractive input, .xfaNonInteractive textarea")) { - el.setAttribute("readOnly", true); - } - return { - textDivs - }; - } - static update(parameters) { - const transform = `matrix(${parameters.viewport.transform.join(",")})`; - parameters.div.style.transform = transform; - parameters.div.hidden = false; - } -} - - -/***/ }), - -/***/ 50: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ XfaText: () => (/* binding */ XfaText) -/* harmony export */ }); -class XfaText { - static textContent(xfa) { - const items = []; - const output = { - items, - styles: Object.create(null) - }; - function walk(node) { - if (!node) { - return; - } - let str = null; - const name = node.name; - if (name === "#text") { - str = node.value; - } else if (!XfaText.shouldBuildText(name)) { - return; - } else if (node?.attributes?.textContent) { - str = node.attributes.textContent; - } else if (node.value) { - str = node.value; - } - if (str !== null) { - items.push({ - str - }); - } - if (!node.children) { - return; - } - for (const child of node.children) { - walk(child); - } - } - walk(xfa); - return output; - } - static shouldBuildText(name) { - return !(name === "textarea" || name === "input" || name === "option" || name === "select"); - } -} - - -/***/ }), - -/***/ 228: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AbortException: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException), -/* harmony export */ AnnotationEditorLayer: () => (/* reexport safe */ _display_editor_annotation_editor_layer_js__WEBPACK_IMPORTED_MODULE_4__.AnnotationEditorLayer), -/* harmony export */ AnnotationEditorParamsType: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType), -/* harmony export */ AnnotationEditorType: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType), -/* harmony export */ AnnotationEditorUIManager: () => (/* reexport safe */ _display_editor_tools_js__WEBPACK_IMPORTED_MODULE_5__.AnnotationEditorUIManager), -/* harmony export */ AnnotationLayer: () => (/* reexport safe */ _display_annotation_layer_js__WEBPACK_IMPORTED_MODULE_6__.AnnotationLayer), -/* harmony export */ AnnotationMode: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode), -/* harmony export */ CMapCompressionType: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.CMapCompressionType), -/* harmony export */ ColorPicker: () => (/* reexport safe */ _display_editor_color_picker_js__WEBPACK_IMPORTED_MODULE_7__.ColorPicker), -/* harmony export */ DOMSVGFactory: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.DOMSVGFactory), -/* harmony export */ DrawLayer: () => (/* reexport safe */ _display_draw_layer_js__WEBPACK_IMPORTED_MODULE_8__.DrawLayer), -/* harmony export */ FeatureTest: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.FeatureTest), -/* harmony export */ GlobalWorkerOptions: () => (/* reexport safe */ _display_worker_options_js__WEBPACK_IMPORTED_MODULE_10__.GlobalWorkerOptions), -/* harmony export */ ImageKind: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.ImageKind), -/* harmony export */ InvalidPDFException: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.InvalidPDFException), -/* harmony export */ MissingPDFException: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException), -/* harmony export */ OPS: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.OPS), -/* harmony export */ Outliner: () => (/* reexport safe */ _display_editor_outliner_js__WEBPACK_IMPORTED_MODULE_9__.Outliner), -/* harmony export */ PDFDataRangeTransport: () => (/* reexport safe */ _display_api_js__WEBPACK_IMPORTED_MODULE_1__.PDFDataRangeTransport), -/* harmony export */ PDFDateString: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.PDFDateString), -/* harmony export */ PDFWorker: () => (/* reexport safe */ _display_api_js__WEBPACK_IMPORTED_MODULE_1__.PDFWorker), -/* harmony export */ PasswordResponses: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.PasswordResponses), -/* harmony export */ PermissionFlag: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.PermissionFlag), -/* harmony export */ PixelsPerInch: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.PixelsPerInch), -/* harmony export */ RenderingCancelledException: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.RenderingCancelledException), -/* harmony export */ UnexpectedResponseException: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.UnexpectedResponseException), -/* harmony export */ Util: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.Util), -/* harmony export */ VerbosityLevel: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.VerbosityLevel), -/* harmony export */ XfaLayer: () => (/* reexport safe */ _display_xfa_layer_js__WEBPACK_IMPORTED_MODULE_11__.XfaLayer), -/* harmony export */ build: () => (/* reexport safe */ _display_api_js__WEBPACK_IMPORTED_MODULE_1__.build), -/* harmony export */ createValidAbsoluteUrl: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.createValidAbsoluteUrl), -/* harmony export */ fetchData: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.fetchData), -/* harmony export */ getDocument: () => (/* reexport safe */ _display_api_js__WEBPACK_IMPORTED_MODULE_1__.getDocument), -/* harmony export */ getFilenameFromUrl: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.getFilenameFromUrl), -/* harmony export */ getPdfFilenameFromUrl: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.getPdfFilenameFromUrl), -/* harmony export */ getXfaPageViewport: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.getXfaPageViewport), -/* harmony export */ isDataScheme: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isDataScheme), -/* harmony export */ isPdfFile: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.isPdfFile), -/* harmony export */ noContextMenu: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.noContextMenu), -/* harmony export */ normalizeUnicode: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.normalizeUnicode), -/* harmony export */ renderTextLayer: () => (/* reexport safe */ _display_text_layer_js__WEBPACK_IMPORTED_MODULE_3__.renderTextLayer), -/* harmony export */ setLayerDimensions: () => (/* reexport safe */ _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__.setLayerDimensions), -/* harmony export */ shadow: () => (/* reexport safe */ _shared_util_js__WEBPACK_IMPORTED_MODULE_0__.shadow), -/* harmony export */ updateTextLayer: () => (/* reexport safe */ _display_text_layer_js__WEBPACK_IMPORTED_MODULE_3__.updateTextLayer), -/* harmony export */ version: () => (/* reexport safe */ _display_api_js__WEBPACK_IMPORTED_MODULE_1__.version) -/* harmony export */ }); -/* harmony import */ var _shared_util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); -/* harmony import */ var _display_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(831); -/* harmony import */ var _display_display_utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(419); -/* harmony import */ var _display_text_layer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(814); -/* harmony import */ var _display_editor_annotation_editor_layer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(731); -/* harmony import */ var _display_editor_tools_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(830); -/* harmony import */ var _display_annotation_layer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(976); -/* harmony import */ var _display_editor_color_picker_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(259); -/* harmony import */ var _display_draw_layer_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(47); -/* harmony import */ var _display_worker_options_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(164); -/* harmony import */ var _display_editor_outliner_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(61); -/* harmony import */ var _display_xfa_layer_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(284); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_display_api_js__WEBPACK_IMPORTED_MODULE_1__]); -_display_api_js__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - - - - - - - - - - - -const pdfjsVersion = "4.2.67"; -const pdfjsBuild = "49b388101"; - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 178: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ MessageHandler: () => (/* binding */ MessageHandler) -/* harmony export */ }); -/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); - -const CallbackKind = { - UNKNOWN: 0, - DATA: 1, - ERROR: 2 -}; -const StreamKind = { - UNKNOWN: 0, - CANCEL: 1, - CANCEL_COMPLETE: 2, - CLOSE: 3, - ENQUEUE: 4, - ERROR: 5, - PULL: 6, - PULL_COMPLETE: 7, - START_COMPLETE: 8 -}; -function wrapReason(reason) { - if (!(reason instanceof Error || typeof reason === "object" && reason !== null)) { - (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.unreachable)('wrapReason: Expected "reason" to be a (possibly cloned) Error.'); - } - switch (reason.name) { - case "AbortException": - return new _util_js__WEBPACK_IMPORTED_MODULE_0__.AbortException(reason.message); - case "MissingPDFException": - return new _util_js__WEBPACK_IMPORTED_MODULE_0__.MissingPDFException(reason.message); - case "PasswordException": - return new _util_js__WEBPACK_IMPORTED_MODULE_0__.PasswordException(reason.message, reason.code); - case "UnexpectedResponseException": - return new _util_js__WEBPACK_IMPORTED_MODULE_0__.UnexpectedResponseException(reason.message, reason.status); - case "UnknownErrorException": - return new _util_js__WEBPACK_IMPORTED_MODULE_0__.UnknownErrorException(reason.message, reason.details); - default: - return new _util_js__WEBPACK_IMPORTED_MODULE_0__.UnknownErrorException(reason.message, reason.toString()); - } -} -class MessageHandler { - constructor(sourceName, targetName, comObj) { - this.sourceName = sourceName; - this.targetName = targetName; - this.comObj = comObj; - this.callbackId = 1; - this.streamId = 1; - this.streamSinks = Object.create(null); - this.streamControllers = Object.create(null); - this.callbackCapabilities = Object.create(null); - this.actionHandler = Object.create(null); - this._onComObjOnMessage = event => { - const data = event.data; - if (data.targetName !== this.sourceName) { - return; - } - if (data.stream) { - this.#processStreamMessage(data); - return; - } - if (data.callback) { - const callbackId = data.callbackId; - const capability = this.callbackCapabilities[callbackId]; - if (!capability) { - throw new Error(`Cannot resolve callback ${callbackId}`); - } - delete this.callbackCapabilities[callbackId]; - if (data.callback === CallbackKind.DATA) { - capability.resolve(data.data); - } else if (data.callback === CallbackKind.ERROR) { - capability.reject(wrapReason(data.reason)); - } else { - throw new Error("Unexpected callback case"); - } - return; - } - const action = this.actionHandler[data.action]; - if (!action) { - throw new Error(`Unknown action from worker: ${data.action}`); - } - if (data.callbackId) { - const cbSourceName = this.sourceName; - const cbTargetName = data.sourceName; - new Promise(function (resolve) { - resolve(action(data.data)); - }).then(function (result) { - comObj.postMessage({ - sourceName: cbSourceName, - targetName: cbTargetName, - callback: CallbackKind.DATA, - callbackId: data.callbackId, - data: result - }); - }, function (reason) { - comObj.postMessage({ - sourceName: cbSourceName, - targetName: cbTargetName, - callback: CallbackKind.ERROR, - callbackId: data.callbackId, - reason: wrapReason(reason) - }); - }); - return; - } - if (data.streamId) { - this.#createStreamSink(data); - return; - } - action(data.data); - }; - comObj.addEventListener("message", this._onComObjOnMessage); - } - on(actionName, handler) { - const ah = this.actionHandler; - if (ah[actionName]) { - throw new Error(`There is already an actionName called "${actionName}"`); - } - ah[actionName] = handler; - } - send(actionName, data, transfers) { - this.comObj.postMessage({ - sourceName: this.sourceName, - targetName: this.targetName, - action: actionName, - data - }, transfers); - } - sendWithPromise(actionName, data, transfers) { - const callbackId = this.callbackId++; - const capability = Promise.withResolvers(); - this.callbackCapabilities[callbackId] = capability; - try { - this.comObj.postMessage({ - sourceName: this.sourceName, - targetName: this.targetName, - action: actionName, - callbackId, - data - }, transfers); - } catch (ex) { - capability.reject(ex); - } - return capability.promise; - } - sendWithStream(actionName, data, queueingStrategy, transfers) { - const streamId = this.streamId++, - sourceName = this.sourceName, - targetName = this.targetName, - comObj = this.comObj; - return new ReadableStream({ - start: controller => { - const startCapability = Promise.withResolvers(); - this.streamControllers[streamId] = { - controller, - startCall: startCapability, - pullCall: null, - cancelCall: null, - isClosed: false - }; - comObj.postMessage({ - sourceName, - targetName, - action: actionName, - streamId, - data, - desiredSize: controller.desiredSize - }, transfers); - return startCapability.promise; - }, - pull: controller => { - const pullCapability = Promise.withResolvers(); - this.streamControllers[streamId].pullCall = pullCapability; - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.PULL, - streamId, - desiredSize: controller.desiredSize - }); - return pullCapability.promise; - }, - cancel: reason => { - (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(reason instanceof Error, "cancel must have a valid reason"); - const cancelCapability = Promise.withResolvers(); - this.streamControllers[streamId].cancelCall = cancelCapability; - this.streamControllers[streamId].isClosed = true; - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.CANCEL, - streamId, - reason: wrapReason(reason) - }); - return cancelCapability.promise; - } - }, queueingStrategy); - } - #createStreamSink(data) { - const streamId = data.streamId, - sourceName = this.sourceName, - targetName = data.sourceName, - comObj = this.comObj; - const self = this, - action = this.actionHandler[data.action]; - const streamSink = { - enqueue(chunk, size = 1, transfers) { - if (this.isCancelled) { - return; - } - const lastDesiredSize = this.desiredSize; - this.desiredSize -= size; - if (lastDesiredSize > 0 && this.desiredSize <= 0) { - this.sinkCapability = Promise.withResolvers(); - this.ready = this.sinkCapability.promise; - } - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.ENQUEUE, - streamId, - chunk - }, transfers); - }, - close() { - if (this.isCancelled) { - return; - } - this.isCancelled = true; - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.CLOSE, - streamId - }); - delete self.streamSinks[streamId]; - }, - error(reason) { - (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(reason instanceof Error, "error must have a valid reason"); - if (this.isCancelled) { - return; - } - this.isCancelled = true; - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.ERROR, - streamId, - reason: wrapReason(reason) - }); - }, - sinkCapability: Promise.withResolvers(), - onPull: null, - onCancel: null, - isCancelled: false, - desiredSize: data.desiredSize, - ready: null - }; - streamSink.sinkCapability.resolve(); - streamSink.ready = streamSink.sinkCapability.promise; - this.streamSinks[streamId] = streamSink; - new Promise(function (resolve) { - resolve(action(data.data, streamSink)); - }).then(function () { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.START_COMPLETE, - streamId, - success: true - }); - }, function (reason) { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.START_COMPLETE, - streamId, - reason: wrapReason(reason) - }); - }); - } - #processStreamMessage(data) { - const streamId = data.streamId, - sourceName = this.sourceName, - targetName = data.sourceName, - comObj = this.comObj; - const streamController = this.streamControllers[streamId], - streamSink = this.streamSinks[streamId]; - switch (data.stream) { - case StreamKind.START_COMPLETE: - if (data.success) { - streamController.startCall.resolve(); - } else { - streamController.startCall.reject(wrapReason(data.reason)); - } - break; - case StreamKind.PULL_COMPLETE: - if (data.success) { - streamController.pullCall.resolve(); - } else { - streamController.pullCall.reject(wrapReason(data.reason)); - } - break; - case StreamKind.PULL: - if (!streamSink) { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.PULL_COMPLETE, - streamId, - success: true - }); - break; - } - if (streamSink.desiredSize <= 0 && data.desiredSize > 0) { - streamSink.sinkCapability.resolve(); - } - streamSink.desiredSize = data.desiredSize; - new Promise(function (resolve) { - resolve(streamSink.onPull?.()); - }).then(function () { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.PULL_COMPLETE, - streamId, - success: true - }); - }, function (reason) { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.PULL_COMPLETE, - streamId, - reason: wrapReason(reason) - }); - }); - break; - case StreamKind.ENQUEUE: - (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(streamController, "enqueue should have stream controller"); - if (streamController.isClosed) { - break; - } - streamController.controller.enqueue(data.chunk); - break; - case StreamKind.CLOSE: - (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(streamController, "close should have stream controller"); - if (streamController.isClosed) { - break; - } - streamController.isClosed = true; - streamController.controller.close(); - this.#deleteStreamController(streamController, streamId); - break; - case StreamKind.ERROR: - (0,_util_js__WEBPACK_IMPORTED_MODULE_0__.assert)(streamController, "error should have stream controller"); - streamController.controller.error(wrapReason(data.reason)); - this.#deleteStreamController(streamController, streamId); - break; - case StreamKind.CANCEL_COMPLETE: - if (data.success) { - streamController.cancelCall.resolve(); - } else { - streamController.cancelCall.reject(wrapReason(data.reason)); - } - this.#deleteStreamController(streamController, streamId); - break; - case StreamKind.CANCEL: - if (!streamSink) { - break; - } - new Promise(function (resolve) { - resolve(streamSink.onCancel?.(wrapReason(data.reason))); - }).then(function () { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.CANCEL_COMPLETE, - streamId, - success: true - }); - }, function (reason) { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.CANCEL_COMPLETE, - streamId, - reason: wrapReason(reason) - }); - }); - streamSink.sinkCapability.reject(wrapReason(data.reason)); - streamSink.isCancelled = true; - delete this.streamSinks[streamId]; - break; - default: - throw new Error("Unexpected stream case"); - } - } - async #deleteStreamController(streamController, streamId) { - await Promise.allSettled([streamController.startCall?.promise, streamController.pullCall?.promise, streamController.cancelCall?.promise]); - delete this.streamControllers[streamId]; - } - destroy() { - this.comObj.removeEventListener("message", this._onComObjOnMessage); - } -} - - -/***/ }), - -/***/ 651: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ MurmurHash3_64: () => (/* binding */ MurmurHash3_64) -/* harmony export */ }); -const SEED = 0xc3d2e1f0; -const MASK_HIGH = 0xffff0000; -const MASK_LOW = 0xffff; -class MurmurHash3_64 { - constructor(seed) { - this.h1 = seed ? seed & 0xffffffff : SEED; - this.h2 = seed ? seed & 0xffffffff : SEED; - } - update(input) { - let data, length; - if (typeof input === "string") { - data = new Uint8Array(input.length * 2); - length = 0; - for (let i = 0, ii = input.length; i < ii; i++) { - const code = input.charCodeAt(i); - if (code <= 0xff) { - data[length++] = code; - } else { - data[length++] = code >>> 8; - data[length++] = code & 0xff; - } - } - } else if (ArrayBuffer.isView(input)) { - data = input.slice(); - length = data.byteLength; - } else { - throw new Error("Invalid data format, must be a string or TypedArray."); - } - const blockCounts = length >> 2; - const tailLength = length - blockCounts * 4; - const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts); - let k1 = 0, - k2 = 0; - let h1 = this.h1, - h2 = this.h2; - const C1 = 0xcc9e2d51, - C2 = 0x1b873593; - const C1_LOW = C1 & MASK_LOW, - C2_LOW = C2 & MASK_LOW; - for (let i = 0; i < blockCounts; i++) { - if (i & 1) { - k1 = dataUint32[i]; - k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; - k1 = k1 << 15 | k1 >>> 17; - k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; - h1 ^= k1; - h1 = h1 << 13 | h1 >>> 19; - h1 = h1 * 5 + 0xe6546b64; - } else { - k2 = dataUint32[i]; - k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW; - k2 = k2 << 15 | k2 >>> 17; - k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW; - h2 ^= k2; - h2 = h2 << 13 | h2 >>> 19; - h2 = h2 * 5 + 0xe6546b64; - } - } - k1 = 0; - switch (tailLength) { - case 3: - k1 ^= data[blockCounts * 4 + 2] << 16; - case 2: - k1 ^= data[blockCounts * 4 + 1] << 8; - case 1: - k1 ^= data[blockCounts * 4]; - k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; - k1 = k1 << 15 | k1 >>> 17; - k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; - if (blockCounts & 1) { - h1 ^= k1; - } else { - h2 ^= k1; - } - } - this.h1 = h1; - this.h2 = h2; - } - hexdigest() { - let h1 = this.h1, - h2 = this.h2; - h1 ^= h2 >>> 1; - h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW; - h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16; - h1 ^= h2 >>> 1; - h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW; - h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16; - h1 ^= h2 >>> 1; - return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0"); - } -} - - -/***/ }), - -/***/ 292: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AbortException: () => (/* binding */ AbortException), -/* harmony export */ AnnotationBorderStyleType: () => (/* binding */ AnnotationBorderStyleType), -/* harmony export */ AnnotationEditorParamsType: () => (/* binding */ AnnotationEditorParamsType), -/* harmony export */ AnnotationEditorPrefix: () => (/* binding */ AnnotationEditorPrefix), -/* harmony export */ AnnotationEditorType: () => (/* binding */ AnnotationEditorType), -/* harmony export */ AnnotationMode: () => (/* binding */ AnnotationMode), -/* harmony export */ AnnotationPrefix: () => (/* binding */ AnnotationPrefix), -/* harmony export */ AnnotationType: () => (/* binding */ AnnotationType), -/* harmony export */ BaseException: () => (/* binding */ BaseException), -/* harmony export */ CMapCompressionType: () => (/* binding */ CMapCompressionType), -/* harmony export */ FONT_IDENTITY_MATRIX: () => (/* binding */ FONT_IDENTITY_MATRIX), -/* harmony export */ FeatureTest: () => (/* binding */ FeatureTest), -/* harmony export */ FontRenderOps: () => (/* binding */ FontRenderOps), -/* harmony export */ FormatError: () => (/* binding */ FormatError), -/* harmony export */ IDENTITY_MATRIX: () => (/* binding */ IDENTITY_MATRIX), -/* harmony export */ ImageKind: () => (/* binding */ ImageKind), -/* harmony export */ InvalidPDFException: () => (/* binding */ InvalidPDFException), -/* harmony export */ LINE_FACTOR: () => (/* binding */ LINE_FACTOR), -/* harmony export */ MAX_IMAGE_SIZE_TO_CACHE: () => (/* binding */ MAX_IMAGE_SIZE_TO_CACHE), -/* harmony export */ MissingPDFException: () => (/* binding */ MissingPDFException), -/* harmony export */ OPS: () => (/* binding */ OPS), -/* harmony export */ PasswordException: () => (/* binding */ PasswordException), -/* harmony export */ PasswordResponses: () => (/* binding */ PasswordResponses), -/* harmony export */ PermissionFlag: () => (/* binding */ PermissionFlag), -/* harmony export */ RenderingIntentFlag: () => (/* binding */ RenderingIntentFlag), -/* harmony export */ TextRenderingMode: () => (/* binding */ TextRenderingMode), -/* harmony export */ UnexpectedResponseException: () => (/* binding */ UnexpectedResponseException), -/* harmony export */ UnknownErrorException: () => (/* binding */ UnknownErrorException), -/* harmony export */ Util: () => (/* binding */ Util), -/* harmony export */ VerbosityLevel: () => (/* binding */ VerbosityLevel), -/* harmony export */ assert: () => (/* binding */ assert), -/* harmony export */ bytesToString: () => (/* binding */ bytesToString), -/* harmony export */ createValidAbsoluteUrl: () => (/* binding */ createValidAbsoluteUrl), -/* harmony export */ getUuid: () => (/* binding */ getUuid), -/* harmony export */ getVerbosityLevel: () => (/* binding */ getVerbosityLevel), -/* harmony export */ info: () => (/* binding */ info), -/* harmony export */ isNodeJS: () => (/* binding */ isNodeJS), -/* harmony export */ normalizeUnicode: () => (/* binding */ normalizeUnicode), -/* harmony export */ objectFromMap: () => (/* binding */ objectFromMap), -/* harmony export */ setVerbosityLevel: () => (/* binding */ setVerbosityLevel), -/* harmony export */ shadow: () => (/* binding */ shadow), -/* harmony export */ string32: () => (/* binding */ string32), -/* harmony export */ stringToBytes: () => (/* binding */ stringToBytes), -/* harmony export */ unreachable: () => (/* binding */ unreachable), -/* harmony export */ warn: () => (/* binding */ warn) -/* harmony export */ }); -/* unused harmony exports AnnotationActionEventType, AnnotationFieldFlag, AnnotationFlag, AnnotationReplyType, BASELINE_FACTOR, DocumentActionEventType, getModificationDate, isArrayEqual, LINE_DESCENT_FACTOR, objectSize, PageActionEventType, stringToPDFString, stringToUTF8String, utf8StringToString */ -const isNodeJS = typeof process === "object" && process + "" === "[object process]" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== "browser"); -const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; -const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; -const MAX_IMAGE_SIZE_TO_CACHE = 10e6; -const LINE_FACTOR = 1.35; -const LINE_DESCENT_FACTOR = 0.35; -const BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR; -const RenderingIntentFlag = { - ANY: 0x01, - DISPLAY: 0x02, - PRINT: 0x04, - SAVE: 0x08, - ANNOTATIONS_FORMS: 0x10, - ANNOTATIONS_STORAGE: 0x20, - ANNOTATIONS_DISABLE: 0x40, - OPLIST: 0x100 -}; -const AnnotationMode = { - DISABLE: 0, - ENABLE: 1, - ENABLE_FORMS: 2, - ENABLE_STORAGE: 3 -}; -const AnnotationEditorPrefix = "pdfjs_internal_editor_"; -const AnnotationEditorType = { - DISABLE: -1, - NONE: 0, - FREETEXT: 3, - HIGHLIGHT: 9, - STAMP: 13, - INK: 15 -}; -const AnnotationEditorParamsType = { - RESIZE: 1, - CREATE: 2, - FREETEXT_SIZE: 11, - FREETEXT_COLOR: 12, - FREETEXT_OPACITY: 13, - INK_COLOR: 21, - INK_THICKNESS: 22, - INK_OPACITY: 23, - HIGHLIGHT_COLOR: 31, - HIGHLIGHT_DEFAULT_COLOR: 32, - HIGHLIGHT_THICKNESS: 33, - HIGHLIGHT_FREE: 34, - HIGHLIGHT_SHOW_ALL: 35 -}; -const PermissionFlag = { - PRINT: 0x04, - MODIFY_CONTENTS: 0x08, - COPY: 0x10, - MODIFY_ANNOTATIONS: 0x20, - FILL_INTERACTIVE_FORMS: 0x100, - COPY_FOR_ACCESSIBILITY: 0x200, - ASSEMBLE: 0x400, - PRINT_HIGH_QUALITY: 0x800 -}; -const TextRenderingMode = { - FILL: 0, - STROKE: 1, - FILL_STROKE: 2, - INVISIBLE: 3, - FILL_ADD_TO_PATH: 4, - STROKE_ADD_TO_PATH: 5, - FILL_STROKE_ADD_TO_PATH: 6, - ADD_TO_PATH: 7, - FILL_STROKE_MASK: 3, - ADD_TO_PATH_FLAG: 4 -}; -const ImageKind = { - GRAYSCALE_1BPP: 1, - RGB_24BPP: 2, - RGBA_32BPP: 3 -}; -const AnnotationType = { - TEXT: 1, - LINK: 2, - FREETEXT: 3, - LINE: 4, - SQUARE: 5, - CIRCLE: 6, - POLYGON: 7, - POLYLINE: 8, - HIGHLIGHT: 9, - UNDERLINE: 10, - SQUIGGLY: 11, - STRIKEOUT: 12, - STAMP: 13, - CARET: 14, - INK: 15, - POPUP: 16, - FILEATTACHMENT: 17, - SOUND: 18, - MOVIE: 19, - WIDGET: 20, - SCREEN: 21, - PRINTERMARK: 22, - TRAPNET: 23, - WATERMARK: 24, - THREED: 25, - REDACT: 26 -}; -const AnnotationReplyType = { - GROUP: "Group", - REPLY: "R" -}; -const AnnotationFlag = { - INVISIBLE: 0x01, - HIDDEN: 0x02, - PRINT: 0x04, - NOZOOM: 0x08, - NOROTATE: 0x10, - NOVIEW: 0x20, - READONLY: 0x40, - LOCKED: 0x80, - TOGGLENOVIEW: 0x100, - LOCKEDCONTENTS: 0x200 -}; -const AnnotationFieldFlag = { - READONLY: 0x0000001, - REQUIRED: 0x0000002, - NOEXPORT: 0x0000004, - MULTILINE: 0x0001000, - PASSWORD: 0x0002000, - NOTOGGLETOOFF: 0x0004000, - RADIO: 0x0008000, - PUSHBUTTON: 0x0010000, - COMBO: 0x0020000, - EDIT: 0x0040000, - SORT: 0x0080000, - FILESELECT: 0x0100000, - MULTISELECT: 0x0200000, - DONOTSPELLCHECK: 0x0400000, - DONOTSCROLL: 0x0800000, - COMB: 0x1000000, - RICHTEXT: 0x2000000, - RADIOSINUNISON: 0x2000000, - COMMITONSELCHANGE: 0x4000000 -}; -const AnnotationBorderStyleType = { - SOLID: 1, - DASHED: 2, - BEVELED: 3, - INSET: 4, - UNDERLINE: 5 -}; -const AnnotationActionEventType = { - E: "Mouse Enter", - X: "Mouse Exit", - D: "Mouse Down", - U: "Mouse Up", - Fo: "Focus", - Bl: "Blur", - PO: "PageOpen", - PC: "PageClose", - PV: "PageVisible", - PI: "PageInvisible", - K: "Keystroke", - F: "Format", - V: "Validate", - C: "Calculate" -}; -const DocumentActionEventType = { - WC: "WillClose", - WS: "WillSave", - DS: "DidSave", - WP: "WillPrint", - DP: "DidPrint" -}; -const PageActionEventType = { - O: "PageOpen", - C: "PageClose" -}; -const VerbosityLevel = { - ERRORS: 0, - WARNINGS: 1, - INFOS: 5 -}; -const CMapCompressionType = { - NONE: 0, - BINARY: 1 -}; -const OPS = { - dependency: 1, - setLineWidth: 2, - setLineCap: 3, - setLineJoin: 4, - setMiterLimit: 5, - setDash: 6, - setRenderingIntent: 7, - setFlatness: 8, - setGState: 9, - save: 10, - restore: 11, - transform: 12, - moveTo: 13, - lineTo: 14, - curveTo: 15, - curveTo2: 16, - curveTo3: 17, - closePath: 18, - rectangle: 19, - stroke: 20, - closeStroke: 21, - fill: 22, - eoFill: 23, - fillStroke: 24, - eoFillStroke: 25, - closeFillStroke: 26, - closeEOFillStroke: 27, - endPath: 28, - clip: 29, - eoClip: 30, - beginText: 31, - endText: 32, - setCharSpacing: 33, - setWordSpacing: 34, - setHScale: 35, - setLeading: 36, - setFont: 37, - setTextRenderingMode: 38, - setTextRise: 39, - moveText: 40, - setLeadingMoveText: 41, - setTextMatrix: 42, - nextLine: 43, - showText: 44, - showSpacedText: 45, - nextLineShowText: 46, - nextLineSetSpacingShowText: 47, - setCharWidth: 48, - setCharWidthAndBounds: 49, - setStrokeColorSpace: 50, - setFillColorSpace: 51, - setStrokeColor: 52, - setStrokeColorN: 53, - setFillColor: 54, - setFillColorN: 55, - setStrokeGray: 56, - setFillGray: 57, - setStrokeRGBColor: 58, - setFillRGBColor: 59, - setStrokeCMYKColor: 60, - setFillCMYKColor: 61, - shadingFill: 62, - beginInlineImage: 63, - beginImageData: 64, - endInlineImage: 65, - paintXObject: 66, - markPoint: 67, - markPointProps: 68, - beginMarkedContent: 69, - beginMarkedContentProps: 70, - endMarkedContent: 71, - beginCompat: 72, - endCompat: 73, - paintFormXObjectBegin: 74, - paintFormXObjectEnd: 75, - beginGroup: 76, - endGroup: 77, - beginAnnotation: 80, - endAnnotation: 81, - paintImageMaskXObject: 83, - paintImageMaskXObjectGroup: 84, - paintImageXObject: 85, - paintInlineImageXObject: 86, - paintInlineImageXObjectGroup: 87, - paintImageXObjectRepeat: 88, - paintImageMaskXObjectRepeat: 89, - paintSolidColorImageMask: 90, - constructPath: 91 -}; -const PasswordResponses = { - NEED_PASSWORD: 1, - INCORRECT_PASSWORD: 2 -}; -let verbosity = VerbosityLevel.WARNINGS; -function setVerbosityLevel(level) { - if (Number.isInteger(level)) { - verbosity = level; - } -} -function getVerbosityLevel() { - return verbosity; -} -function info(msg) { - if (verbosity >= VerbosityLevel.INFOS) { - console.log(`Info: ${msg}`); - } -} -function warn(msg) { - if (verbosity >= VerbosityLevel.WARNINGS) { - console.log(`Warning: ${msg}`); - } -} -function unreachable(msg) { - throw new Error(msg); -} -function assert(cond, msg) { - if (!cond) { - unreachable(msg); - } -} -function _isValidProtocol(url) { - switch (url?.protocol) { - case "http:": - case "https:": - case "ftp:": - case "mailto:": - case "tel:": - return true; - default: - return false; - } -} -function createValidAbsoluteUrl(url, baseUrl = null, options = null) { - if (!url) { - return null; - } - try { - if (options && typeof url === "string") { - if (options.addDefaultProtocol && url.startsWith("www.")) { - const dots = url.match(/\./g); - if (dots?.length >= 2) { - url = `http://${url}`; - } - } - if (options.tryConvertEncoding) { - try { - url = stringToUTF8String(url); - } catch {} - } - } - const absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url); - if (_isValidProtocol(absoluteUrl)) { - return absoluteUrl; - } - } catch {} - return null; -} -function shadow(obj, prop, value, nonSerializable = false) { - Object.defineProperty(obj, prop, { - value, - enumerable: !nonSerializable, - configurable: true, - writable: false - }); - return value; -} -const BaseException = function BaseExceptionClosure() { - function BaseException(message, name) { - if (this.constructor === BaseException) { - unreachable("Cannot initialize BaseException."); - } - this.message = message; - this.name = name; - } - BaseException.prototype = new Error(); - BaseException.constructor = BaseException; - return BaseException; -}(); -class PasswordException extends BaseException { - constructor(msg, code) { - super(msg, "PasswordException"); - this.code = code; - } -} -class UnknownErrorException extends BaseException { - constructor(msg, details) { - super(msg, "UnknownErrorException"); - this.details = details; - } -} -class InvalidPDFException extends BaseException { - constructor(msg) { - super(msg, "InvalidPDFException"); - } -} -class MissingPDFException extends BaseException { - constructor(msg) { - super(msg, "MissingPDFException"); - } -} -class UnexpectedResponseException extends BaseException { - constructor(msg, status) { - super(msg, "UnexpectedResponseException"); - this.status = status; - } -} -class FormatError extends BaseException { - constructor(msg) { - super(msg, "FormatError"); - } -} -class AbortException extends BaseException { - constructor(msg) { - super(msg, "AbortException"); - } -} -function bytesToString(bytes) { - if (typeof bytes !== "object" || bytes?.length === undefined) { - unreachable("Invalid argument for bytesToString"); - } - const length = bytes.length; - const MAX_ARGUMENT_COUNT = 8192; - if (length < MAX_ARGUMENT_COUNT) { - return String.fromCharCode.apply(null, bytes); - } - const strBuf = []; - for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) { - const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); - const chunk = bytes.subarray(i, chunkEnd); - strBuf.push(String.fromCharCode.apply(null, chunk)); - } - return strBuf.join(""); -} -function stringToBytes(str) { - if (typeof str !== "string") { - unreachable("Invalid argument for stringToBytes"); - } - const length = str.length; - const bytes = new Uint8Array(length); - for (let i = 0; i < length; ++i) { - bytes[i] = str.charCodeAt(i) & 0xff; - } - return bytes; -} -function string32(value) { - return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff); -} -function objectSize(obj) { - return Object.keys(obj).length; -} -function objectFromMap(map) { - const obj = Object.create(null); - for (const [key, value] of map) { - obj[key] = value; - } - return obj; -} -function isLittleEndian() { - const buffer8 = new Uint8Array(4); - buffer8[0] = 1; - const view32 = new Uint32Array(buffer8.buffer, 0, 1); - return view32[0] === 1; -} -function isEvalSupported() { - try { - new Function(""); - return true; - } catch { - return false; - } -} -class FeatureTest { - static get isLittleEndian() { - return shadow(this, "isLittleEndian", isLittleEndian()); - } - static get isEvalSupported() { - return shadow(this, "isEvalSupported", isEvalSupported()); - } - static get isOffscreenCanvasSupported() { - return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined"); - } - static get platform() { - if (typeof navigator !== "undefined" && typeof navigator?.platform === "string") { - return shadow(this, "platform", { - isMac: navigator.platform.includes("Mac") - }); - } - return shadow(this, "platform", { - isMac: false - }); - } - static get isCSSRoundSupported() { - return shadow(this, "isCSSRoundSupported", globalThis.CSS?.supports?.("width: round(1.5px, 1px)")); - } -} -const hexNumbers = Array.from(Array(256).keys(), n => n.toString(16).padStart(2, "0")); -class Util { - static makeHexColor(r, g, b) { - return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`; - } - static scaleMinMax(transform, minMax) { - let temp; - if (transform[0]) { - if (transform[0] < 0) { - temp = minMax[0]; - minMax[0] = minMax[2]; - minMax[2] = temp; - } - minMax[0] *= transform[0]; - minMax[2] *= transform[0]; - if (transform[3] < 0) { - temp = minMax[1]; - minMax[1] = minMax[3]; - minMax[3] = temp; - } - minMax[1] *= transform[3]; - minMax[3] *= transform[3]; - } else { - temp = minMax[0]; - minMax[0] = minMax[1]; - minMax[1] = temp; - temp = minMax[2]; - minMax[2] = minMax[3]; - minMax[3] = temp; - if (transform[1] < 0) { - temp = minMax[1]; - minMax[1] = minMax[3]; - minMax[3] = temp; - } - minMax[1] *= transform[1]; - minMax[3] *= transform[1]; - if (transform[2] < 0) { - temp = minMax[0]; - minMax[0] = minMax[2]; - minMax[2] = temp; - } - minMax[0] *= transform[2]; - minMax[2] *= transform[2]; - } - minMax[0] += transform[4]; - minMax[1] += transform[5]; - minMax[2] += transform[4]; - minMax[3] += transform[5]; - } - static transform(m1, m2) { - return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]]; - } - static applyTransform(p, m) { - const xt = p[0] * m[0] + p[1] * m[2] + m[4]; - const yt = p[0] * m[1] + p[1] * m[3] + m[5]; - return [xt, yt]; - } - static applyInverseTransform(p, m) { - const d = m[0] * m[3] - m[1] * m[2]; - const xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; - const yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; - return [xt, yt]; - } - static getAxialAlignedBoundingBox(r, m) { - const p1 = this.applyTransform(r, m); - const p2 = this.applyTransform(r.slice(2, 4), m); - const p3 = this.applyTransform([r[0], r[3]], m); - const p4 = this.applyTransform([r[2], r[1]], m); - return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])]; - } - static inverseTransform(m) { - const d = m[0] * m[3] - m[1] * m[2]; - return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; - } - static singularValueDecompose2dScale(m) { - const transpose = [m[0], m[2], m[1], m[3]]; - const a = m[0] * transpose[0] + m[1] * transpose[2]; - const b = m[0] * transpose[1] + m[1] * transpose[3]; - const c = m[2] * transpose[0] + m[3] * transpose[2]; - const d = m[2] * transpose[1] + m[3] * transpose[3]; - const first = (a + d) / 2; - const second = Math.sqrt((a + d) ** 2 - 4 * (a * d - c * b)) / 2; - const sx = first + second || 1; - const sy = first - second || 1; - return [Math.sqrt(sx), Math.sqrt(sy)]; - } - static normalizeRect(rect) { - const r = rect.slice(0); - if (rect[0] > rect[2]) { - r[0] = rect[2]; - r[2] = rect[0]; - } - if (rect[1] > rect[3]) { - r[1] = rect[3]; - r[3] = rect[1]; - } - return r; - } - static intersect(rect1, rect2) { - const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2])); - const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2])); - if (xLow > xHigh) { - return null; - } - const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3])); - const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3])); - if (yLow > yHigh) { - return null; - } - return [xLow, yLow, xHigh, yHigh]; - } - static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) { - if (t <= 0 || t >= 1) { - return; - } - const mt = 1 - t; - const tt = t * t; - const ttt = tt * t; - const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3; - const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3; - minMax[0] = Math.min(minMax[0], x); - minMax[1] = Math.min(minMax[1], y); - minMax[2] = Math.max(minMax[2], x); - minMax[3] = Math.max(minMax[3], y); - } - static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) { - if (Math.abs(a) < 1e-12) { - if (Math.abs(b) >= 1e-12) { - this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax); - } - return; - } - const delta = b ** 2 - 4 * c * a; - if (delta < 0) { - return; - } - const sqrtDelta = Math.sqrt(delta); - const a2 = 2 * a; - this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax); - this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax); - } - static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) { - if (minMax) { - minMax[0] = Math.min(minMax[0], x0, x3); - minMax[1] = Math.min(minMax[1], y0, y3); - minMax[2] = Math.max(minMax[2], x0, x3); - minMax[3] = Math.max(minMax[3], y0, y3); - } else { - minMax = [Math.min(x0, x3), Math.min(y0, y3), Math.max(x0, x3), Math.max(y0, y3)]; - } - this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax); - this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax); - return minMax; - } -} -const PDFStringTranslateTable = (/* unused pure expression or super */ null && ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac])); -function stringToPDFString(str) { - if (str[0] >= "\xEF") { - let encoding; - if (str[0] === "\xFE" && str[1] === "\xFF") { - encoding = "utf-16be"; - if (str.length % 2 === 1) { - str = str.slice(0, -1); - } - } else if (str[0] === "\xFF" && str[1] === "\xFE") { - encoding = "utf-16le"; - if (str.length % 2 === 1) { - str = str.slice(0, -1); - } - } else if (str[0] === "\xEF" && str[1] === "\xBB" && str[2] === "\xBF") { - encoding = "utf-8"; - } - if (encoding) { - try { - const decoder = new TextDecoder(encoding, { - fatal: true - }); - const buffer = stringToBytes(str); - const decoded = decoder.decode(buffer); - if (!decoded.includes("\x1b")) { - return decoded; - } - return decoded.replaceAll(/\x1b[^\x1b]*(?:\x1b|$)/g, ""); - } catch (ex) { - warn(`stringToPDFString: "${ex}".`); - } - } - } - const strBuf = []; - for (let i = 0, ii = str.length; i < ii; i++) { - const charCode = str.charCodeAt(i); - if (charCode === 0x1b) { - while (++i < ii && str.charCodeAt(i) !== 0x1b) {} - continue; - } - const code = PDFStringTranslateTable[charCode]; - strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); - } - return strBuf.join(""); -} -function stringToUTF8String(str) { - return decodeURIComponent(escape(str)); -} -function utf8StringToString(str) { - return unescape(encodeURIComponent(str)); -} -function isArrayEqual(arr1, arr2) { - if (arr1.length !== arr2.length) { - return false; - } - for (let i = 0, ii = arr1.length; i < ii; i++) { - if (arr1[i] !== arr2[i]) { - return false; - } - } - return true; -} -function getModificationDate(date = new Date()) { - const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, "0"), date.getUTCDate().toString().padStart(2, "0"), date.getUTCHours().toString().padStart(2, "0"), date.getUTCMinutes().toString().padStart(2, "0"), date.getUTCSeconds().toString().padStart(2, "0")]; - return buffer.join(""); -} -let NormalizeRegex = null; -let NormalizationMap = null; -function normalizeUnicode(str) { - if (!NormalizeRegex) { - NormalizeRegex = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu; - NormalizationMap = new Map([["ſt", "ſt"]]); - } - return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2)); -} -function getUuid() { - if (typeof crypto !== "undefined" && typeof crypto?.randomUUID === "function") { - return crypto.randomUUID(); - } - const buf = new Uint8Array(32); - if (typeof crypto !== "undefined" && typeof crypto?.getRandomValues === "function") { - crypto.getRandomValues(buf); - } else { - for (let i = 0; i < 32; i++) { - buf[i] = Math.floor(Math.random() * 255); - } - } - return bytesToString(buf); -} -const AnnotationPrefix = "pdfjs_internal_id_"; -const FontRenderOps = { - BEZIER_CURVE_TO: 0, - MOVE_TO: 1, - LINE_TO: 2, - QUADRATIC_CURVE_TO: 3, - RESTORE: 4, - SAVE: 5, - SCALE: 6, - TRANSFORM: 7, - TRANSLATE: 8 -}; - - -/***/ }) - -/******/ }); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/async module */ -/******/ (() => { -/******/ var webpackQueues = typeof Symbol === "function" ? Symbol("webpack queues") : "__webpack_queues__"; -/******/ var webpackExports = typeof Symbol === "function" ? Symbol("webpack exports") : "__webpack_exports__"; -/******/ var webpackError = typeof Symbol === "function" ? Symbol("webpack error") : "__webpack_error__"; -/******/ var resolveQueue = (queue) => { -/******/ if(queue && queue.d < 1) { -/******/ queue.d = 1; -/******/ queue.forEach((fn) => (fn.r--)); -/******/ queue.forEach((fn) => (fn.r-- ? fn.r++ : fn())); -/******/ } -/******/ } -/******/ var wrapDeps = (deps) => (deps.map((dep) => { -/******/ if(dep !== null && typeof dep === "object") { -/******/ if(dep[webpackQueues]) return dep; -/******/ if(dep.then) { -/******/ var queue = []; -/******/ queue.d = 0; -/******/ dep.then((r) => { -/******/ obj[webpackExports] = r; -/******/ resolveQueue(queue); -/******/ }, (e) => { -/******/ obj[webpackError] = e; -/******/ resolveQueue(queue); -/******/ }); -/******/ var obj = {}; -/******/ obj[webpackQueues] = (fn) => (fn(queue)); -/******/ return obj; -/******/ } -/******/ } -/******/ var ret = {}; -/******/ ret[webpackQueues] = x => {}; -/******/ ret[webpackExports] = dep; -/******/ return ret; -/******/ })); -/******/ __webpack_require__.a = (module, body, hasAwait) => { -/******/ var queue; -/******/ hasAwait && ((queue = []).d = -1); -/******/ var depQueues = new Set(); -/******/ var exports = module.exports; -/******/ var currentDeps; -/******/ var outerResolve; -/******/ var reject; -/******/ var promise = new Promise((resolve, rej) => { -/******/ reject = rej; -/******/ outerResolve = resolve; -/******/ }); -/******/ promise[webpackExports] = exports; -/******/ promise[webpackQueues] = (fn) => (queue && fn(queue), depQueues.forEach(fn), promise["catch"](x => {})); -/******/ module.exports = promise; -/******/ body((deps) => { -/******/ currentDeps = wrapDeps(deps); -/******/ var fn; -/******/ var getResult = () => (currentDeps.map((d) => { -/******/ if(d[webpackError]) throw d[webpackError]; -/******/ return d[webpackExports]; -/******/ })) -/******/ var promise = new Promise((resolve) => { -/******/ fn = () => (resolve(getResult)); -/******/ fn.r = 0; -/******/ var fnQueue = (q) => (q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn)))); -/******/ currentDeps.map((dep) => (dep[webpackQueues](fnQueue))); -/******/ }); -/******/ return fn.r ? promise : getResult(); -/******/ }, (err) => ((err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue))); -/******/ queue && queue.d < 0 && (queue.d = 0); -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/define property getters */ -/******/ (() => { -/******/ // define getter functions for harmony exports -/******/ __webpack_require__.d = (exports, definition) => { -/******/ for(var key in definition) { -/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); -/******/ } -/******/ } -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ (() => { -/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) -/******/ })(); -/******/ -/************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module used 'module' so it can't be inlined -/******/ var __webpack_exports__ = __webpack_require__(228); -/******/ __webpack_exports__ = globalThis.pdfjsLib = await (globalThis.pdfjsLibPromise = __webpack_exports__); - -/******/ var __webpack_exports__AbortException = __webpack_exports__.AbortException; -/******/ var __webpack_exports__AnnotationEditorLayer = __webpack_exports__.AnnotationEditorLayer; -/******/ var __webpack_exports__AnnotationEditorParamsType = __webpack_exports__.AnnotationEditorParamsType; -/******/ var __webpack_exports__AnnotationEditorType = __webpack_exports__.AnnotationEditorType; -/******/ var __webpack_exports__AnnotationEditorUIManager = __webpack_exports__.AnnotationEditorUIManager; -/******/ var __webpack_exports__AnnotationLayer = __webpack_exports__.AnnotationLayer; -/******/ var __webpack_exports__AnnotationMode = __webpack_exports__.AnnotationMode; -/******/ var __webpack_exports__CMapCompressionType = __webpack_exports__.CMapCompressionType; -/******/ var __webpack_exports__ColorPicker = __webpack_exports__.ColorPicker; -/******/ var __webpack_exports__DOMSVGFactory = __webpack_exports__.DOMSVGFactory; -/******/ var __webpack_exports__DrawLayer = __webpack_exports__.DrawLayer; -/******/ var __webpack_exports__FeatureTest = __webpack_exports__.FeatureTest; -/******/ var __webpack_exports__GlobalWorkerOptions = __webpack_exports__.GlobalWorkerOptions; -/******/ var __webpack_exports__ImageKind = __webpack_exports__.ImageKind; -/******/ var __webpack_exports__InvalidPDFException = __webpack_exports__.InvalidPDFException; -/******/ var __webpack_exports__MissingPDFException = __webpack_exports__.MissingPDFException; -/******/ var __webpack_exports__OPS = __webpack_exports__.OPS; -/******/ var __webpack_exports__Outliner = __webpack_exports__.Outliner; -/******/ var __webpack_exports__PDFDataRangeTransport = __webpack_exports__.PDFDataRangeTransport; -/******/ var __webpack_exports__PDFDateString = __webpack_exports__.PDFDateString; -/******/ var __webpack_exports__PDFWorker = __webpack_exports__.PDFWorker; -/******/ var __webpack_exports__PasswordResponses = __webpack_exports__.PasswordResponses; -/******/ var __webpack_exports__PermissionFlag = __webpack_exports__.PermissionFlag; -/******/ var __webpack_exports__PixelsPerInch = __webpack_exports__.PixelsPerInch; -/******/ var __webpack_exports__RenderingCancelledException = __webpack_exports__.RenderingCancelledException; -/******/ var __webpack_exports__UnexpectedResponseException = __webpack_exports__.UnexpectedResponseException; -/******/ var __webpack_exports__Util = __webpack_exports__.Util; -/******/ var __webpack_exports__VerbosityLevel = __webpack_exports__.VerbosityLevel; -/******/ var __webpack_exports__XfaLayer = __webpack_exports__.XfaLayer; -/******/ var __webpack_exports__build = __webpack_exports__.build; -/******/ var __webpack_exports__createValidAbsoluteUrl = __webpack_exports__.createValidAbsoluteUrl; -/******/ var __webpack_exports__fetchData = __webpack_exports__.fetchData; -/******/ var __webpack_exports__getDocument = __webpack_exports__.getDocument; -/******/ var __webpack_exports__getFilenameFromUrl = __webpack_exports__.getFilenameFromUrl; -/******/ var __webpack_exports__getPdfFilenameFromUrl = __webpack_exports__.getPdfFilenameFromUrl; -/******/ var __webpack_exports__getXfaPageViewport = __webpack_exports__.getXfaPageViewport; -/******/ var __webpack_exports__isDataScheme = __webpack_exports__.isDataScheme; -/******/ var __webpack_exports__isPdfFile = __webpack_exports__.isPdfFile; -/******/ var __webpack_exports__noContextMenu = __webpack_exports__.noContextMenu; -/******/ var __webpack_exports__normalizeUnicode = __webpack_exports__.normalizeUnicode; -/******/ var __webpack_exports__renderTextLayer = __webpack_exports__.renderTextLayer; -/******/ var __webpack_exports__setLayerDimensions = __webpack_exports__.setLayerDimensions; -/******/ var __webpack_exports__shadow = __webpack_exports__.shadow; -/******/ var __webpack_exports__updateTextLayer = __webpack_exports__.updateTextLayer; -/******/ var __webpack_exports__version = __webpack_exports__.version; -/******/ export { __webpack_exports__AbortException as AbortException, __webpack_exports__AnnotationEditorLayer as AnnotationEditorLayer, __webpack_exports__AnnotationEditorParamsType as AnnotationEditorParamsType, __webpack_exports__AnnotationEditorType as AnnotationEditorType, __webpack_exports__AnnotationEditorUIManager as AnnotationEditorUIManager, __webpack_exports__AnnotationLayer as AnnotationLayer, __webpack_exports__AnnotationMode as AnnotationMode, __webpack_exports__CMapCompressionType as CMapCompressionType, __webpack_exports__ColorPicker as ColorPicker, __webpack_exports__DOMSVGFactory as DOMSVGFactory, __webpack_exports__DrawLayer as DrawLayer, __webpack_exports__FeatureTest as FeatureTest, __webpack_exports__GlobalWorkerOptions as GlobalWorkerOptions, __webpack_exports__ImageKind as ImageKind, __webpack_exports__InvalidPDFException as InvalidPDFException, __webpack_exports__MissingPDFException as MissingPDFException, __webpack_exports__OPS as OPS, __webpack_exports__Outliner as Outliner, __webpack_exports__PDFDataRangeTransport as PDFDataRangeTransport, __webpack_exports__PDFDateString as PDFDateString, __webpack_exports__PDFWorker as PDFWorker, __webpack_exports__PasswordResponses as PasswordResponses, __webpack_exports__PermissionFlag as PermissionFlag, __webpack_exports__PixelsPerInch as PixelsPerInch, __webpack_exports__RenderingCancelledException as RenderingCancelledException, __webpack_exports__UnexpectedResponseException as UnexpectedResponseException, __webpack_exports__Util as Util, __webpack_exports__VerbosityLevel as VerbosityLevel, __webpack_exports__XfaLayer as XfaLayer, __webpack_exports__build as build, __webpack_exports__createValidAbsoluteUrl as createValidAbsoluteUrl, __webpack_exports__fetchData as fetchData, __webpack_exports__getDocument as getDocument, __webpack_exports__getFilenameFromUrl as getFilenameFromUrl, __webpack_exports__getPdfFilenameFromUrl as getPdfFilenameFromUrl, __webpack_exports__getXfaPageViewport as getXfaPageViewport, __webpack_exports__isDataScheme as isDataScheme, __webpack_exports__isPdfFile as isPdfFile, __webpack_exports__noContextMenu as noContextMenu, __webpack_exports__normalizeUnicode as normalizeUnicode, __webpack_exports__renderTextLayer as renderTextLayer, __webpack_exports__setLayerDimensions as setLayerDimensions, __webpack_exports__shadow as shadow, __webpack_exports__updateTextLayer as updateTextLayer, __webpack_exports__version as version }; -/******/ - -//# sourceMappingURL=pdf.mjs.map \ No newline at end of file diff --git a/projects/web/public/pdfjs-dist/build/pdf.worker.mjs b/projects/web/public/pdfjs-dist/build/pdf.worker.mjs deleted file mode 100644 index d89becb5c0fe18f3121d1b6e1915bf616eb931f6..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/build/pdf.worker.mjs +++ /dev/null @@ -1,4 +0,0 @@ -var __webpack_require__={d:(exports,definition)=>{for(var key in definition)__webpack_require__.o(definition,key)&&!__webpack_require__.o(exports,key)&&Object.defineProperty(exports,key,{enumerable:!0,get:definition[key]})},o:(obj,prop)=>Object.prototype.hasOwnProperty.call(obj,prop)},__webpack_exports__=globalThis.pdfjsWorker={};__webpack_require__.d(__webpack_exports__,{WorkerMessageHandler:()=>WorkerMessageHandler});const isNodeJS=!("object"!=typeof process||process+""!="[object process]"||process.versions.nw||process.versions.electron&&process.type&&"browser"!==process.type),IDENTITY_MATRIX=[1,0,0,1,0,0],FONT_IDENTITY_MATRIX=[.001,0,0,.001,0,0],MAX_IMAGE_SIZE_TO_CACHE=1e7,LINE_FACTOR=1.35,LINE_DESCENT_FACTOR=.35,BASELINE_FACTOR=LINE_DESCENT_FACTOR/LINE_FACTOR,RenderingIntentFlag={ANY:1,DISPLAY:2,PRINT:4,SAVE:8,ANNOTATIONS_FORMS:16,ANNOTATIONS_STORAGE:32,ANNOTATIONS_DISABLE:64,OPLIST:256},AnnotationMode={DISABLE:0,ENABLE:1,ENABLE_FORMS:2,ENABLE_STORAGE:3},AnnotationEditorPrefix="pdfjs_internal_editor_",AnnotationEditorType={DISABLE:-1,NONE:0,FREETEXT:3,HIGHLIGHT:9,STAMP:13,INK:15},AnnotationEditorParamsType={RESIZE:1,CREATE:2,FREETEXT_SIZE:11,FREETEXT_COLOR:12,FREETEXT_OPACITY:13,INK_COLOR:21,INK_THICKNESS:22,INK_OPACITY:23,HIGHLIGHT_COLOR:31,HIGHLIGHT_DEFAULT_COLOR:32,HIGHLIGHT_THICKNESS:33,HIGHLIGHT_FREE:34,HIGHLIGHT_SHOW_ALL:35},PermissionFlag={PRINT:4,MODIFY_CONTENTS:8,COPY:16,MODIFY_ANNOTATIONS:32,FILL_INTERACTIVE_FORMS:256,COPY_FOR_ACCESSIBILITY:512,ASSEMBLE:1024,PRINT_HIGH_QUALITY:2048},TextRenderingMode={FILL:0,STROKE:1,FILL_STROKE:2,INVISIBLE:3,FILL_ADD_TO_PATH:4,STROKE_ADD_TO_PATH:5,FILL_STROKE_ADD_TO_PATH:6,ADD_TO_PATH:7,FILL_STROKE_MASK:3,ADD_TO_PATH_FLAG:4},ImageKind={GRAYSCALE_1BPP:1,RGB_24BPP:2,RGBA_32BPP:3},AnnotationType={TEXT:1,LINK:2,FREETEXT:3,LINE:4,SQUARE:5,CIRCLE:6,POLYGON:7,POLYLINE:8,HIGHLIGHT:9,UNDERLINE:10,SQUIGGLY:11,STRIKEOUT:12,STAMP:13,CARET:14,INK:15,POPUP:16,FILEATTACHMENT:17,SOUND:18,MOVIE:19,WIDGET:20,SCREEN:21,PRINTERMARK:22,TRAPNET:23,WATERMARK:24,THREED:25,REDACT:26},AnnotationReplyType={GROUP:"Group",REPLY:"R"},AnnotationFlag={INVISIBLE:1,HIDDEN:2,PRINT:4,NOZOOM:8,NOROTATE:16,NOVIEW:32,READONLY:64,LOCKED:128,TOGGLENOVIEW:256,LOCKEDCONTENTS:512},AnnotationFieldFlag={READONLY:1,REQUIRED:2,NOEXPORT:4,MULTILINE:4096,PASSWORD:8192,NOTOGGLETOOFF:16384,RADIO:32768,PUSHBUTTON:65536,COMBO:131072,EDIT:262144,SORT:524288,FILESELECT:1048576,MULTISELECT:2097152,DONOTSPELLCHECK:4194304,DONOTSCROLL:8388608,COMB:16777216,RICHTEXT:33554432,RADIOSINUNISON:33554432,COMMITONSELCHANGE:67108864},AnnotationBorderStyleType={SOLID:1,DASHED:2,BEVELED:3,INSET:4,UNDERLINE:5},AnnotationActionEventType={E:"Mouse Enter",X:"Mouse Exit",D:"Mouse Down",U:"Mouse Up",Fo:"Focus",Bl:"Blur",PO:"PageOpen",PC:"PageClose",PV:"PageVisible",PI:"PageInvisible",K:"Keystroke",F:"Format",V:"Validate",C:"Calculate"},DocumentActionEventType={WC:"WillClose",WS:"WillSave",DS:"DidSave",WP:"WillPrint",DP:"DidPrint"},PageActionEventType={O:"PageOpen",C:"PageClose"},VerbosityLevel={ERRORS:0,WARNINGS:1,INFOS:5},CMapCompressionType={NONE:0,BINARY:1},OPS={dependency:1,setLineWidth:2,setLineCap:3,setLineJoin:4,setMiterLimit:5,setDash:6,setRenderingIntent:7,setFlatness:8,setGState:9,save:10,restore:11,transform:12,moveTo:13,lineTo:14,curveTo:15,curveTo2:16,curveTo3:17,closePath:18,rectangle:19,stroke:20,closeStroke:21,fill:22,eoFill:23,fillStroke:24,eoFillStroke:25,closeFillStroke:26,closeEOFillStroke:27,endPath:28,clip:29,eoClip:30,beginText:31,endText:32,setCharSpacing:33,setWordSpacing:34,setHScale:35,setLeading:36,setFont:37,setTextRenderingMode:38,setTextRise:39,moveText:40,setLeadingMoveText:41,setTextMatrix:42,nextLine:43,showText:44,showSpacedText:45,nextLineShowText:46,nextLineSetSpacingShowText:47,setCharWidth:48,setCharWidthAndBounds:49,setStrokeColorSpace:50,setFillColorSpace:51,setStrokeColor:52,setStrokeColorN:53,setFillColor:54,setFillColorN:55,setStrokeGray:56,setFillGray:57,setStrokeRGBColor:58,setFillRGBColor:59,setStrokeCMYKColor:60,setFillCMYKColor:61,shadingFill:62,beginInlineImage:63,beginImageData:64,endInlineImage:65,paintXObject:66,markPoint:67,markPointProps:68,beginMarkedContent:69,beginMarkedContentProps:70,endMarkedContent:71,beginCompat:72,endCompat:73,paintFormXObjectBegin:74,paintFormXObjectEnd:75,beginGroup:76,endGroup:77,beginAnnotation:80,endAnnotation:81,paintImageMaskXObject:83,paintImageMaskXObjectGroup:84,paintImageXObject:85,paintInlineImageXObject:86,paintInlineImageXObjectGroup:87,paintImageXObjectRepeat:88,paintImageMaskXObjectRepeat:89,paintSolidColorImageMask:90,constructPath:91},PasswordResponses={NEED_PASSWORD:1,INCORRECT_PASSWORD:2};let verbosity=VerbosityLevel.WARNINGS;function setVerbosityLevel(level){Number.isInteger(level)&&(verbosity=level)}function getVerbosityLevel(){return verbosity}function info(msg){verbosity>=VerbosityLevel.INFOS&&console.log("Info: "+msg)}function warn(msg){verbosity>=VerbosityLevel.WARNINGS&&console.log("Warning: "+msg)}function unreachable(msg){throw new Error(msg)}function assert(cond,msg){cond||unreachable(msg)}function _isValidProtocol(url){switch(url?.protocol){case"http:":case"https:":case"ftp:":case"mailto:":case"tel:":return!0;default:return!1}}function createValidAbsoluteUrl(url,baseUrl=null,options=null){if(url)try{if(options&&"string"==typeof url)if(options.addDefaultProtocol&&url.startsWith("www.")&&2<=url.match(/\./g)?.length&&(url="http://"+url),options.tryConvertEncoding)try{url=stringToUTF8String(url)}catch{}var absoluteUrl=baseUrl?new URL(url,baseUrl):new URL(url);if(_isValidProtocol(absoluteUrl))return absoluteUrl}catch{}return null}function shadow(obj,prop,value,nonSerializable=!1){return Object.defineProperty(obj,prop,{value:value,enumerable:!nonSerializable,configurable:!0,writable:!1}),value}const BaseException=function(){function BaseException(message,name){this.constructor===BaseException&&unreachable("Cannot initialize BaseException."),this.message=message,this.name=name}return BaseException.prototype=new Error,BaseException.constructor=BaseException}();class PasswordException extends BaseException{constructor(msg,code){super(msg,"PasswordException"),this.code=code}}class UnknownErrorException extends BaseException{constructor(msg,details){super(msg,"UnknownErrorException"),this.details=details}}class InvalidPDFException extends BaseException{constructor(msg){super(msg,"InvalidPDFException")}}class MissingPDFException extends BaseException{constructor(msg){super(msg,"MissingPDFException")}}class UnexpectedResponseException extends BaseException{constructor(msg,status){super(msg,"UnexpectedResponseException"),this.status=status}}class FormatError extends BaseException{constructor(msg){super(msg,"FormatError")}}class AbortException extends BaseException{constructor(msg){super(msg,"AbortException")}}function bytesToString(bytes){"object"==typeof bytes&&void 0!==bytes?.length||unreachable("Invalid argument for bytesToString");var length=bytes.length;if(length<8192)return String.fromCharCode.apply(null,bytes);var strBuf=[];for(let i=0;i>24&255,value>>16&255,value>>8&255,255&value)}function objectSize(obj){return Object.keys(obj).length}function objectFromMap(map){var key,value,obj=Object.create(null);for([key,value]of map)obj[key]=value;return obj}function isLittleEndian(){var buffer8=new Uint8Array(4),buffer8=(buffer8[0]=1,new Uint32Array(buffer8.buffer,0,1));return 1===buffer8[0]}function isEvalSupported(){try{return new Function(""),!0}catch{return!1}}class FeatureTest{static get isLittleEndian(){return shadow(this,"isLittleEndian",isLittleEndian())}static get isEvalSupported(){return shadow(this,"isEvalSupported",isEvalSupported())}static get isOffscreenCanvasSupported(){return shadow(this,"isOffscreenCanvasSupported","undefined"!=typeof OffscreenCanvas)}static get platform(){return"undefined"!=typeof navigator&&"string"==typeof navigator?.platform?shadow(this,"platform",{isMac:navigator.platform.includes("Mac")}):shadow(this,"platform",{isMac:!1})}static get isCSSRoundSupported(){return shadow(this,"isCSSRoundSupported",globalThis.CSS?.supports?.("width: round(1.5px, 1px)"))}}const hexNumbers=Array.from(Array(256).keys(),n=>n.toString(16).padStart(2,"0"));class Util{static makeHexColor(r,g,b){return"#"+hexNumbers[r]+hexNumbers[g]+hexNumbers[b]}static scaleMinMax(transform,minMax){let temp;transform[0]?(transform[0]<0&&(temp=minMax[0],minMax[0]=minMax[2],minMax[2]=temp),minMax[0]*=transform[0],minMax[2]*=transform[0],transform[3]<0&&(temp=minMax[1],minMax[1]=minMax[3],minMax[3]=temp),minMax[1]*=transform[3],minMax[3]*=transform[3]):(temp=minMax[0],minMax[0]=minMax[1],minMax[1]=temp,temp=minMax[2],minMax[2]=minMax[3],minMax[3]=temp,transform[1]<0&&(temp=minMax[1],minMax[1]=minMax[3],minMax[3]=temp),minMax[1]*=transform[1],minMax[3]*=transform[1],transform[2]<0&&(temp=minMax[0],minMax[0]=minMax[2],minMax[2]=temp),minMax[0]*=transform[2],minMax[2]*=transform[2]),minMax[0]+=transform[4],minMax[1]+=transform[5],minMax[2]+=transform[4],minMax[3]+=transform[5]}static transform(m1,m2){return[m1[0]*m2[0]+m1[2]*m2[1],m1[1]*m2[0]+m1[3]*m2[1],m1[0]*m2[2]+m1[2]*m2[3],m1[1]*m2[2]+m1[3]*m2[3],m1[0]*m2[4]+m1[2]*m2[5]+m1[4],m1[1]*m2[4]+m1[3]*m2[5]+m1[5]]}static applyTransform(p,m){return[p[0]*m[0]+p[1]*m[2]+m[4],p[0]*m[1]+p[1]*m[3]+m[5]]}static applyInverseTransform(p,m){var d=m[0]*m[3]-m[1]*m[2];return[(p[0]*m[3]-p[1]*m[2]+m[2]*m[5]-m[4]*m[3])/d,(-p[0]*m[1]+p[1]*m[0]+m[4]*m[1]-m[5]*m[0])/d]}static getAxialAlignedBoundingBox(r,m){var p1=this.applyTransform(r,m),p2=this.applyTransform(r.slice(2,4),m),p3=this.applyTransform([r[0],r[3]],m),r=this.applyTransform([r[2],r[1]],m);return[Math.min(p1[0],p2[0],p3[0],r[0]),Math.min(p1[1],p2[1],p3[1],r[1]),Math.max(p1[0],p2[0],p3[0],r[0]),Math.max(p1[1],p2[1],p3[1],r[1])]}static inverseTransform(m){var d=m[0]*m[3]-m[1]*m[2];return[m[3]/d,-m[1]/d,-m[2]/d,m[0]/d,(m[2]*m[5]-m[4]*m[3])/d,(m[4]*m[1]-m[5]*m[0])/d]}static singularValueDecompose2dScale(m){var transpose=[m[0],m[2],m[1],m[3]],a=m[0]*transpose[0]+m[1]*transpose[2],b=m[0]*transpose[1]+m[1]*transpose[3],c=m[2]*transpose[0]+m[3]*transpose[2],m=m[2]*transpose[1]+m[3]*transpose[3],transpose=(a+m)/2,a=Math.sqrt((a+m)**2-4*(a*m-c*b))/2,m=transpose-a||1;return[Math.sqrt(transpose+a||1),Math.sqrt(m)]}static normalizeRect(rect){var r=rect.slice(0);return rect[0]>rect[2]&&(r[0]=rect[2],r[2]=rect[0]),rect[1]>rect[3]&&(r[1]=rect[3],r[3]=rect[1]),r}static intersect(rect1,rect2){var yLow,xLow=Math.max(Math.min(rect1[0],rect1[2]),Math.min(rect2[0],rect2[2])),xHigh=Math.min(Math.max(rect1[0],rect1[2]),Math.max(rect2[0],rect2[2]));return xHighp1?p1.normalize("NFKC"):NormalizationMap.get(p2))}function getUuid(){if("undefined"!=typeof crypto&&"function"==typeof crypto?.randomUUID)return crypto.randomUUID();var buf=new Uint8Array(32);if("undefined"!=typeof crypto&&"function"==typeof crypto?.getRandomValues)crypto.getRandomValues(buf);else for(let i=0;i<32;i++)buf[i]=Math.floor(255*Math.random());return bytesToString(buf)}const AnnotationPrefix="pdfjs_internal_id_",FontRenderOps={BEZIER_CURVE_TO:0,MOVE_TO:1,LINE_TO:2,QUADRATIC_CURVE_TO:3,RESTORE:4,SAVE:5,SCALE:6,TRANSFORM:7,TRANSLATE:8},CIRCULAR_REF=Symbol("CIRCULAR_REF"),EOF=Symbol("EOF");let CmdCache=Object.create(null),NameCache=Object.create(null),RefCache=Object.create(null);function clearPrimitiveCaches(){CmdCache=Object.create(null),NameCache=Object.create(null),RefCache=Object.create(null)}class Name{constructor(name){this.name=name}static get(name){return NameCache[name]||=new Name(name)}}class Cmd{constructor(cmd){this.cmd=cmd}static get(cmd){return CmdCache[cmd]||=new Cmd(cmd)}}const nonSerializable=function(){return nonSerializable};class Dict{constructor(xref=null){this._map=Object.create(null),this.xref=xref,this.objId=null,this.suppressEncryption=!1,this.__nonSerializable__=nonSerializable}assignXref(newXref){this.xref=newXref}get size(){return Object.keys(this._map).length}get(key1,key2,key3){let value=this._map[key1];return(value=void 0===value&&void 0!==key2&&void 0===(value=this._map[key2])&&void 0!==key3?this._map[key3]:value)instanceof Ref&&this.xref?this.xref.fetch(value,this.suppressEncryption):value}async getAsync(key1,key2,key3){let value=this._map[key1];return(value=void 0===value&&void 0!==key2&&void 0===(value=this._map[key2])&&void 0!==key3?this._map[key3]:value)instanceof Ref&&this.xref?this.xref.fetchAsync(value,this.suppressEncryption):value}getArray(key1,key2,key3){let value=this._map[key1];if((value=void 0===value&&void 0!==key2&&void 0===(value=this._map[key2])&&void 0!==key3?this._map[key3]:value)instanceof Ref&&this.xref&&(value=this.xref.fetch(value,this.suppressEncryption)),Array.isArray(value))for(let i=0,ii=(value=value.slice()).length;i{unreachable("Should not call `set` on the empty dictionary.")},shadow(this,"empty",emptyDict)}static merge({xref,dictArray,mergeSubDicts=!1}){var name,values,mergedDict=new Dict(xref),properties=new Map;for(const dict of dictArray)if(dict instanceof Dict)for(var[key,value]of Object.entries(dict._map)){let property=properties.get(key);if(void 0===property)property=[],properties.set(key,property);else if(!(mergeSubDicts&&value instanceof Dict))continue;property.push(value)}for([name,values]of properties)if(1!==values.length&&values[0]instanceof Dict){var subDict=new Dict(xref);for(const dict of values)for(const[key,value]of Object.entries(dict._map))void 0===subDict._map[key]&&(subDict._map[key]=value);0>24}function readUint16(data,offset){return data[offset]<<8|data[offset+1]}function readUint32(data,offset){return(data[offset]<<24|data[offset+1]<<16|data[offset+2]<<8|data[offset+3])>>>0}function isWhiteSpace(ch){return 32===ch||9===ch||13===ch||10===ch}function isNumberArray(arr,len){return Array.isArray(arr)&&(null===len||arr.length===len)&&arr.every(x=>"number"==typeof x)}function parseXFAPath(path){const positionPattern=/(.+)\[(\d+)\]$/;return path.split(".").map(component=>{var m=component.match(positionPattern);return m?{name:m[1],pos:parseInt(m[2],10)}:{name:component,pos:0}})}function escapePDFName(str){var buffer=[];let start=0;for(let i=0,ii=str.length;i"\n"===match?"\\n":"\r"===match?"\\r":"\\"+match)}function _collectJS(entry,xref,list,parents){if(entry){let parent=null;if(entry instanceof Ref){if(parents.has(entry))return;parent=entry,parents.put(parent),entry=xref.fetch(entry)}if(Array.isArray(entry))for(const element of entry)_collectJS(element,xref,list,parents);else if(entry instanceof Dict){if(isName(entry.get("S"),"JavaScript")){var js=entry.get("JS");let code;js instanceof BaseStream?code=js.getString():"string"==typeof js&&(code=js),(code&&=stringToPDFString(code).replaceAll("\0",""))&&list.push(code)}_collectJS(entry.getRaw("Next"),xref,list,parents)}parent&&parents.remove(parent)}}function collectActions(xref,dict,eventType){var actions=Object.create(null),additionalActionsDicts=getInheritableProperty({dict:dict,key:"AA",stopWhenFound:!1});if(additionalActionsDicts)for(let i=additionalActionsDicts.length-1;0<=i;i--){var additionalActions=additionalActionsDicts[i];if(additionalActions instanceof Dict)for(const key of additionalActions.getKeys()){var list,action=eventType[key];action&&(list=[],_collectJS(additionalActions.getRaw(key),xref,list,new RefSet),0: ${fontFamily}.`),!1;return!0}function validateCSSFont(cssFontInfo){var CSS_FONT_WEIGHT_VALUES=new Set(["100","200","300","400","500","600","700","800","900","1000","normal","bold","bolder","lighter"]),{fontFamily,fontWeight,italicAngle}=cssFontInfo;return!!validateFontName(fontFamily,!0)&&(fontFamily=fontWeight?fontWeight.toString():"",cssFontInfo.fontWeight=CSS_FONT_WEIGHT_VALUES.has(fontFamily)?fontFamily:"400",fontWeight=parseFloat(italicAngle),cssFontInfo.italicAngle=isNaN(fontWeight)||fontWeight<-90||90>8&255).toString(16).padStart(2,"0"),(255&char).toString(16).padStart(2,"0"))}return buf.join("")}function stringToUTF16String(str,bigEndian=!1){var buf=[];bigEndian&&buf.push("þÿ");for(let i=0,ii=str.length;i>8&255),String.fromCharCode(255&char))}return buf.join("")}function getRotationMatrix(rotation,width,height){switch(rotation){case 90:return[0,1,-1,0,width,0];case 180:return[-1,0,0,-1,width,height];case 270:return[0,-1,1,0,0,height];default:throw new Error("Invalid rotation")}}function getSizeInBytes(x){return Math.ceil(Math.ceil(Math.log2(1+x))/8)}class Stream extends BaseStream{constructor(arrayBuffer,start,length,dict){super(),this.bytes=arrayBuffer instanceof Uint8Array?arrayBuffer:new Uint8Array(arrayBuffer),this.start=start||0,this.pos=this.start,this.end=start+length||this.bytes.length,this.dict=dict}get length(){return this.end-this.start}get isEmpty(){return 0===this.length}getByte(){return this.pos>=this.end?-1:this.bytes[this.pos++]}getBytes(length){var bytes=this.bytes,pos=this.pos,strEnd=this.end;if(!length)return bytes.subarray(pos,strEnd);let end=pos+length;return end>strEnd&&(end=strEnd),this.pos=end,bytes.subarray(pos,end)}getByteRange(begin,end){return end>this.end&&(end=this.end),this.bytes.subarray(begin=begin<0?0:begin,end)}reset(){this.pos=this.start}moveStart(){this.start=this.pos}makeSubStream(start,length,dict=null){return new Stream(this.bytes.buffer,start,length,dict)}}class StringStream extends Stream{constructor(str){super(stringToBytes(str))}}class NullStream extends Stream{constructor(){super(new Uint8Array(0))}}class ChunkedStream extends Stream{constructor(length,chunkSize,manager){super(new Uint8Array(length),0,length,null),this.chunkSize=chunkSize,this._loadedChunks=new Set,this.numChunks=Math.ceil(length/chunkSize),this.manager=manager,this.progressiveDataLength=0,this.lastSuccessfulEnsureByteChunk=-1}getMissingChunks(){var chunks=[];for(let chunk=0,n=this.numChunks;chunk=this.end?this.numChunks:Math.floor(position/this.chunkSize));for(let curChunk=beginChunk;curChunkthis.numChunks)&&chunk!==this.lastSuccessfulEnsureByteChunk){if(!this._loadedChunks.has(chunk))throw new MissingDataException(pos,pos+1);this.lastSuccessfulEnsureByteChunk=chunk}}}ensureRange(begin,end){if(!(end<=begin||end<=this.progressiveDataLength)){var beginChunk=Math.floor(begin/this.chunkSize);if(!(beginChunk>this.numChunks)){var endChunk=Math.min(Math.floor((end-1)/this.chunkSize)+1,this.numChunks);for(let chunk=beginChunk;chunk=this.end?-1:(pos>=this.progressiveDataLength&&this.ensureByte(pos),this.bytes[this.pos++])}getBytes(length){var bytes=this.bytes,pos=this.pos,strEnd=this.end;if(!length)return strEnd>this.progressiveDataLength&&this.ensureRange(pos,strEnd),bytes.subarray(pos,strEnd);let end=pos+length;return(end=end>strEnd?strEnd:end)>this.progressiveDataLength&&this.ensureRange(pos,end),this.pos=end,bytes.subarray(pos,end)}getByteRange(begin,end){return begin<0&&(begin=0),(end=end>this.end?this.end:end)>this.progressiveDataLength&&this.ensureRange(begin,end),this.bytes.subarray(begin,end)}makeSubStream(start,length,dict=null){function ChunkedStreamSubstream(){}length?start+length>this.progressiveDataLength&&this.ensureRange(start,start+length):start>=this.progressiveDataLength&&this.ensureByte(start),(ChunkedStreamSubstream.prototype=Object.create(this)).getMissingChunks=function(){var chunkSize=this.chunkSize,beginChunk=Math.floor(this.start/chunkSize),endChunk=Math.floor((this.end-1)/chunkSize)+1,missingChunks=[];for(let chunk=beginChunk;chunk{const readChunk=({value,done})=>{try{var chunkData;done?(chunkData=arrayBuffersToBytes(chunks),chunks=null,resolve(chunkData)):(loaded+=value.byteLength,rangeReader.isStreamingSupported&&this.onProgress({loaded:loaded}),chunks.push(value),rangeReader.read().then(readChunk,reject))}catch(e){reject(e)}};rangeReader.read().then(readChunk,reject)}).then(data=>{this.aborted||this.onReceiveData({chunk:data,begin:begin})})}requestAllChunks(noFetch=!1){return noFetch||(noFetch=this.stream.getMissingChunks(),this._requestChunks(noFetch)),this._loadedStreamCapability.promise}_requestChunks(chunks){var requestId=this.currRequestId++,chunksNeeded=new Set;this._chunksNeededByRequest.set(requestId,chunksNeeded);for(const chunk of chunks)this.stream.hasChunk(chunk)||chunksNeeded.add(chunk);if(0===chunksNeeded.size)return Promise.resolve();var capability=Promise.withResolvers(),chunksToRequest=(this._promisesByRequest.set(requestId,capability),[]);for(const chunk of chunksNeeded){let requestIds=this._requestsByChunk.get(chunk);requestIds||(requestIds=[],this._requestsByChunk.set(chunk,requestIds),chunksToRequest.push(chunk)),requestIds.push(requestId)}if(0{if(!this.aborted)throw reason})}getStream(){return this.stream}requestRange(begin,end){end=Math.min(end,this.length);var begin=this.getBeginChunk(begin),endChunk=this.getEndChunk(end),chunks=[];for(let chunk=begin;chunkthis.amax||this.bmin>this.bmax)&&(info("Invalid Range, falling back to defaults"),this.amin=-100,this.amax=100,this.bmin=-100,this.bmax=100)}#fn_g(x){return 6/29<=x?x**3:108/841*(x-4/29)}#decode(value,high1,low2,high2){return low2+value*(high2-low2)/high1}#toRgb(src,srcOffset,maxVal,dest,destOffset){let Ls=src[srcOffset],as=src[srcOffset+1],bs=src[srcOffset+2];!1!==maxVal&&(Ls=this.#decode(Ls,maxVal,0,100),as=this.#decode(as,maxVal,this.amin,this.amax),bs=this.#decode(bs,maxVal,this.bmin,this.bmax)),as>this.amax?as=this.amax:asthis.bmax?bs=this.bmax:bs>>0}function hexToStr(a,size){return 1===size?String.fromCharCode(a[0],a[1]):3===size?String.fromCharCode(a[0],a[1],a[2],a[3]):String.fromCharCode(...a.subarray(0,size+1))}function addHex(a,b,size){let c=0;for(let i=size;0<=i;i--)c+=a[i]+b[i],a[i]=255&c,c>>=8}function incHex(a,size){let c=1;for(let i=size;0<=i&&0>=8}const MAX_NUM_SIZE=16,MAX_ENCODED_NUM_SIZE=19;class BinaryCMapStream{constructor(data){this.buffer=data,this.pos=0,this.end=data.length,this.tmpBuf=new Uint8Array(MAX_ENCODED_NUM_SIZE)}readByte(){return this.pos>=this.end?-1:this.buffer[this.pos++]}readNumber(){let n=0;var last;do{var b=this.readByte();if(b<0)throw new FormatError("unexpected EOF in bcmap");last=!(128&b),n=n<<7|127&b}while(!last);return n}readSigned(){var n=this.readNumber();return 1&n?~(n>>>1):n>>>1}readHex(num,size){num.set(this.buffer.subarray(this.pos,this.pos+size+1)),this.pos+=size+1}readHexNumber(num,size){var last,stack=this.tmpBuf;let sp=0;do{var b=this.readByte();if(b<0)throw new FormatError("unexpected EOF in bcmap");last=!(128&b),stack[sp++]=127&b}while(!last);let i=size,buffer=0,bufferSize=0;for(;0<=i;){for(;bufferSize<8&&0>=8,bufferSize-=8}}readHexSigned(num,size){this.readHexNumber(num,size);var sign=1&num[size]?255:0;let c=0;for(let i=0;i<=size;i++)c=(1&c)<<8|num[i],num[i]=c>>1^sign}readString(){var len=this.readNumber(),buf=new Array(len);for(let i=0;i>5;if(7==type)switch(31&b){case 0:stream.readString();break;case 1:useCMap=stream.readString()}else{var sequence=!!(16&b),dataSize=15&b;if(1+dataSize>MAX_NUM_SIZE)throw new Error("BinaryCMapReader.process: Invalid dataSize.");var subitemsCount=stream.readNumber();switch(type){case 0:stream.readHex(start,dataSize),stream.readHexNumber(end,dataSize),addHex(end,start,dataSize),cMap.addCodespaceRange(1+dataSize,hexToInt(start,dataSize),hexToInt(end,dataSize));for(let i=1;ilength&&(end=length)}else{for(;!this.eof;)this.readBlock(ignoreColorSpace);end=this.bufferLength}return this.pos=end,this.buffer.subarray(pos,end)}reset(){this.pos=0}makeSubStream(start,length,dict=null){if(void 0===length)for(;!this.eof;)this.readBlock();else for(var end=start+length;this.bufferLength<=end&&!this.eof;)this.readBlock();return new Stream(this.buffer,start,length,dict)}getBaseStreams(){return this.str?this.str.getBaseStreams():null}}class StreamsSequenceStream extends DecodeStream{constructor(streams,onError=null){let maybeLength=0;for(const stream of streams)maybeLength+=stream instanceof DecodeStream?stream._rawMinBufferLength:stream.length;super(maybeLength),this.streams=streams,this._onError=onError}readBlock(){var streams=this.streams;if(0===streams.length)this.eof=!0;else{streams=streams.shift();let chunk;try{chunk=streams.getBytes()}catch(reason){if(this._onError)return void this._onError(reason,streams.dict?.objId);throw reason}var streams=this.bufferLength,newLength=streams+chunk.length;this.ensureBuffer(newLength).set(chunk,streams),this.bufferLength=newLength}}getBaseStreams(){var baseStreamsBuf=[];for(const stream of this.streams){var baseStreams=stream.getBaseStreams();baseStreams&&baseStreamsBuf.push(...baseStreams)}return 0>=8}}}}class AsciiHexStream extends DecodeStream{constructor(str,maybeLength){maybeLength&&(maybeLength*=.5),super(maybeLength),this.str=str,this.dict=str.dict,this.firstDigit=-1}readBlock(){var bytes=this.str.getBytes(8e3);if(bytes.length){var maxDecodeLength=bytes.length+1>>1,buffer=this.ensureBuffer(this.bufferLength+maxDecodeLength);let bufferLength=this.bufferLength,firstDigit=this.firstDigit;for(const ch of bytes){let digit;if(48<=ch&&ch<=57)digit=15&ch;else{if(!(65<=ch&&ch<=70||97<=ch&&ch<=102)){if(62!==ch)continue;this.eof=!0;break}digit=9+(15&ch)}firstDigit=firstDigit<0?digit:(buffer[bufferLength++]=firstDigit<<4|digit,-1)}0<=firstDigit&&this.eof&&(buffer[bufferLength++]=firstDigit<<4,firstDigit=-1),this.firstDigit=firstDigit,this.bufferLength=bufferLength}else this.eof=!0}}const ccittEOL=-2,ccittEOF=-1,twoDimPass=0,twoDimHoriz=1,twoDimVert0=2,twoDimVertR1=3,twoDimVertL1=4,twoDimVertR2=5,twoDimVertL2=6,twoDimVertR3=7,twoDimVertL3=8,twoDimTable=[[-1,-1],[-1,-1],[7,twoDimVertL3],[7,twoDimVertR3],[6,twoDimVertL2],[6,twoDimVertL2],[6,twoDimVertR2],[6,twoDimVertR2],[4,twoDimPass],[4,twoDimPass],[4,twoDimPass],[4,twoDimPass],[4,twoDimPass],[4,twoDimPass],[4,twoDimPass],[4,twoDimPass],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimHoriz],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertL1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[3,twoDimVertR1],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0],[1,twoDimVert0]],whiteTable1=[[-1,-1],[12,ccittEOL],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[11,1792],[11,1792],[12,1984],[12,2048],[12,2112],[12,2176],[12,2240],[12,2304],[11,1856],[11,1856],[11,1920],[11,1920],[12,2368],[12,2432],[12,2496],[12,2560]],whiteTable2=[[-1,-1],[-1,-1],[-1,-1],[-1,-1],[8,29],[8,29],[8,30],[8,30],[8,45],[8,45],[8,46],[8,46],[7,22],[7,22],[7,22],[7,22],[7,23],[7,23],[7,23],[7,23],[8,47],[8,47],[8,48],[8,48],[6,13],[6,13],[6,13],[6,13],[6,13],[6,13],[6,13],[6,13],[7,20],[7,20],[7,20],[7,20],[8,33],[8,33],[8,34],[8,34],[8,35],[8,35],[8,36],[8,36],[8,37],[8,37],[8,38],[8,38],[7,19],[7,19],[7,19],[7,19],[8,31],[8,31],[8,32],[8,32],[6,1],[6,1],[6,1],[6,1],[6,1],[6,1],[6,1],[6,1],[6,12],[6,12],[6,12],[6,12],[6,12],[6,12],[6,12],[6,12],[8,53],[8,53],[8,54],[8,54],[7,26],[7,26],[7,26],[7,26],[8,39],[8,39],[8,40],[8,40],[8,41],[8,41],[8,42],[8,42],[8,43],[8,43],[8,44],[8,44],[7,21],[7,21],[7,21],[7,21],[7,28],[7,28],[7,28],[7,28],[8,61],[8,61],[8,62],[8,62],[8,63],[8,63],[8,0],[8,0],[8,320],[8,320],[8,384],[8,384],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[7,27],[7,27],[7,27],[7,27],[8,59],[8,59],[8,60],[8,60],[9,1472],[9,1536],[9,1600],[9,1728],[7,18],[7,18],[7,18],[7,18],[7,24],[7,24],[7,24],[7,24],[8,49],[8,49],[8,50],[8,50],[8,51],[8,51],[8,52],[8,52],[7,25],[7,25],[7,25],[7,25],[8,55],[8,55],[8,56],[8,56],[8,57],[8,57],[8,58],[8,58],[6,192],[6,192],[6,192],[6,192],[6,192],[6,192],[6,192],[6,192],[6,1664],[6,1664],[6,1664],[6,1664],[6,1664],[6,1664],[6,1664],[6,1664],[8,448],[8,448],[8,512],[8,512],[9,704],[9,768],[8,640],[8,640],[8,576],[8,576],[9,832],[9,896],[9,960],[9,1024],[9,1088],[9,1152],[9,1216],[9,1280],[9,1344],[9,1408],[7,256],[7,256],[7,256],[7,256],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[6,16],[6,16],[6,16],[6,16],[6,16],[6,16],[6,16],[6,16],[6,17],[6,17],[6,17],[6,17],[6,17],[6,17],[6,17],[6,17],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[6,14],[6,14],[6,14],[6,14],[6,14],[6,14],[6,14],[6,14],[6,15],[6,15],[6,15],[6,15],[6,15],[6,15],[6,15],[6,15],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7]],blackTable1=[[-1,-1],[-1,-1],[12,ccittEOL],[12,ccittEOL],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[11,1792],[11,1792],[11,1792],[11,1792],[12,1984],[12,1984],[12,2048],[12,2048],[12,2112],[12,2112],[12,2176],[12,2176],[12,2240],[12,2240],[12,2304],[12,2304],[11,1856],[11,1856],[11,1856],[11,1856],[11,1920],[11,1920],[11,1920],[11,1920],[12,2368],[12,2368],[12,2432],[12,2432],[12,2496],[12,2496],[12,2560],[12,2560],[10,18],[10,18],[10,18],[10,18],[10,18],[10,18],[10,18],[10,18],[12,52],[12,52],[13,640],[13,704],[13,768],[13,832],[12,55],[12,55],[12,56],[12,56],[13,1280],[13,1344],[13,1408],[13,1472],[12,59],[12,59],[12,60],[12,60],[13,1536],[13,1600],[11,24],[11,24],[11,24],[11,24],[11,25],[11,25],[11,25],[11,25],[13,1664],[13,1728],[12,320],[12,320],[12,384],[12,384],[12,448],[12,448],[13,512],[13,576],[12,53],[12,53],[12,54],[12,54],[13,896],[13,960],[13,1024],[13,1088],[13,1152],[13,1216],[10,64],[10,64],[10,64],[10,64],[10,64],[10,64],[10,64],[10,64]],blackTable2=[[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[11,23],[11,23],[12,50],[12,51],[12,44],[12,45],[12,46],[12,47],[12,57],[12,58],[12,61],[12,256],[10,16],[10,16],[10,16],[10,16],[10,17],[10,17],[10,17],[10,17],[12,48],[12,49],[12,62],[12,63],[12,30],[12,31],[12,32],[12,33],[12,40],[12,41],[11,22],[11,22],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[9,15],[9,15],[9,15],[9,15],[9,15],[9,15],[9,15],[9,15],[12,128],[12,192],[12,26],[12,27],[12,28],[12,29],[11,19],[11,19],[11,20],[11,20],[12,34],[12,35],[12,36],[12,37],[12,38],[12,39],[11,21],[11,21],[12,42],[12,43],[10,0],[10,0],[10,0],[10,0],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12]],blackTable3=[[-1,-1],[-1,-1],[-1,-1],[-1,-1],[6,9],[6,8],[5,7],[5,7],[4,6],[4,6],[4,6],[4,6],[4,5],[4,5],[4,5],[4,5],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2]];class CCITTFaxDecoder{constructor(source,options={}){if(!source||"function"!=typeof source.next)throw new Error('CCITTFaxDecoder - invalid "source" parameter.');this.source=source,this.eof=!1,this.encoding=options.K||0,this.eoline=options.EndOfLine||!1,this.byteAlign=options.EncodedByteAlign||!1,this.columns=options.Columns||1728,this.rows=options.Rows||0,this.eoblock=options.EndOfBlock??!0,this.black=options.BlackIs1||!1,this.codingLine=new Uint32Array(this.columns+1),this.refLine=new Uint32Array(this.columns+2),this.codingLine[0]=this.columns,this.codingPos=0,this.row=0,this.nextLine2D=this.encoding<0,this.inputBits=0,this.inputBuf=0,this.outputBits=0,this.rowsDone=!1;let code1;for(;0===(code1=this._lookBits(12));)this._eatBits(1);1===code1&&this._eatBits(12),0>1==1)break;this._eatBits(1)}this._eatBits(12),0bits?(c<<=bits,1&this.codingPos||(c|=255>>8-bits),this.outputBits-=bits,bits=0):(c<<=this.outputBits,1&this.codingPos||(c|=255>>8-this.outputBits),bits-=this.outputBits,this.outputBits=0,codingLine[this.codingPos]codingLine[codingPos]&&(a1>this.columns&&(info("row is wrong length"),this.err=!0,a1=this.columns),1&codingPos^blackPixels&&++codingPos,codingLine[codingPos]=a1),this.codingPos=codingPos}_addPixelsNeg(a1,blackPixels){var codingLine=this.codingLine;let codingPos=this.codingPos;if(a1>codingLine[codingPos])a1>this.columns&&(info("row is wrong length"),this.err=!0,a1=this.columns),1&codingPos^blackPixels&&++codingPos,codingLine[codingPos]=a1;else if(a1=limitValue){var p=table[code-limitValue];if(p[0]===i)return this._eatBits(i),[!0,p[1],!0]}}return[!1,0,!1]}_getTwoDimCode(){if(this.eoblock){if(code=this._lookBits(7),0<(code=twoDimTable[code])?.[0])return this._eatBits(code[0]),code[1]}else{var code=this._findTableCode(1,7,twoDimTable);if(code[0]&&code[2])return code[1]}return info("Bad two dim code"),ccittEOF}_getWhiteCode(){if(this.eoblock){if((code=this._lookBits(12))===ccittEOF)return 1;if(0<(code=code>>5==0?whiteTable1[code]:whiteTable2[code>>3])[0])return this._eatBits(code[0]),code[1]}else{var code=this._findTableCode(1,9,whiteTable2);if(code[0])return code[1];if((code=this._findTableCode(11,12,whiteTable1))[0])return code[1]}return info("bad white code"),this._eatBits(1),1}_getBlackCode(){let code,p;if(this.eoblock){if((code=this._lookBits(13))===ccittEOF)return 1;if(0<(p=code>>7==0?blackTable1[code]:code>>9==0&&code>>7!=0?blackTable2[(code>>1)-64]:blackTable3[code>>7])[0])return this._eatBits(p[0]),p[1]}else{var result=this._findTableCode(2,6,blackTable3);if(result[0])return result[1];if((result=this._findTableCode(7,12,blackTable2,64))[0])return result[1];if((result=this._findTableCode(10,13,blackTable1))[0])return result[1]}return info("bad black code"),this._eatBits(1),1}_lookBits(n){for(var c;this.inputBits>16-n;this.inputBuf=this.inputBuf<<8|c,this.inputBits+=8}return this.inputBuf>>this.inputBits-n&65535>>16-n}_eatBits(n){(this.inputBits-=n)<0&&(this.inputBits=0)}}class CCITTFaxStream extends DecodeStream{constructor(str,maybeLength,params){super(maybeLength),this.str=str,this.dict=str.dict,params instanceof Dict||(params=Dict.empty);maybeLength={next(){return str.getByte()}};this.ccittFaxDecoder=new CCITTFaxDecoder(maybeLength,{K:params.get("K"),EndOfLine:params.get("EndOfLine"),EncodedByteAlign:params.get("EncodedByteAlign"),Columns:params.get("Columns"),Rows:params.get("Rows"),EndOfBlock:params.get("EndOfBlock"),BlackIs1:params.get("BlackIs1")})}readBlock(){for(;!this.eof;){var c=this.ccittFaxDecoder.readNextChar();if(-1===c)return void(this.eof=!0);this.ensureBuffer(this.bufferLength+1),this.buffer[this.bufferLength++]=c}}}const codeLenCodeMap=new Int32Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),lengthDecode=new Int32Array([3,4,5,6,7,8,9,10,65547,65549,65551,65553,131091,131095,131099,131103,196643,196651,196659,196667,262211,262227,262243,262259,327811,327843,327875,327907,258,258,258]),distDecode=new Int32Array([1,2,3,4,65541,65543,131081,131085,196625,196633,262177,262193,327745,327777,393345,393409,459009,459137,524801,525057,590849,591361,657409,658433,724993,727041,794625,798721,868353,876545]),fixedLitCodeTab=[new Int32Array([459008,524368,524304,524568,459024,524400,524336,590016,459016,524384,524320,589984,524288,524416,524352,590048,459012,524376,524312,589968,459028,524408,524344,590032,459020,524392,524328,59e4,524296,524424,524360,590064,459010,524372,524308,524572,459026,524404,524340,590024,459018,524388,524324,589992,524292,524420,524356,590056,459014,524380,524316,589976,459030,524412,524348,590040,459022,524396,524332,590008,524300,524428,524364,590072,459009,524370,524306,524570,459025,524402,524338,590020,459017,524386,524322,589988,524290,524418,524354,590052,459013,524378,524314,589972,459029,524410,524346,590036,459021,524394,524330,590004,524298,524426,524362,590068,459011,524374,524310,524574,459027,524406,524342,590028,459019,524390,524326,589996,524294,524422,524358,590060,459015,524382,524318,589980,459031,524414,524350,590044,459023,524398,524334,590012,524302,524430,524366,590076,459008,524369,524305,524569,459024,524401,524337,590018,459016,524385,524321,589986,524289,524417,524353,590050,459012,524377,524313,589970,459028,524409,524345,590034,459020,524393,524329,590002,524297,524425,524361,590066,459010,524373,524309,524573,459026,524405,524341,590026,459018,524389,524325,589994,524293,524421,524357,590058,459014,524381,524317,589978,459030,524413,524349,590042,459022,524397,524333,590010,524301,524429,524365,590074,459009,524371,524307,524571,459025,524403,524339,590022,459017,524387,524323,589990,524291,524419,524355,590054,459013,524379,524315,589974,459029,524411,524347,590038,459021,524395,524331,590006,524299,524427,524363,590070,459011,524375,524311,524575,459027,524407,524343,590030,459019,524391,524327,589998,524295,524423,524359,590062,459015,524383,524319,589982,459031,524415,524351,590046,459023,524399,524335,590014,524303,524431,524367,590078,459008,524368,524304,524568,459024,524400,524336,590017,459016,524384,524320,589985,524288,524416,524352,590049,459012,524376,524312,589969,459028,524408,524344,590033,459020,524392,524328,590001,524296,524424,524360,590065,459010,524372,524308,524572,459026,524404,524340,590025,459018,524388,524324,589993,524292,524420,524356,590057,459014,524380,524316,589977,459030,524412,524348,590041,459022,524396,524332,590009,524300,524428,524364,590073,459009,524370,524306,524570,459025,524402,524338,590021,459017,524386,524322,589989,524290,524418,524354,590053,459013,524378,524314,589973,459029,524410,524346,590037,459021,524394,524330,590005,524298,524426,524362,590069,459011,524374,524310,524574,459027,524406,524342,590029,459019,524390,524326,589997,524294,524422,524358,590061,459015,524382,524318,589981,459031,524414,524350,590045,459023,524398,524334,590013,524302,524430,524366,590077,459008,524369,524305,524569,459024,524401,524337,590019,459016,524385,524321,589987,524289,524417,524353,590051,459012,524377,524313,589971,459028,524409,524345,590035,459020,524393,524329,590003,524297,524425,524361,590067,459010,524373,524309,524573,459026,524405,524341,590027,459018,524389,524325,589995,524293,524421,524357,590059,459014,524381,524317,589979,459030,524413,524349,590043,459022,524397,524333,590011,524301,524429,524365,590075,459009,524371,524307,524571,459025,524403,524339,590023,459017,524387,524323,589991,524291,524419,524355,590055,459013,524379,524315,589975,459029,524411,524347,590039,459021,524395,524331,590007,524299,524427,524363,590071,459011,524375,524311,524575,459027,524407,524343,590031,459019,524391,524327,589999,524295,524423,524359,590063,459015,524383,524319,589983,459031,524415,524351,590047,459023,524399,524335,590015,524303,524431,524367,590079]),9],fixedDistCodeTab=[new Int32Array([327680,327696,327688,327704,327684,327700,327692,327708,327682,327698,327690,327706,327686,327702,327694,0,327681,327697,327689,327705,327685,327701,327693,327709,327683,327699,327691,327707,327687,327703,327695,0]),5];class FlateStream extends DecodeStream{constructor(str,maybeLength){super(maybeLength),this.str=str,this.dict=str.dict;maybeLength=str.getByte(),str=str.getByte();if(-1===maybeLength||-1===str)throw new FormatError(`Invalid header in flate stream: ${maybeLength}, `+str);if(8!=(15&maybeLength))throw new FormatError(`Unknown compression method in flate stream: ${maybeLength}, `+str);if(((maybeLength<<8)+str)%31!=0)throw new FormatError(`Bad FCHECK in flate stream: ${maybeLength}, `+str);if(32&str)throw new FormatError(`FDICT bit set in flate stream: ${maybeLength}, `+str);this.codeSize=0,this.codeBuf=0}getBits(bits){var str=this.str;let codeSize=this.codeSize,codeBuf=this.codeBuf,b;for(;codeSize>bits,this.codeSize=codeSize-=bits,b}getCode(table){var b,str=this.str,codes=table[0],maxLen=table[1];let codeSize=this.codeSize,codeBuf=this.codeBuf;for(;codeSize>16,table&=65535;if(codes<1||codeSize>codes,this.codeSize=codeSize-codes,table}generateHuffmanTable(lengths){var n=lengths.length;let maxLen=0,i;for(i=0;imaxLen&&(maxLen=lengths[i]);var size=1<>=1;for(i=code2;i>=1))if(-1===(b=str.getByte()))this.#endsStreamOnError("Bad block header in flate stream");else{var blockLen=b;if(-1===(b=str.getByte()))this.#endsStreamOnError("Bad block header in flate stream");else if(blockLen|=b<<8,-1===(b=str.getByte()))this.#endsStreamOnError("Bad block header in flate stream");else{var check=b;if(-1===(b=str.getByte()))this.#endsStreamOnError("Bad block header in flate stream");else{if((check|=b<<8)!=(65535&~blockLen)&&(0!=blockLen||0!=check))throw new FormatError("Bad uncompressed block length in flate stream");this.codeBuf=0,this.codeSize=0;var b=this.bufferLength,check=b+blockLen;buffer=this.ensureBuffer(check),this.bufferLength=check,0==blockLen?-1===str.peekByte()&&(this.eof=!0):(check=str.getBytes(blockLen),buffer.set(check,b),check.length=limit&&(buffer=this.ensureBuffer(pos+1),limit=buffer.length),buffer[pos++]=code1;else{if(256===code1)return void(this.bufferLength=pos);code1-=257;let code2=(code1=lengthDecode[code1])>>16;0>16)?this.getBits(code2):code2);pos+len>=limit&&(buffer=this.ensureBuffer(pos+len),limit=buffer.length);for(let k=0;k>9&127,this.clow=this.clow<<7&65535,this.ct-=7,this.a=32768}byteIn(){var data=this.data;let bp=this.bp;255===data[bp]?143>16,this.clow&=65535)}readBit(contexts,pos){let cx_index=contexts[pos]>>1,cx_mps=1&contexts[pos];var qeTableIcx=QeTable[cx_index],qeIcx=qeTableIcx.qe;let d,a=this.a-qeIcx;if(this.chigh>15&1,this.clow=this.clow<<1&65535,this.ct--,0==(32768&a););return this.a=a,contexts[pos]=cx_index<<1|cx_mps,d}}class Jbig2Error extends BaseException{constructor(msg){super(msg,"Jbig2Error")}}class ContextCache{getContexts(id){return id in this?this[id]:this[id]=new Int8Array(65536)}}class DecodingContext{constructor(data,start,end){this.data=data,this.start=start,this.end=end}get decoder(){return shadow(this,"decoder",new ArithmeticDecoder(this.data,this.start,this.end))}get contextCache(){return shadow(this,"contextCache",new ContextCache)}}const MAX_INT_32=2**31-1,MIN_INT_32=-(2**31);function decodeInteger(contextCache,procedure,decoder){const contexts=contextCache.getContexts(procedure);let prev=1;function readBits(length){let v=0;for(let i=0;i>>0}contextCache=readBits(1),procedure=readBits(1)?readBits(1)?readBits(1)?readBits(1)?readBits(1)?readBits(32)+4436:readBits(12)+340:readBits(8)+84:readBits(6)+20:readBits(4)+4:readBits(2);let signedValue;return 0===contextCache?signedValue=procedure:0=MIN_INT_32&&signedValue<=MAX_INT_32?signedValue:null}function decodeIAID(contextCache,decoder,codeLength){var contexts=contextCache.getContexts("IAID");let prev=1;for(let i=0;i=sbb_left&&j=sbb_top)for(contextLabel=contextLabel<<1&reuseMask,k=0;k=width?contextLabel<<=1:contextLabel=contextLabel<<1|bitmap[i0][j0];for(k=0;k=referenceHeight||j0<0||j0>=referenceWidth?contextLabel<<=1:contextLabel=contextLabel<<1|referenceBitmap[i0][j0];var pixel=decoder.readBit(contexts,contextLabel);row[j]=pixel}}return bitmap}function decodeSymbolDictionary(huffman,refinement,symbols,numberOfNewSymbols,numberOfExportedSymbols,huffmanTables,templateIndex,at,refinementTemplateIndex,refinementAt,decodingContext,huffmanInput){if(huffman&&refinement)throw new Jbig2Error("symbol refinement with Huffman is not supported");var newSymbols=[];let currentHeight=0,symbolCodeLength=log2(symbols.length+numberOfNewSymbols);var decoder=decodingContext.decoder,contextCache=decodingContext.contextCache;let tableB1,symbolWidths;for(huffman&&(tableB1=getStandardTable(1),symbolWidths=[],symbolCodeLength=Math.max(symbolCodeLength,1));newSymbols.length>1)+rdx,(applyRefinement>>1)+rdy,!1,refinementAt,decodingContext)),0);transposed?1&referenceCorner?increment=symbolHeight-1:currentS+=symbolHeight-1:1>8,y=gridOffsetY+mg*gridVectorX-ng*gridVectorY>>8,0<=x&&x+patternWidth<=regionWidth&&0<=y&&y+patternHeight<=regionHeight)for(i=0;i>5&7;var retainBits=[31&referredFlags];let position=start+6;if(7===referredFlags){referredToCount=536870911&readUint32(data,position-1),position+=3;let bytes=referredToCount+7>>3;for(retainBits[0]=data[position++];0<--bytes;)retainBits.push(data[position++])}else if(5===referredFlags||6===referredFlags)throw new Jbig2Error("invalid referred-to flags");segmentHeader.retainBits=retainBits;let referredToSegmentNumberSize=4;segmentHeader.number<=256?referredToSegmentNumberSize=1:segmentHeader.number<=65536&&(referredToSegmentNumberSize=2);var referredTo=[];let i,ii;for(i=0;i>>24&255,searchPattern[3]=start.height>>16&255,searchPattern[4]=start.height>>8&255,searchPattern[5]=255&start.height,i=position,ii=data.length;i>2&3,dictionary.huffmanDWSelector=dictionaryFlags>>4&3,dictionary.bitmapSizeSelector=dictionaryFlags>>6&1,dictionary.aggregationInstancesSelector=dictionaryFlags>>7&1,dictionary.bitmapCodingContextUsed=!!(256&dictionaryFlags),dictionary.bitmapCodingContextRetained=!!(512&dictionaryFlags),dictionary.template=dictionaryFlags>>10&3,dictionary.refinementTemplate=dictionaryFlags>>12&1,position+=2,!dictionary.huffman){for(atLength=0===dictionary.template?4:1,at=[],i=0;i>2&3,dictionaryFlags.stripSize=1<>4&3,dictionaryFlags.transposed=!!(64&dictionary),dictionaryFlags.combinationOperator=dictionary>>7&3,dictionaryFlags.defaultPixelValue=dictionary>>9&1,dictionaryFlags.dsOffset=dictionary<<17>>27,dictionaryFlags.refinementTemplate=dictionary>>15&1,dictionaryFlags.huffman&&(dictionary=readUint16(data,position),position+=2,dictionaryFlags.huffmanFS=3&dictionary,dictionaryFlags.huffmanDS=dictionary>>2&3,dictionaryFlags.huffmanDT=dictionary>>4&3,dictionaryFlags.huffmanRefinementDW=dictionary>>6&3,dictionaryFlags.huffmanRefinementDH=dictionary>>8&3,dictionaryFlags.huffmanRefinementDX=dictionary>>10&3,dictionaryFlags.huffmanRefinementDY=dictionary>>12&3,dictionaryFlags.huffmanRefinementSizeSelector=!!(16384&dictionary)),dictionaryFlags.refinement&&!dictionaryFlags.refinementTemplate){for(at=[],i=0;i<2;i++)at.push({x:readInt8(data,position),y:readInt8(data,position+1)}),position+=2;dictionaryFlags.refinementAt=at}dictionaryFlags.numberOfSymbolInstances=readUint32(data,position),position+=4,args=[dictionaryFlags,header.referredTo,data,position,end];break;case 16:dictionary={},dictionaryFlags=data[position++];dictionary.mmr=!!(1&dictionaryFlags),dictionary.template=dictionaryFlags>>1&3,dictionary.patternWidth=data[position++],dictionary.patternHeight=data[position++],dictionary.maxPatternIndex=readUint32(data,position),position+=4,args=[dictionary,header.number,data,position,end];break;case 22:case 23:dictionaryFlags={},dictionary=(dictionaryFlags.info=readRegionSegmentInformation(data,position),position+=RegionSegmentInformationFieldLength,data[position++]);dictionaryFlags.mmr=!!(1&dictionary),dictionaryFlags.template=dictionary>>1&3,dictionaryFlags.enableSkip=!!(8&dictionary),dictionaryFlags.combinationOperator=dictionary>>4&7,dictionaryFlags.defaultPixelValue=dictionary>>7&1,dictionaryFlags.gridWidth=readUint32(data,position),position+=4,dictionaryFlags.gridHeight=readUint32(data,position),position+=4,dictionaryFlags.gridOffsetX=4294967295&readUint32(data,position),position+=4,dictionaryFlags.gridOffsetY=4294967295&readUint32(data,position),position+=4,dictionaryFlags.gridVectorX=readUint16(data,position),position+=2,dictionaryFlags.gridVectorY=readUint16(data,position),position+=2,args=[dictionaryFlags,header.referredTo,data,position,end];break;case 38:case 39:dictionary={},dictionaryFlags=(dictionary.info=readRegionSegmentInformation(data,position),position+=RegionSegmentInformationFieldLength,data[position++]);if(dictionary.mmr=!!(1&dictionaryFlags),dictionary.template=dictionaryFlags>>1&3,dictionary.prediction=!!(8&dictionaryFlags),!dictionary.mmr){for(atLength=0===dictionary.template?4:1,at=[],i=0;i>2&1,dictionaryFlags.combinationOperator=dictionary>>3&3,dictionaryFlags.requiresBuffer=!!(32&dictionary),dictionaryFlags.combinationOperatorOverride=!!(64&dictionary),args=[dictionaryFlags];break;case 49:case 50:case 51:break;case 53:args=[header.number,data,position,end];break;case 62:break;default:throw new Jbig2Error(`segment type ${header.typeName}(${header.type}) is not implemented`)}segment="on"+header.typeName;segment in visitor&&visitor[segment].apply(visitor,args)}function processSegments(segments,visitor){for(let i=0,ii=segments.length;i>3,rowSize=new Uint8ClampedArray(rowSize*info.height);info.defaultPixelValue&&rowSize.fill(255),this.buffer=rowSize}drawBitmap(regionInfo,bitmap){var pageInfo=this.currentPageInfo,width=regionInfo.width,height=regionInfo.height,rowSize=pageInfo.width+7>>3,combinationOperator=(pageInfo.combinationOperatorOverride?regionInfo:pageInfo).combinationOperator,buffer=this.buffer,mask0=128>>(7®ionInfo.x);let offset0=regionInfo.y*rowSize+(regionInfo.x>>3),i,j,mask,offset;switch(combinationOperator){case 0:for(i=0;i>=1)||(mask=128,offset++);offset0+=rowSize}break;case 2:for(i=0;i>=1)||(mask=128,offset++);offset0+=rowSize}break;default:throw new Jbig2Error(`operator ${combinationOperator} is not supported`)}}onImmediateGenericRegion(region,data,start,end){var regionInfo=region.info,data=new DecodingContext(data,start,end),start=decodeBitmap(region.mmr,regionInfo.width,regionInfo.height,region.template,region.prediction,null,region.at,data);this.drawBitmap(regionInfo,start)}onImmediateLosslessGenericRegion(){this.onImmediateGenericRegion(...arguments)}onSymbolDictionary(dictionary,currentSegment,referredSegments,data,start,end){let huffmanTables,huffmanInput,symbols=(dictionary.huffman&&(huffmanTables=getSymbolDictionaryHuffmanTables(dictionary,referredSegments,this.customTables),huffmanInput=new Reader(data,start,end)),this.symbols);symbols||(this.symbols=symbols={});var inputSymbols=[];for(const referredSegment of referredSegments){var referredSymbols=symbols[referredSegment];referredSymbols&&inputSymbols.push(...referredSymbols)}referredSegments=new DecodingContext(data,start,end);symbols[currentSegment]=decodeSymbolDictionary(dictionary.huffman,dictionary.refinement,inputSymbols,dictionary.numberOfNewSymbols,dictionary.numberOfExportedSymbols,huffmanTables,dictionary.template,dictionary.at,dictionary.refinementTemplate,dictionary.refinementAt,referredSegments,huffmanInput)}onImmediateTextRegion(region,referredSegments,data,start,end){var regionInfo=region.info;let huffmanTables,huffmanInput;var symbols=this.symbols,inputSymbols=[];for(const referredSegment of referredSegments){var referredSymbols=symbols[referredSegment];referredSymbols&&inputSymbols.push(...referredSymbols)}var symbolCodeLength=log2(inputSymbols.length),referredSegments=(region.huffman&&(huffmanInput=new Reader(data,start,end),huffmanTables=getTextRegionHuffmanTables(region,referredSegments,this.customTables,inputSymbols.length,huffmanInput)),new DecodingContext(data,start,end)),data=decodeTextRegion(region.huffman,region.refinement,regionInfo.width,regionInfo.height,region.defaultPixelValue,region.numberOfSymbolInstances,region.stripSize,inputSymbols,symbolCodeLength,region.transposed,region.dsOffset,region.referenceCorner,region.combinationOperator,huffmanTables,region.refinementTemplate,region.refinementAt,referredSegments,region.logStripSize,huffmanInput);this.drawBitmap(regionInfo,data)}onImmediateLosslessTextRegion(){this.onImmediateTextRegion(...arguments)}onPatternDictionary(dictionary,currentSegment,data,start,end){let patterns=this.patterns;patterns||(this.patterns=patterns={});data=new DecodingContext(data,start,end);patterns[currentSegment]=decodePatternDictionary(dictionary.mmr,dictionary.patternWidth,dictionary.patternHeight,dictionary.maxPatternIndex,dictionary.template,data)}onImmediateHalftoneRegion(region,referredSegments,data,start,end){var referredSegments=this.patterns[referredSegments[0]],regionInfo=region.info,data=new DecodingContext(data,start,end),start=decodeHalftoneRegion(region.mmr,referredSegments,region.template,regionInfo.width,regionInfo.height,region.defaultPixelValue,region.enableSkip,region.combinationOperator,region.gridWidth,region.gridHeight,region.gridOffsetX,region.gridOffsetY,region.gridVectorX,region.gridVectorY,data);this.drawBitmap(regionInfo,start)}onImmediateLosslessHalftoneRegion(){this.onImmediateHalftoneRegion(...arguments)}onTables(currentSegment,data,start,end){let customTables=this.customTables;customTables||(this.customTables=customTables={}),customTables[currentSegment]=decodeTablesSegment(data,start,end)}}class HuffmanLine{constructor(lineData){2===lineData.length?(this.isOOB=!0,this.rangeLow=0,this.prefixLength=lineData[0],this.rangeLength=0,this.prefixCode=lineData[1],this.isLowerRange=!1):(this.isOOB=!1,this.rangeLow=lineData[0],this.prefixLength=lineData[1],this.rangeLength=lineData[2],this.prefixCode=lineData[3],this.isLowerRange="lower"===lineData[4])}}class HuffmanTreeNode{constructor(line){this.children=[],line?(this.isLeaf=!0,this.rangeLength=line.rangeLength,this.rangeLow=line.rangeLow,this.isLowerRange=line.isLowerRange,this.isOOB=line.isOOB):this.isLeaf=!1}buildTree(line,shift){var bit=line.prefixCode>>shift&1;if(shift<=0)this.children[bit]=new HuffmanTreeNode(line);else{let node=this.children[bit];node||(this.children[bit]=node=new HuffmanTreeNode(null)),node.buildTree(line,shift-1)}}decodeNode(reader){if(this.isLeaf)return this.isOOB?null:(htOffset=reader.readBits(this.rangeLength),this.rangeLow+(this.isLowerRange?-htOffset:htOffset));var htOffset=this.children[reader.readBit()];if(htOffset)return htOffset.decodeNode(reader);throw new Jbig2Error("invalid Huffman data")}}class HuffmanTable{constructor(lines,prefixCodesDone){prefixCodesDone||this.assignPrefixCodes(lines),this.rootNode=new HuffmanTreeNode(null);for(let i=0,ii=lines.length;i>1&7),rangeSizeBits=1+(flags>>4&7),lines=[];let prefixLength,rangeLength,currentRangeLow=lowestValue;for(;prefixLength=reader.readBits(prefixSizeBits),rangeLength=reader.readBits(rangeSizeBits),lines.push(new HuffmanLine([currentRangeLow,prefixLength,rangeLength,0])),(currentRangeLow+=1<=this.end)throw new Jbig2Error("end of data while reading bit");this.currentByte=this.data[this.position++],this.shift=7}var bit=this.currentByte>>this.shift&1;return this.shift--,bit}readBits(numBits){let result=0,i;for(i=numBits-1;0<=i;i--)result|=this.readBit()<=this.end?-1:this.data[this.position++]}}function getCustomHuffmanTable(index,referredTo,customTables){let currentIndex=0;for(let i=0,ii=referredTo.length;i>shift&1,shift--}if(endOfBlock&&!eof)for(let i=0;i<5&&-1!==decoder.readNextChar();i++);return bitmap}class Jbig2Image{parseChunks(chunks){return parseJbig2Chunks(chunks)}parse(data){throw new Error("Not implemented: Jbig2Image.parse")}}class Jbig2Stream extends DecodeStream{constructor(stream,maybeLength,params){super(maybeLength),this.stream=stream,this.dict=stream.dict,this.maybeLength=maybeLength,this.params=params}get bytes(){return shadow(this,"bytes",this.stream.getBytes(this.maybeLength))}ensureBuffer(requested){}readBlock(){if(!this.eof){var globalsStream,jbig2Image=new Jbig2Image,chunks=[],data=(this.params instanceof Dict&&(globalsStream=this.params.get("JBIG2Globals"))instanceof BaseStream&&(globalsStream=globalsStream.getBytes(),chunks.push({data:globalsStream,start:0,end:globalsStream.length})),chunks.push({data:this.bytes,start:0,end:this.bytes.length}),jbig2Image.parseChunks(chunks)),dataLength=data.length;for(let i=0;i>3,widthRemainder=7&width,srcLength=src.length;dest=new Uint32Array(dest.buffer);let destPos=0;for(let i=0;i>2,src32=new Uint32Array(src.buffer,srcPos,len32);if(FeatureTest.isLittleEndian){for(;i>>24|s2<<8|4278190080,dest[destPos+2]=s2>>>16|s3<<16|4278190080,dest[destPos+3]=s3>>>8|4278190080}for(let j=4*i,jj=src.length;j>>8|255,dest[destPos+2]=s2<<16|s3>>>16|255,dest[destPos+3]=s3<<8|255}for(let j=4*i,jj=src.length;j>bitsCount&1;if(255===(bitsData=data[offset++])){var nextByte=data[offset++];if(nextByte){if(220===nextByte&&parseDNLMarker){var scanLines=readUint16(data,offset+=2);if(offset+=2,0>>7}function decodeHuffman(tree){let node=tree;for(;;){switch(typeof(node=node[readBit()])){case"number":return node;case"object":continue}throw new JpegError("invalid huffman sequence")}}function receive(length){let n=0;for(;0>4;if(0==s){if(rs<15){eobrun=receive(rs)+(1<>4,0==s)successiveACState=r<15?(eobrun=receive(r)+(1<>4;if(0==s){if(rs<15)break;k+=16}else{k+=rs;rs=dctZigZag[k];component.blockData[blockOffset+rs]=receiveAndExtend(s),k++}}},0),fileMarker;for(var h,v,mcuExpected=1===componentsLength?components[0].blocksPerLine*components[0].blocksPerColumn:mcusPerLine*frame.mcusPerColumn;mcu<=mcuExpected;){var mcuToRead=resetInterval?Math.min(mcuExpected-mcu,resetInterval):mcuExpected;if(0>10,p[row]=t,p[row+1]=t,p[row+2]=t,p[row+3]=t,p[row+4]=t,p[row+5]=t,p[row+6]=t,p[row+7]=t):(p1*=qt[row+1],p2*=qt[row+2],p3*=qt[row+3],p4*=qt[row+4],p5*=qt[row+5],p6*=qt[row+6],p7*=qt[row+7],v0=dctSqrt2*p0+128>>8,v1=dctSqrt2*p4+128>>8,v2=p2,v3=p6,v4=dctSqrt1d2*(p1-p7)+128>>8,v7=dctSqrt1d2*(p1+p7)+128>>8,v5=p3<<4,v6=p5<<4,v0=v0+v1+1>>1,v1=v0-v1,t=v2*dctSin6+v3*dctCos6+128>>8,v2=v2*dctCos6-v3*dctSin6+128>>8,v3=t,v4=v4+v6+1>>1,v6=v4-v6,v7=v7+v5+1>>1,v5=v7-v5,v0=v0+v3+1>>1,v3=v0-v3,v1=v1+v2+1>>1,v2=v1-v2,t=v4*dctSin3+v7*dctCos3+2048>>12,v4=v4*dctCos3-v7*dctSin3+2048>>12,v7=t,t=v5*dctSin1+v6*dctCos1+2048>>12,v5=v5*dctCos1-v6*dctSin1+2048>>12,v6=t,p[row]=v0+v7,p[row+7]=v0-v7,p[row+1]=v1+v6,p[row+6]=v1-v6,p[row+2]=v2+v5,p[row+5]=v2-v5,p[row+3]=v3+v4,p[row+4]=v3-v4);for(let col=0;col<8;++col)p0=p[col],p1=p[col+8],p2=p[col+16],p3=p[col+24],p4=p[col+32],p5=p[col+40],p6=p[col+48],p7=p[col+56],0==(p1|p2|p3|p4|p5|p6|p7)?(t=(t=dctSqrt2*p0+8192>>14)<-2040?0:2024<=t?255:t+2056>>4,blockData[blockBufferOffset+col]=t,blockData[blockBufferOffset+col+8]=t,blockData[blockBufferOffset+col+16]=t,blockData[blockBufferOffset+col+24]=t,blockData[blockBufferOffset+col+32]=t,blockData[blockBufferOffset+col+40]=t,blockData[blockBufferOffset+col+48]=t,blockData[blockBufferOffset+col+56]=t):(v0=dctSqrt2*p0+2048>>12,v1=dctSqrt2*p4+2048>>12,v2=p2,v3=p6,v4=dctSqrt1d2*(p1-p7)+2048>>12,v7=dctSqrt1d2*(p1+p7)+2048>>12,v5=p3,v6=p5,v0=4112+(v0+v1+1>>1),v1=v0-v1,t=v2*dctSin6+v3*dctCos6+2048>>12,v2=v2*dctCos6-v3*dctSin6+2048>>12,v3=t,v4=v4+v6+1>>1,v6=v4-v6,v7=v7+v5+1>>1,v5=v7-v5,v0=v0+v3+1>>1,v3=v0-v3,v1=v1+v2+1>>1,v2=v1-v2,t=v4*dctSin3+v7*dctCos3+2048>>12,v4=v4*dctCos3-v7*dctSin3+2048>>12,v7=t,t=v5*dctSin1+v6*dctCos1+2048>>12,v5=v5*dctCos1-v6*dctSin1+2048>>12,v6=t,p0=v0+v7,p7=v0-v7,p1=v1+v6,p6=v1-v6,p2=v2+v5,p5=v2-v5,p3=v3+v4,p4=v3-v4,p0<16?p0=0:4080<=p0?p0=255:p0>>=4,p1<16?p1=0:4080<=p1?p1=255:p1>>=4,p2<16?p2=0:4080<=p2?p2=255:p2>>=4,p3<16?p3=0:4080<=p3?p3=255:p3>>=4,p4<16?p4=0:4080<=p4?p4=255:p4>>=4,p5<16?p5=0:4080<=p5?p5=255:p5>>=4,p6<16?p6=0:4080<=p6?p6=255:p6>>=4,p7<16?p7=0:4080<=p7?p7=255:p7>>=4,blockData[blockBufferOffset+col]=p0,blockData[blockBufferOffset+col+8]=p1,blockData[blockBufferOffset+col+16]=p2,blockData[blockBufferOffset+col+24]=p3,blockData[blockBufferOffset+col+32]=p4,blockData[blockBufferOffset+col+40]=p5,blockData[blockBufferOffset+col+48]=p6,blockData[blockBufferOffset+col+56]=p7)}function buildComponentData(frame,component){var blocksPerLine=component.blocksPerLine,blocksPerColumn=component.blocksPerColumn,computationBuffer=new Int16Array(64);for(let blockRow=0;blockRow=maxPos)return null;newMarker=readUint16(data,newPos)}return{invalid:startPos.toString(16),marker:newMarker,offset:newPos}}class JpegImage{constructor({decodeTransform=null,colorTransform=-1}={}){this._decodeTransform=decodeTransform,this._colorTransform=colorTransform}parse(data,{dnlScanLines=null}={}){let offset=0,jfif=null,adobe=null,frame,resetInterval,numSOSMarkers=0;var quantizationTables=[],huffmanTablesAC=[],huffmanTablesDC=[];let fileMarker=readUint16(data,offset);if(offset+=2,65496!==fileMarker)throw new JpegError("SOI not found");fileMarker=readUint16(data,offset),offset+=2;markerLoop:for(;65497!==fileMarker;){let i,j,l;switch(fileMarker){case 65504:case 65505:case 65506:case 65507:case 65508:case 65509:case 65510:case 65511:case 65512:case 65513:case 65514:case 65515:case 65516:case 65517:case 65518:case 65519:case 65534:var appData=function(){var length=readUint16(data,offset);let endOffset=(offset+=2)+length-2;return(length=findNextFileMarker(data,endOffset,offset))?.invalid&&(warn("readDataBlock - incorrect length, current marker is: "+length.invalid),endOffset=length.offset),length=data.subarray(offset,endOffset),offset+=length.length,length}();65504===fileMarker&&74===appData[0]&&70===appData[1]&&73===appData[2]&&70===appData[3]&&0===appData[4]&&(jfif={version:{major:appData[5],minor:appData[6]},densityUnits:appData[7],xDensity:appData[8]<<8|appData[9],yDensity:appData[10]<<8|appData[11],thumbWidth:appData[12],thumbHeight:appData[13],thumbData:appData.subarray(14,14+3*appData[12]*appData[13])}),65518===fileMarker&&65===appData[0]&&100===appData[1]&&111===appData[2]&&98===appData[3]&&101===appData[4]&&(adobe={version:appData[5]<<8|appData[6],flags0:appData[7]<<8|appData[8],flags1:appData[9]<<8|appData[10],transformCode:appData[11]});break;case 65499:var quantizationTablesEnd=readUint16(data,offset)+(offset+=2)-2;let z;for(;offset>4==0)for(j=0;j<64;j++)tableData[z=dctZigZag[j]]=data[offset++];else{if(quantizationTableSpec>>4!=1)throw new JpegError("DQT - invalid table spec");for(j=0;j<64;j++)tableData[z=dctZigZag[j]]=readUint16(data,offset),offset+=2}quantizationTables[15&quantizationTableSpec]=tableData}break;case 65472:case 65473:case 65474:if(frame)throw new JpegError("Only single frame JPEGs supported");offset+=2,(frame={}).extended=65473===fileMarker,frame.progressive=65474===fileMarker,frame.precision=data[offset++];var appData=readUint16(data,offset),componentsCount=(offset+=2,frame.scanLines=dnlScanLines||appData,frame.samplesPerLine=readUint16(data,offset),offset+=2,frame.components=[],frame.componentIds={},data[offset++]);let maxH=0,maxV=0;for(i=0;i>4,v=15&data[offset+1],qId=(maxH>4==0?huffmanTablesDC:huffmanTablesAC)[15&huffmanTableSpec]=buildHuffmanTable(codeLengths,huffmanValues)}break;case 65501:offset+=2,resetInterval=readUint16(data,offset),offset+=2;break;case 65498:var parseDNLMarker=1==++numSOSMarkers&&!dnlScanLines,selectorsCount=(offset+=2,data[offset++]),components=[];for(i=0;i>4],componentIndex.huffmanTableAC=huffmanTablesAC[15&index],components.push(componentIndex)}var spectralStart=data[offset++],spectralEnd=data[offset++],successiveApproximation=data[offset++];try{var processed=decodeScan(data,offset,frame,components,resetInterval,spectralStart,spectralEnd,successiveApproximation>>4,15&successiveApproximation,parseDNLMarker);offset+=processed}catch(ex){if(ex instanceof DNLMarkerError)return warn(ex.message+" -- attempting to re-parse the JPEG image."),this.parse(data,{dnlScanLines:ex.scanLines});if(ex instanceof EOIMarkerError){warn(ex.message+" -- ignoring the rest of the image data.");break markerLoop}throw ex}break;case 65500:offset+=4;break;case 65535:255!==data[offset]&&offset--;break;default:spectralStart=findNextFileMarker(data,offset-2,offset-3);if(spectralStart?.invalid){warn("JpegImage.parse - unexpected data, current marker is: "+spectralStart.invalid),offset=spectralStart.offset;break}if(!spectralStart||offset>=data.length-1){warn("JpegImage.parse - reached the end of the image data without finding an EOI marker (0xFFD9).");break markerLoop}throw new JpegError("JpegImage.parse - unknown marker: "+fileMarker.toString(16))}fileMarker=readUint16(data,offset),offset+=2}if(!frame)throw new JpegError("JpegImage.parse - no frame data found.");this.width=frame.samplesPerLine,this.height=frame.scanLines,this.jfif=jfif,this.adobe=adobe,this.components=[];for(const component of frame.components){var quantizationTable=quantizationTables[component.quantizationId];quantizationTable&&(component.quantizationTable=quantizationTable),this.components.push({index:component.index,output:buildComponentData(frame,component),scaleX:component.h/frame.maxH,scaleY:component.v/frame.maxV,blocksPerLine:component.blocksPerLine,blocksPerColumn:component.blocksPerColumn})}this.numComponents=this.components.length}_getLinearizedBlockData(width,height,isSourcePDF=!1){var component,componentScaleX,componentScaleY,blocksPerScanline,index,output,scaleX=this.width/width,scaleY=this.height/height;let x,y,i,j,k,offset=0;var numComponents=this.components.length,dataLength=width*height*numComponents,data=new Uint8ClampedArray(dataLength),xScaleBlockOffset=new Uint32Array(width);let lastComponentScaleX;for(i=0;i>8)+transform[k+1];return data}get _isColorConversionNeeded(){return this.adobe?!!this.adobe.transformCode:3===this.numComponents?0!==this._colorTransform&&(82!==this.components[0].index||71!==this.components[1].index||66!==this.components[2].index):1===this._colorTransform}_convertYccToRgb(data){var Y,Cb,Cr;for(let i=0,length=data.length;i{var _scriptDir="file:///home/timvandermeij/Documenten/Ontwikkeling/pdf.js/Code/external/openjpeg/openjpeg.js";return function(moduleArg={}){var readyPromiseResolve,readyPromiseReject,readBinary,wasmBinary,wasmMemory,Module=moduleArg,moduleOverrides=(new Promise((resolve,reject)=>{readyPromiseResolve=resolve,readyPromiseReject=reject}),Module.decode=function(bytes,ignoreColorSpace){var size=bytes.length,ptr=Module._malloc(size),bytes=(Module.HEAPU8.set(bytes,ptr),Module._jp2_decode(ptr,size,ignoreColorSpace?1:0));return Module._free(ptr),bytes?(size=Module["errorMessages"],size?(delete Module.errorMessages,size):"Unknown error"):(ignoreColorSpace=Module["imageData"],Module.imageData=null,ignoreColorSpace)},Object.assign({},Module)),thisProgram="./this.program",scriptDirectory="",out=("undefined"!=typeof document&&document.currentScript&&(scriptDirectory=document.currentScript.src),scriptDirectory=(scriptDirectory=_scriptDir).startsWith("blob:")?"":scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1),Module.print||console.log.bind(console)),err=Module.printErr||console.error.bind(console);function tryParseAsDataURI(filename){if((filename=>filename.startsWith(dataURIPrefix))(filename)){for(var filename=filename.slice(dataURIPrefix.length),decoded=atob(filename),bytes=new Uint8Array(decoded.length),i=0;i{for(;0thisProgram||"./this.program",getEnvStrings=()=>{if(!getEnvStrings.strings){var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:getExecutableName()};for(x in ENV)void 0===ENV[x]?delete env[x]:env[x]=ENV[x];var x,strings=[];for(x in env)strings.push(x+"="+env[x]);getEnvStrings.strings=strings}return getEnvStrings.strings},printCharBuffers=[null,[],[]],UTF8Decoder="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0,UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{for(var endIdx=idx+maxBytesToRead,endPtr=idx;heapOrArray[endPtr]&&!(endIdx<=endPtr);)++endPtr;if(16>10,56320|1023&u1)))):str+=String.fromCharCode(u0)}return str},UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var calledRun,wasmImports={f:(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num),b:requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;if(!(2147483648{size=(size-wasmMemory.buffer.byteLength+65535)/65536;try{return wasmMemory.grow(size),updateMemoryViews(),1}catch(e){}})(Math.min(2147483648,(overGrownHeapSize=Math.max(requestedSize,overGrownHeapSize))+((multiple=65536)-overGrownHeapSize%multiple)%multiple)))return!0}return!1},c:(__environ,environ_buf)=>{var bufSize=0;return getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;((str,buffer)=>{for(var i=0;i>2]=ptr),bufSize+=string.length+1}),0},d:(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings(),bufSize=(HEAPU32[penviron_count>>2]=strings.length,0);return strings.forEach(string=>bufSize+=string.length+1),HEAPU32[penviron_buf_size>>2]=bufSize,0},e:(fd,iov,iovcnt,pnum)=>{for(var stream,curr,buffer,num=0,i=0;i>2],len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num,0},g:function(message_ptr){message_ptr=UTF8ToString(message_ptr),(Module.warn||console.warn)("OpenJPEG: "+message_ptr)},h:function(array_ptr,array_size){Module.imageData=new Uint8ClampedArray(Module.HEAPU8.subarray(array_ptr,array_ptr+array_size))},a:function(message_ptr){message_ptr=UTF8ToString(message_ptr),Module.errorMessages?Module.errorMessages+="\n"+message_ptr:Module.errorMessages=message_ptr}},wasmExports=function(){var info={a:wasmImports};function receiveInstance(instance,module){return wasmExports=instance.exports,wasmMemory=wasmExports.i,updateMemoryViews(),instance=wasmExports.j,__ATINIT__.unshift(instance),runDependencies--,Module.monitorRunDependencies?.(runDependencies),0==runDependencies&&(null!==runDependencyWatcher&&(clearInterval(runDependencyWatcher),runDependencyWatcher=null),dependenciesFulfilled)&&(instance=dependenciesFulfilled,dependenciesFulfilled=null,instance()),wasmExports}if(runDependencies++,Module.monitorRunDependencies?.(runDependencies),Module.instantiateWasm)try{return Module.instantiateWasm(info,receiveInstance)}catch(e){err("Module.instantiateWasm callback failed with error: "+e),readyPromiseReject(e)}return receiveInstance(instantiateSync(wasmBinaryFile,info)[0])}();wasmExports.j,Module._malloc=wasmExports.k,Module._free=wasmExports.l,Module._jp2_decode=wasmExports.n,wasmExports._emscripten_stack_restore,wasmExports._emscripten_stack_alloc,wasmExports.emscripten_stack_get_current;function run(){function doRun(){calledRun||(calledRun=!0,Module.calledRun=!0,ABORT)||(callRuntimeCallbacks(__ATINIT__),readyPromiseResolve(Module),Module.onRuntimeInitialized&&Module.onRuntimeInitialized(),postRun())}0>>0,Ysiz=stream.getInt32()>>>0,XOsiz=stream.getInt32()>>>0,YOsiz=stream.getInt32()>>>0,stream.skip(16),{width:Xsiz-XOsiz,height:Ysiz-YOsiz,bitsPerComponent:8,componentsCount:stream.getUint16()}}throw new JpxError("No size marker found in JPX stream")}}class JpxStream extends DecodeStream{constructor(stream,maybeLength,params){super(maybeLength),this.stream=stream,this.dict=stream.dict,this.maybeLength=maybeLength,this.params=params}get bytes(){return shadow(this,"bytes",this.stream.getBytes(this.maybeLength))}ensureBuffer(requested){}readBlock(ignoreColorSpace){this.eof||(this.buffer=JpxImage.decode(this.bytes,ignoreColorSpace),this.bufferLength=this.buffer.length,this.eof=!0)}}class LZWStream extends DecodeStream{constructor(str,maybeLength,earlyChange){super(maybeLength),this.str=str,this.dict=str.dict,this.cachedData=0,this.bitsCached=0;var lzwState={earlyChange:earlyChange,codeLength:9,nextCode:258,dictionaryValues:new Uint8Array(4096),dictionaryLengths:new Uint16Array(4096),dictionaryPrevCodes:new Uint16Array(4096),currentSequence:new Uint8Array(4096),currentSequenceLength:0};for(let i=0;i<256;++i)lzwState.dictionaryValues[i]=i,lzwState.dictionaryLengths[i]=1;this.lzwState=lzwState}readBits(n){let bitsCached=this.bitsCached,cachedData=this.cachedData;for(;bitsCached>>bitsCached&(1<>3,this.rowBytes=params*maybeLength*str+7>>3,this}readBlockTiff(){var rowBytes=this.rowBytes,bufferLength=this.bufferLength,buffer=this.ensureBuffer(bufferLength+rowBytes),bits=this.bits,colors=this.colors,rawBytes=this.str.getBytes(rowBytes);if(this.eof=!rawBytes.length,!this.eof){let inbuf=0,outbuf=0,inbits=0,outbits=0,pos=bufferLength,i;if(1===bits&&1===colors)for(i=0;i>1)^c>>2)^c>>4;inbuf=(1&c)<<7,buffer[pos++]=c}else if(8===bits){for(i=0;i>8&255,buffer[pos++]=255&sum}}else{var compArray=new Uint8Array(colors+1),bitMask=(1<>inbits-bits)&bitMask,inbits-=bits,outbuf=outbuf<>outbits-8&255,outbits-=8);0>1)+rawBytes[i];for(;i>1)+rawBytes[i]&255,j++;break;case 4:for(i=0;i>")&&this.buf1!==EOF;)if(this.buf1 instanceof Name){var key=this.buf1.name;if(this.shift(),this.buf1===EOF)break;dict.set(key,this.getObj(cipherTransform))}else info("Malformed dictionary: key must be a name object"),this.shift();if(this.buf1!==EOF)return isCmd(this.buf2,"stream")?this.allowStreams?this.makeStream(dict,cipherTransform):dict:(this.shift(),dict);if(this.recoveryMode)return dict;throw new ParserEOFException("End of file inside dictionary.");default:return buf1}return Number.isInteger(buf1)?Number.isInteger(this.buf1)&&isCmd(this.buf2,"R")?(ref=Ref.get(buf1,this.buf1),this.shift(),this.shift(),ref):buf1:"string"==typeof buf1&&cipherTransform?cipherTransform.decryptString(buf1):buf1}findDefaultInlineStreamEnd(stream){var knownCommands=this.lexer["knownCommands"],startPos=stream.pos;let state=0,ch,maybeEIPos;for(;-1!==(ch=stream.getByte());)if(0===state)state=69===ch?1:0;else if(1===state)state=73===ch?2:0;else if(32===ch||10===ch||13===ch){maybeEIPos=stream.pos;var followingBytes=stream.peekBytes(15),ii=followingBytes.length;if(0===ii)break;for(let i=0;i{};let numArgs=0;for(;;){var nextObj=tmpLexer.getObj();if(nextObj===EOF){state=0;break}if(nextObj instanceof Cmd){nextObj=knownCommands[nextObj.cmd];if(!nextObj){state=0;break}if(nextObj.variableArgs?numArgs<=nextObj.numArgs:numArgs===nextObj.numArgs)break;numArgs=0}else numArgs++}if(2===state)break}else warn("findDefaultInlineStreamEnd - `lexer.knownCommands` is undefined.")}else state=0;-1===ch&&(warn("findDefaultInlineStreamEnd: Reached the end of the stream without finding a valid EI marker"),maybeEIPos)&&(warn('... trying to recover by using the last "EI" occurrence.'),stream.skip(-(stream.pos-maybeEIPos)));let endOffset=4;return stream.skip(-endOffset),ch=stream.peekByte(),stream.skip(endOffset),isWhiteSpace(ch)||endOffset--,stream.pos-endOffset-startPos}findDCTDecodeInlineStreamEnd(stream){var startPos=stream.pos;let foundEOI=!1,b,markerLength;for(;-1!==(b=stream.getByte());)if(255===b){switch(stream.getByte()){case 0:break;case 255:stream.skip(-1);break;case 217:foundEOI=!0;break;case 192:case 193:case 194:case 195:case 197:case 198:case 199:case 201:case 202:case 203:case 205:case 206:case 207:case 196:case 204:case 218:case 219:case 220:case 221:case 222:case 223:case 224:case 225:case 226:case 227:case 228:case 229:case 230:case 231:case 232:case 233:case 234:case 235:case 236:case 237:case 238:case 239:case 254:2<(markerLength=stream.getUint16())?stream.skip(markerLength-2):stream.skip(-2)}if(foundEOI)break}startPos=stream.pos-startPos;return-1===b?(warn("Inline DCTDecode image stream: EOI marker not found, searching for /EI/ instead."),stream.skip(-startPos),this.findDefaultInlineStreamEnd(stream)):(this.inlineStreamSkipEI(stream),startPos)}findASCII85DecodeInlineStreamEnd(stream){var startPos=stream.pos;let ch;for(;-1!==(ch=stream.getByte());)if(126===ch){var tildePos=stream.pos;for(ch=stream.peekByte();isWhiteSpace(ch);)stream.skip(),ch=stream.peekByte();if(62===ch){stream.skip();break}if(stream.pos>tildePos){tildePos=stream.peekBytes(2);if(69===tildePos[0]&&73===tildePos[1])break}}startPos=stream.pos-startPos;return-1===ch?(warn("Inline ASCII85Decode image stream: EOD marker not found, searching for /EI/ instead."),stream.skip(-startPos),this.findDefaultInlineStreamEnd(stream)):(this.inlineStreamSkipEI(stream),startPos)}findASCIIHexDecodeInlineStreamEnd(stream){var startPos=stream.pos;let ch;for(;-1!==(ch=stream.getByte())&&62!==ch;);startPos=stream.pos-startPos;return-1===ch?(warn("Inline ASCIIHexDecode image stream: EOD marker not found, searching for /EI/ instead."),stream.skip(-startPos),this.findDefaultInlineStreamEnd(stream)):(this.inlineStreamSkipEI(stream),startPos)}inlineStreamSkipEI(stream){let state=0,ch;for(;-1!==(ch=stream.getByte());)if(0===state)state=69===ch?1:0;else if(1===state)state=73===ch?2:0;else if(2===state)break}makeInlineImage(cipherTransform){var lexer=this.lexer,stream=lexer.stream,dictMap=Object.create(null);let dictLength;for(;!isCmd(this.buf1,"ID")&&this.buf1!==EOF;){if(!(this.buf1 instanceof Name))throw new FormatError("Dictionary key must be a name object");var key=this.buf1.name;if(this.shift(),this.buf1===EOF)break;dictMap[key]=this.getObj(cipherTransform)}-1!==lexer.beginInlineImagePos&&(dictLength=stream.pos-lexer.beginInlineImagePos);var filter=this.xref.fetchIfRef(dictMap.F||dictMap.Filter);let filterName;filter instanceof Name?filterName=filter.name:Array.isArray(filter)&&(filter=this.xref.fetchIfRef(filter[0]))instanceof Name&&(filterName=filter.name);filter=stream.pos;let length;switch(filterName){case"DCT":case"DCTDecode":length=this.findDCTDecodeInlineStreamEnd(stream);break;case"A85":case"ASCII85Decode":length=this.findASCII85DecodeInlineStreamEnd(stream);break;case"AHx":case"ASCIIHexDecode":length=this.findASCIIHexDecodeInlineStreamEnd(stream);break;default:length=this.findDefaultInlineStreamEnd(stream)}let cacheKey;if(length=signatureLength)return stream.pos+=pos,stream.pos-startPos;pos++}stream.pos+=scanLength}return-1}makeStream(dict,cipherTransform){var lexer=this.lexer;let stream=lexer.stream;lexer.skipToNextLine();var startPos=stream.pos-1;let length=dict.get("Length");if(Number.isInteger(length)||(info(`Bad length "${length&&length.toString()}" in stream.`),length=0),stream.pos=startPos+length,lexer.nextChar(),!this.tryShift()||!isCmd(this.buf2,"endstream")){var ENDSTREAM_SIGNATURE=new Uint8Array([101,110,100,115,116,114,101,97,109]);let actualLength=this._findStreamLength(startPos,ENDSTREAM_SIGNATURE);if(actualLength<0){for(let i=1;i<=1;i++){var end=ENDSTREAM_SIGNATURE.length-i,TRUNCATED_SIGNATURE=ENDSTREAM_SIGNATURE.slice(0,end),maybeLength=this._findStreamLength(startPos,TRUNCATED_SIGNATURE);if(0<=maybeLength){if(!isWhiteSpace(stream.peekBytes(1+end)[end]))break;info(`Found "${bytesToString(TRUNCATED_SIGNATURE)}" when `+"searching for endstream command."),actualLength=maybeLength;break}}if(actualLength<0)throw new FormatError("Missing endstream command.")}length=actualLength,lexer.nextChar(),this.shift()}return this.shift(),this.shift(),stream=stream.makeSubStream(startPos,length,dict),cipherTransform&&(stream=cipherTransform.createStream(stream,length)),(stream=this.filter(stream,dict,length)).dict=dict,stream}filter(stream,dict,length){let filter=dict.get("F","Filter"),params=dict.get("DP","DecodeParms");if(filter instanceof Name)return Array.isArray(params)&&warn("/DecodeParms should not be an Array, when /Filter is a Name."),this.makeFilter(stream,filter.name,length,params);let maybeLength=length;if(Array.isArray(filter)){var filterArray=filter,paramsArray=params;for(let i=0,ii=filterArray.length;i>")):Cmd.get(">");case 123:return this.nextChar(),Cmd.get("{");case 125:return this.nextChar(),Cmd.get("}");case 41:throw this.nextChar(),new FormatError("Illegal character: "+ch)}let str=String.fromCharCode(ch);if(ch<32||127MAX_MAP_RANGE)throw new Error("mapCidRange - ignoring data above MAX_MAP_RANGE.");for(;low<=high;)this._map[low++]=dstLow++}mapBfRange(low,high,dstLow){if(high-low>MAX_MAP_RANGE)throw new Error("mapBfRange - ignoring data above MAX_MAP_RANGE.");for(var lastByte=dstLow.length-1;low<=high;){var nextCharCode=(this._map[low++]=dstLow).charCodeAt(lastByte)+1;255MAX_MAP_RANGE)throw new Error("mapBfRangeToArray - ignoring data above MAX_MAP_RANGE.");var ii=array.length;let i=0;for(;low<=high&&i>>0;var codespaceRange=codespaceRanges[n];for(let k=0,kk=codespaceRange.length;k=low&&c<=high)return out.charcode=c,void(out.length=n+1)}}out.charcode=0,out.length=1}getCharCodeLength(charCode){var codespaceRanges=this.codespaceRanges;for(let n=0,nn=codespaceRanges.length;n>>0}function expectString(obj){if("string"!=typeof obj)throw new FormatError("Malformed CMap: expected string.")}function expectInt(obj){if(!Number.isInteger(obj))throw new FormatError("Malformed CMap: expected int.")}function parseBfChar(cMap,lexer){for(;;){var obj=lexer.getObj();if(obj===EOF)break;if(isCmd(obj,"endbfchar"))return;expectString(obj);var src=strToInt(obj);expectString(obj=lexer.getObj()),cMap.mapOne(src,obj)}}function parseBfRange(cMap,lexer){for(;;){let obj=lexer.getObj();if(obj===EOF)break;if(isCmd(obj,"endbfrange"))return;expectString(obj);var low=strToInt(obj),high=(expectString(obj=lexer.getObj()),strToInt(obj));if(obj=lexer.getObj(),Number.isInteger(obj)||"string"==typeof obj){var dstLow=Number.isInteger(obj)?String.fromCharCode(obj):obj;cMap.mapBfRange(low,high,dstLow)}else{if(!isCmd(obj,"["))break;obj=lexer.getObj();for(var array=[];!isCmd(obj,"]")&&obj!==EOF;)array.push(obj),obj=lexer.getObj();cMap.mapBfRangeToArray(low,high,array)}}throw new FormatError("Invalid bf range.")}function parseCidChar(cMap,lexer){for(;;){var obj=lexer.getObj();if(obj===EOF)break;if(isCmd(obj,"endcidchar"))return;expectString(obj);var src=strToInt(obj);expectInt(obj=lexer.getObj()),cMap.mapOne(src,obj)}}function parseCidRange(cMap,lexer){for(;;){var obj=lexer.getObj();if(obj===EOF)break;if(isCmd(obj,"endcidrange"))return;expectString(obj);var low=strToInt(obj),high=(expectString(obj=lexer.getObj()),strToInt(obj));expectInt(obj=lexer.getObj());cMap.mapCidRange(low,high,obj)}}function parseCodespaceRange(cMap,lexer){for(;;){var obj=lexer.getObj();if(obj===EOF)break;if(isCmd(obj,"endcodespacerange"))return;if("string"!=typeof obj)break;var low=strToInt(obj);if("string"!=typeof(obj=lexer.getObj()))break;var high=strToInt(obj);cMap.addCodespaceRange(obj.length,low,high)}throw new FormatError("Invalid codespace range.")}function parseWMode(cMap,lexer){lexer=lexer.getObj();Number.isInteger(lexer)&&(cMap.vertical=!!lexer)}function parseCMapName(cMap,lexer){lexer=lexer.getObj();lexer instanceof Name&&(cMap.name=lexer.name)}async function parseCMap(cMap,lexer,fetchBuiltInCMap,useCMap){let previous,embeddedUseCMap;objLoop:for(;;)try{var obj=lexer.getObj();if(obj===EOF)break;if(obj instanceof Name)"WMode"===obj.name?parseWMode(cMap,lexer):"CMapName"===obj.name&&parseCMapName(cMap,lexer),previous=obj;else if(obj instanceof Cmd)switch(obj.cmd){case"endcmap":break objLoop;case"usecmap":previous instanceof Name&&(embeddedUseCMap=previous.name);break;case"begincodespacerange":parseCodespaceRange(cMap,lexer);break;case"beginbfchar":parseBfChar(cMap,lexer);break;case"begincidchar":parseCidChar(cMap,lexer);break;case"beginbfrange":parseBfRange(cMap,lexer);break;case"begincidrange":parseCidRange(cMap,lexer)}}catch(ex){if(ex instanceof MissingDataException)throw ex;warn("Invalid cMap data: "+ex);continue}return(useCMap=!useCMap&&embeddedUseCMap?embeddedUseCMap:useCMap)?extendCMap(cMap,fetchBuiltInCMap,useCMap):cMap}async function extendCMap(cMap,fetchBuiltInCMap,useCMap){if(cMap.useCMap=await createBuiltInCMap(useCMap,fetchBuiltInCMap),0===cMap.numCodespaceRanges){var useCodespaceRanges=cMap.useCMap.codespaceRanges;for(let i=0;iextendCMap(cMap,fetchBuiltInCMap,useCMap));if(compressionType===CMapCompressionType.NONE)return name=new Lexer(new Stream(name)),parseCMap(cMap,name,fetchBuiltInCMap,null);throw new Error('Invalid CMap "compressionType" value: '+compressionType)}class CMapFactory{static async create({encoding,fetchBuiltInCMap,useCMap}){if(encoding instanceof Name)return createBuiltInCMap(encoding.name,fetchBuiltInCMap);if(encoding instanceof BaseStream)return(encoding=await parseCMap(new CMap,new Lexer(encoding),fetchBuiltInCMap,useCMap)).isIdentityCMap?createBuiltInCMap(encoding.name,fetchBuiltInCMap):encoding;throw new Error("Encoding required.")}}const ISOAdobeCharset=[".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","quoteleft","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","exclamdown","cent","sterling","fraction","yen","florin","section","currency","quotesingle","quotedblleft","guillemotleft","guilsinglleft","guilsinglright","fi","fl","endash","dagger","daggerdbl","periodcentered","paragraph","bullet","quotesinglbase","quotedblbase","quotedblright","guillemotright","ellipsis","perthousand","questiondown","grave","acute","circumflex","tilde","macron","breve","dotaccent","dieresis","ring","cedilla","hungarumlaut","ogonek","caron","emdash","AE","ordfeminine","Lslash","Oslash","OE","ordmasculine","ae","dotlessi","lslash","oslash","oe","germandbls","onesuperior","logicalnot","mu","trademark","Eth","onehalf","plusminus","Thorn","onequarter","divide","brokenbar","degree","thorn","threequarters","twosuperior","registered","minus","eth","multiply","threesuperior","copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring","Atilde","Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave","Iacute","Icircumflex","Idieresis","Igrave","Ntilde","Oacute","Ocircumflex","Odieresis","Ograve","Otilde","Scaron","Uacute","Ucircumflex","Udieresis","Ugrave","Yacute","Ydieresis","Zcaron","aacute","acircumflex","adieresis","agrave","aring","atilde","ccedilla","eacute","ecircumflex","edieresis","egrave","iacute","icircumflex","idieresis","igrave","ntilde","oacute","ocircumflex","odieresis","ograve","otilde","scaron","uacute","ucircumflex","udieresis","ugrave","yacute","ydieresis","zcaron"],ExpertCharset=[".notdef","space","exclamsmall","Hungarumlautsmall","dollaroldstyle","dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","comma","hyphen","period","fraction","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","colon","semicolon","commasuperior","threequartersemdash","periodsuperior","questionsmall","asuperior","bsuperior","centsuperior","dsuperior","esuperior","isuperior","lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior","tsuperior","ff","fi","fl","ffi","ffl","parenleftinferior","parenrightinferior","Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall","Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","exclamdownsmall","centoldstyle","Lslashsmall","Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall","Dotaccentsmall","Macronsmall","figuredash","hypheninferior","Ogoneksmall","Ringsmall","Cedillasmall","onequarter","onehalf","threequarters","questiondownsmall","oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds","zerosuperior","onesuperior","twosuperior","threesuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","eightsuperior","ninesuperior","zeroinferior","oneinferior","twoinferior","threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior","eightinferior","nineinferior","centinferior","dollarinferior","periodinferior","commainferior","Agravesmall","Aacutesmall","Acircumflexsmall","Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall","Egravesmall","Eacutesmall","Ecircumflexsmall","Edieresissmall","Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall","Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall","Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall","Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall","Thornsmall","Ydieresissmall"],ExpertSubsetCharset=[".notdef","space","dollaroldstyle","dollarsuperior","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","comma","hyphen","period","fraction","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","colon","semicolon","commasuperior","threequartersemdash","periodsuperior","asuperior","bsuperior","centsuperior","dsuperior","esuperior","isuperior","lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior","tsuperior","ff","fi","fl","ffi","ffl","parenleftinferior","parenrightinferior","hyphensuperior","colonmonetary","onefitted","rupiah","centoldstyle","figuredash","hypheninferior","onequarter","onehalf","threequarters","oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds","zerosuperior","onesuperior","twosuperior","threesuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","eightsuperior","ninesuperior","zeroinferior","oneinferior","twoinferior","threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior","eightinferior","nineinferior","centinferior","dollarinferior","periodinferior","commainferior"],ExpertEncoding=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclamsmall","Hungarumlautsmall","","dollaroldstyle","dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","comma","hyphen","period","fraction","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","colon","semicolon","commasuperior","threequartersemdash","periodsuperior","questionsmall","","asuperior","bsuperior","centsuperior","dsuperior","esuperior","","","","isuperior","","","lsuperior","msuperior","nsuperior","osuperior","","","rsuperior","ssuperior","tsuperior","","ff","fi","fl","ffi","ffl","parenleftinferior","","parenrightinferior","Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall","Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","exclamdownsmall","centoldstyle","Lslashsmall","","","Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall","","Dotaccentsmall","","","Macronsmall","","","figuredash","hypheninferior","","","Ogoneksmall","Ringsmall","Cedillasmall","","","","onequarter","onehalf","threequarters","questiondownsmall","oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds","","","zerosuperior","onesuperior","twosuperior","threesuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","eightsuperior","ninesuperior","zeroinferior","oneinferior","twoinferior","threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior","eightinferior","nineinferior","centinferior","dollarinferior","periodinferior","commainferior","Agravesmall","Aacutesmall","Acircumflexsmall","Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall","Egravesmall","Eacutesmall","Ecircumflexsmall","Edieresissmall","Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall","Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall","Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall","Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall","Thornsmall","Ydieresissmall"],MacExpertEncoding=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclamsmall","Hungarumlautsmall","centoldstyle","dollaroldstyle","dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","comma","hyphen","period","fraction","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","colon","semicolon","","threequartersemdash","","questionsmall","","","","","Ethsmall","","","onequarter","onehalf","threequarters","oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds","","","","","","","ff","fi","fl","ffi","ffl","parenleftinferior","","parenrightinferior","Circumflexsmall","hypheninferior","Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall","Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","","","asuperior","centsuperior","","","","","Aacutesmall","Agravesmall","Acircumflexsmall","Adieresissmall","Atildesmall","Aringsmall","Ccedillasmall","Eacutesmall","Egravesmall","Ecircumflexsmall","Edieresissmall","Iacutesmall","Igravesmall","Icircumflexsmall","Idieresissmall","Ntildesmall","Oacutesmall","Ogravesmall","Ocircumflexsmall","Odieresissmall","Otildesmall","Uacutesmall","Ugravesmall","Ucircumflexsmall","Udieresissmall","","eightsuperior","fourinferior","threeinferior","sixinferior","eightinferior","seveninferior","Scaronsmall","","centinferior","twoinferior","","Dieresissmall","","Caronsmall","osuperior","fiveinferior","","commainferior","periodinferior","Yacutesmall","","dollarinferior","","","Thornsmall","","nineinferior","zeroinferior","Zcaronsmall","AEsmall","Oslashsmall","questiondownsmall","oneinferior","Lslashsmall","","","","","","","Cedillasmall","","","","","","OEsmall","figuredash","hyphensuperior","","","","","exclamdownsmall","","Ydieresissmall","","onesuperior","twosuperior","threesuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","ninesuperior","zerosuperior","","esuperior","rsuperior","tsuperior","","","isuperior","ssuperior","dsuperior","","","","","","lsuperior","Ogoneksmall","Brevesmall","Macronsmall","bsuperior","nsuperior","msuperior","commasuperior","periodsuperior","Dotaccentsmall","Ringsmall","","","",""],MacRomanEncoding=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quotesingle","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","grave","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","","Adieresis","Aring","Ccedilla","Eacute","Ntilde","Odieresis","Udieresis","aacute","agrave","acircumflex","adieresis","atilde","aring","ccedilla","eacute","egrave","ecircumflex","edieresis","iacute","igrave","icircumflex","idieresis","ntilde","oacute","ograve","ocircumflex","odieresis","otilde","uacute","ugrave","ucircumflex","udieresis","dagger","degree","cent","sterling","section","bullet","paragraph","germandbls","registered","copyright","trademark","acute","dieresis","notequal","AE","Oslash","infinity","plusminus","lessequal","greaterequal","yen","mu","partialdiff","summation","product","pi","integral","ordfeminine","ordmasculine","Omega","ae","oslash","questiondown","exclamdown","logicalnot","radical","florin","approxequal","Delta","guillemotleft","guillemotright","ellipsis","space","Agrave","Atilde","Otilde","OE","oe","endash","emdash","quotedblleft","quotedblright","quoteleft","quoteright","divide","lozenge","ydieresis","Ydieresis","fraction","currency","guilsinglleft","guilsinglright","fi","fl","daggerdbl","periodcentered","quotesinglbase","quotedblbase","perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave","Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex","apple","Ograve","Uacute","Ucircumflex","Ugrave","dotlessi","circumflex","tilde","macron","breve","dotaccent","ring","cedilla","hungarumlaut","ogonek","caron"],StandardEncoding=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","quoteleft","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","exclamdown","cent","sterling","fraction","yen","florin","section","currency","quotesingle","quotedblleft","guillemotleft","guilsinglleft","guilsinglright","fi","fl","","endash","dagger","daggerdbl","periodcentered","","paragraph","bullet","quotesinglbase","quotedblbase","quotedblright","guillemotright","ellipsis","perthousand","","questiondown","","grave","acute","circumflex","tilde","macron","breve","dotaccent","dieresis","","ring","cedilla","","hungarumlaut","ogonek","caron","emdash","","","","","","","","","","","","","","","","","AE","","ordfeminine","","","","","Lslash","Oslash","OE","ordmasculine","","","","","","ae","","","","dotlessi","","","lslash","oslash","oe","germandbls","","","",""],WinAnsiEncoding=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quotesingle","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","grave","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","bullet","Euro","bullet","quotesinglbase","florin","quotedblbase","ellipsis","dagger","daggerdbl","circumflex","perthousand","Scaron","guilsinglleft","OE","bullet","Zcaron","bullet","bullet","quoteleft","quoteright","quotedblleft","quotedblright","bullet","endash","emdash","tilde","trademark","scaron","guilsinglright","oe","bullet","zcaron","Ydieresis","space","exclamdown","cent","sterling","currency","yen","brokenbar","section","dieresis","copyright","ordfeminine","guillemotleft","logicalnot","hyphen","registered","macron","degree","plusminus","twosuperior","threesuperior","acute","mu","paragraph","periodcentered","cedilla","onesuperior","ordmasculine","guillemotright","onequarter","onehalf","threequarters","questiondown","Agrave","Aacute","Acircumflex","Atilde","Adieresis","Aring","AE","Ccedilla","Egrave","Eacute","Ecircumflex","Edieresis","Igrave","Iacute","Icircumflex","Idieresis","Eth","Ntilde","Ograve","Oacute","Ocircumflex","Otilde","Odieresis","multiply","Oslash","Ugrave","Uacute","Ucircumflex","Udieresis","Yacute","Thorn","germandbls","agrave","aacute","acircumflex","atilde","adieresis","aring","ae","ccedilla","egrave","eacute","ecircumflex","edieresis","igrave","iacute","icircumflex","idieresis","eth","ntilde","ograve","oacute","ocircumflex","otilde","odieresis","divide","oslash","ugrave","uacute","ucircumflex","udieresis","yacute","thorn","ydieresis"],SymbolSetEncoding=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclam","universal","numbersign","existential","percent","ampersand","suchthat","parenleft","parenright","asteriskmath","plus","comma","minus","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","congruent","Alpha","Beta","Chi","Delta","Epsilon","Phi","Gamma","Eta","Iota","theta1","Kappa","Lambda","Mu","Nu","Omicron","Pi","Theta","Rho","Sigma","Tau","Upsilon","sigma1","Omega","Xi","Psi","Zeta","bracketleft","therefore","bracketright","perpendicular","underscore","radicalex","alpha","beta","chi","delta","epsilon","phi","gamma","eta","iota","phi1","kappa","lambda","mu","nu","omicron","pi","theta","rho","sigma","tau","upsilon","omega1","omega","xi","psi","zeta","braceleft","bar","braceright","similar","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Euro","Upsilon1","minute","lessequal","fraction","infinity","florin","club","diamond","heart","spade","arrowboth","arrowleft","arrowup","arrowright","arrowdown","degree","plusminus","second","greaterequal","multiply","proportional","partialdiff","bullet","divide","notequal","equivalence","approxequal","ellipsis","arrowvertex","arrowhorizex","carriagereturn","aleph","Ifraktur","Rfraktur","weierstrass","circlemultiply","circleplus","emptyset","intersection","union","propersuperset","reflexsuperset","notsubset","propersubset","reflexsubset","element","notelement","angle","gradient","registerserif","copyrightserif","trademarkserif","product","radical","dotmath","logicalnot","logicaland","logicalor","arrowdblboth","arrowdblleft","arrowdblup","arrowdblright","arrowdbldown","lozenge","angleleft","registersans","copyrightsans","trademarksans","summation","parenlefttp","parenleftex","parenleftbt","bracketlefttp","bracketleftex","bracketleftbt","bracelefttp","braceleftmid","braceleftbt","braceex","","angleright","integral","integraltp","integralex","integralbt","parenrighttp","parenrightex","parenrightbt","bracketrighttp","bracketrightex","bracketrightbt","bracerighttp","bracerightmid","bracerightbt",""],ZapfDingbatsEncoding=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","a1","a2","a202","a3","a4","a5","a119","a118","a117","a11","a12","a13","a14","a15","a16","a105","a17","a18","a19","a20","a21","a22","a23","a24","a25","a26","a27","a28","a6","a7","a8","a9","a10","a29","a30","a31","a32","a33","a34","a35","a36","a37","a38","a39","a40","a41","a42","a43","a44","a45","a46","a47","a48","a49","a50","a51","a52","a53","a54","a55","a56","a57","a58","a59","a60","a61","a62","a63","a64","a65","a66","a67","a68","a69","a70","a71","a72","a73","a74","a203","a75","a204","a76","a77","a78","a79","a81","a82","a83","a84","a97","a98","a99","a100","","a89","a90","a93","a94","a91","a92","a205","a85","a206","a86","a87","a88","a95","a96","","","","","","","","","","","","","","","","","","","","a101","a102","a103","a104","a106","a107","a108","a112","a111","a110","a109","a120","a121","a122","a123","a124","a125","a126","a127","a128","a129","a130","a131","a132","a133","a134","a135","a136","a137","a138","a139","a140","a141","a142","a143","a144","a145","a146","a147","a148","a149","a150","a151","a152","a153","a154","a155","a156","a157","a158","a159","a160","a161","a163","a164","a196","a165","a192","a166","a167","a168","a169","a170","a171","a172","a173","a162","a174","a175","a176","a177","a178","a179","a193","a180","a199","a181","a200","a182","","a201","a183","a184","a197","a185","a194","a198","a186","a195","a187","a188","a189","a190","a191",""];function getEncoding(encodingName){switch(encodingName){case"WinAnsiEncoding":return WinAnsiEncoding;case"StandardEncoding":return StandardEncoding;case"MacRomanEncoding":return MacRomanEncoding;case"SymbolSetEncoding":return SymbolSetEncoding;case"ZapfDingbatsEncoding":return ZapfDingbatsEncoding;case"ExpertEncoding":return ExpertEncoding;case"MacExpertEncoding":return MacExpertEncoding;default:return null}}const MAX_SUBR_NESTING=10,CFFStandardStrings=[".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","quoteleft","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","exclamdown","cent","sterling","fraction","yen","florin","section","currency","quotesingle","quotedblleft","guillemotleft","guilsinglleft","guilsinglright","fi","fl","endash","dagger","daggerdbl","periodcentered","paragraph","bullet","quotesinglbase","quotedblbase","quotedblright","guillemotright","ellipsis","perthousand","questiondown","grave","acute","circumflex","tilde","macron","breve","dotaccent","dieresis","ring","cedilla","hungarumlaut","ogonek","caron","emdash","AE","ordfeminine","Lslash","Oslash","OE","ordmasculine","ae","dotlessi","lslash","oslash","oe","germandbls","onesuperior","logicalnot","mu","trademark","Eth","onehalf","plusminus","Thorn","onequarter","divide","brokenbar","degree","thorn","threequarters","twosuperior","registered","minus","eth","multiply","threesuperior","copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring","Atilde","Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave","Iacute","Icircumflex","Idieresis","Igrave","Ntilde","Oacute","Ocircumflex","Odieresis","Ograve","Otilde","Scaron","Uacute","Ucircumflex","Udieresis","Ugrave","Yacute","Ydieresis","Zcaron","aacute","acircumflex","adieresis","agrave","aring","atilde","ccedilla","eacute","ecircumflex","edieresis","egrave","iacute","icircumflex","idieresis","igrave","ntilde","oacute","ocircumflex","odieresis","ograve","otilde","scaron","uacute","ucircumflex","udieresis","ugrave","yacute","ydieresis","zcaron","exclamsmall","Hungarumlautsmall","dollaroldstyle","dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","commasuperior","threequartersemdash","periodsuperior","questionsmall","asuperior","bsuperior","centsuperior","dsuperior","esuperior","isuperior","lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior","tsuperior","ff","ffi","ffl","parenleftinferior","parenrightinferior","Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall","Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","exclamdownsmall","centoldstyle","Lslashsmall","Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall","Dotaccentsmall","Macronsmall","figuredash","hypheninferior","Ogoneksmall","Ringsmall","Cedillasmall","questiondownsmall","oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds","zerosuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","eightsuperior","ninesuperior","zeroinferior","oneinferior","twoinferior","threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior","eightinferior","nineinferior","centinferior","dollarinferior","periodinferior","commainferior","Agravesmall","Aacutesmall","Acircumflexsmall","Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall","Egravesmall","Eacutesmall","Ecircumflexsmall","Edieresissmall","Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall","Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall","Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall","Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall","Thornsmall","Ydieresissmall","001.000","001.001","001.002","001.003","Black","Bold","Book","Light","Medium","Regular","Roman","Semibold"],NUM_STANDARD_CFF_STRINGS=391,CharstringValidationData=[null,{id:"hstem",min:2,stackClearing:!0,stem:!0},null,{id:"vstem",min:2,stackClearing:!0,stem:!0},{id:"vmoveto",min:1,stackClearing:!0},{id:"rlineto",min:2,resetStack:!0},{id:"hlineto",min:1,resetStack:!0},{id:"vlineto",min:1,resetStack:!0},{id:"rrcurveto",min:6,resetStack:!0},null,{id:"callsubr",min:1,undefStack:!0},{id:"return",min:0,undefStack:!0},null,null,{id:"endchar",min:0,stackClearing:!0},null,null,null,{id:"hstemhm",min:2,stackClearing:!0,stem:!0},{id:"hintmask",min:0,stackClearing:!0},{id:"cntrmask",min:0,stackClearing:!0},{id:"rmoveto",min:2,stackClearing:!0},{id:"hmoveto",min:1,stackClearing:!0},{id:"vstemhm",min:2,stackClearing:!0,stem:!0},{id:"rcurveline",min:8,resetStack:!0},{id:"rlinecurve",min:8,resetStack:!0},{id:"vvcurveto",min:4,resetStack:!0},{id:"hhcurveto",min:4,resetStack:!0},null,{id:"callgsubr",min:1,undefStack:!0},{id:"vhcurveto",min:4,resetStack:!0},{id:"hvcurveto",min:4,resetStack:!0}],CharstringValidationData12=[null,null,null,{id:"and",min:2,stackDelta:-1},{id:"or",min:2,stackDelta:-1},{id:"not",min:1,stackDelta:0},null,null,null,{id:"abs",min:1,stackDelta:0},{id:"add",min:2,stackDelta:-1,stackFn(stack,index){stack[index-2]=stack[index-2]+stack[index-1]}},{id:"sub",min:2,stackDelta:-1,stackFn(stack,index){stack[index-2]=stack[index-2]-stack[index-1]}},{id:"div",min:2,stackDelta:-1,stackFn(stack,index){stack[index-2]=stack[index-2]/stack[index-1]}},null,{id:"neg",min:1,stackDelta:0,stackFn(stack,index){stack[index-1]=-stack[index-1]}},{id:"eq",min:2,stackDelta:-1},null,null,{id:"drop",min:1,stackDelta:-1},null,{id:"put",min:2,stackDelta:-2},{id:"get",min:1,stackDelta:0},{id:"ifelse",min:4,stackDelta:-3},{id:"random",min:0,stackDelta:1},{id:"mul",min:2,stackDelta:-1,stackFn(stack,index){stack[index-2]=stack[index-2]*stack[index-1]}},null,{id:"sqrt",min:1,stackDelta:0},{id:"dup",min:1,stackDelta:1},{id:"exch",min:2,stackDelta:0},{id:"index",min:2,stackDelta:0},{id:"roll",min:3,stackDelta:-2},null,null,null,{id:"hflex",min:7,resetStack:!0},{id:"flex",min:13,resetStack:!0},{id:"hflex1",min:9,resetStack:!0},{id:"flex1",min:11,resetStack:!0}];class CFFParser{constructor(file,properties,seacAnalysisEnabled){this.bytes=file.getBytes(),this.properties=properties,this.seacAnalysisEnabled=!!seacAnalysisEnabled}parse(){var properties=this.properties,cff=new CFF,header=(this.cff=cff,this.parseHeader()),nameIndex=this.parseIndex(header.endPos),topDictIndex=this.parseIndex(nameIndex.endPos),stringIndex=this.parseIndex(topDictIndex.endPos),globalSubrIndex=this.parseIndex(stringIndex.endPos),topDictIndex=this.parseDict(topDictIndex.obj.get(0)),topDictIndex=this.createDict(CFFTopDict,topDictIndex,cff.strings),header=(cff.header=header.obj,cff.names=this.parseNameIndex(nameIndex.obj),cff.strings=this.parseStringIndex(stringIndex.obj),cff.topDict=topDictIndex,cff.globalSubrIndex=globalSubrIndex.obj,this.parsePrivateDict(cff.topDict),cff.isCIDFont=topDictIndex.hasName("ROS"),topDictIndex.getByName("CharStrings")),nameIndex=this.parseIndex(header).obj,stringIndex=topDictIndex.getByName("FontMatrix"),header=(stringIndex&&(properties.fontMatrix=stringIndex),topDictIndex.getByName("FontBBox"));header&&(properties.ascent=Math.max(header[3],header[1]),properties.descent=Math.min(header[1],header[3]),properties.ascentScaled=!0);let charset,encoding;if(cff.isCIDFont){var fdArrayIndex=this.parseIndex(topDictIndex.getByName("FDArray")).obj;for(let i=0,ii=fdArrayIndex.count;i=bytesLength)throw new FormatError("Invalid CFF header");0!==offset&&(info("cff data is shifted"),bytes=bytes.subarray(offset),this.bytes=bytes);var major=bytes[0],minor=bytes[1],hdrSize=bytes[2],offSize=bytes[3];return{obj:new CFFHeader(major,minor,hdrSize,offSize),endPos:hdrSize}}parseDict(dict){let pos=0;function parseOperand(){let value=dict[pos++];if(30!==value)return 28===value?value=((value=dict[pos++])<<24|dict[pos++]<<16)>>16:29===value?value=(value=(value=(value=dict[pos++])<<8|dict[pos++])<<8|dict[pos++])<<8|dict[pos++]:32<=value&&value<=246?value-139:247<=value&&value<=250?256*(value-247)+dict[pos++]+108:251<=value&&value<=254?-256*(value-251)-dict[pos++]-108:(warn('CFFParser_parseDict: "'+value+'" is a reserved command.'),NaN);{let str="";var lookup=["0","1","2","3","4","5","6","7","8","9",".","E","E-",null,"-"],length=dict.length;for(;pos>4,b=15&b;if(15==b1)break;if(str+=lookup[b1],15==b)break;str+=lookup[b]}return parseFloat(str)}}let operands=[];for(var entries=[],end=(pos=0,dict.length);posMAX_SUBR_NESTING)return!1;let stackSize=state.stackSize;var stack=state.stack;let length=data.length;for(let j=0;j>16,j+=2,stackSize++;else if(14===value){if(4<=stackSize&&(stackSize-=4,this.seacAnalysisEnabled))return state.seac=stack.slice(stackSize,stackSize+4),!1;validationCommand=CharstringValidationData[value]}else if(32<=value&&value<=246)stack[stackSize]=value-139,stackSize++;else if(247<=value&&value<=254)stack[stackSize]=value<251?(value-247<<8)+data[j]+108:-(value-251<<8)-data[j]-108,j++,stackSize++;else if(255===value)stack[stackSize]=(data[j]<<24|data[j+1]<<16|data[j+2]<<8|data[j+3])/65536,j+=4,stackSize++;else if(19===value||20===value){if(state.hints+=stackSize>>1,0===state.hints){data.copyWithin(j-1,j,-1),--j,--length;continue}j+=state.hints+7>>3,stackSize%=2,validationCommand=CharstringValidationData[value]}else{if(10===value||29===value){q=10===value?localSubrIndex:globalSubrIndex;if(!q)return warn("Missing subrsIndex for "+(validationCommand=CharstringValidationData[value]).id),!1;let bias=32768;q.count<1240?bias=107:q.count<33900&&(bias=1131);var subrNumber=stack[--stackSize]+bias;if(subrNumber<0||subrNumber>=q.count||isNaN(subrNumber))return warn("Out of bounds subrIndex for "+(validationCommand=CharstringValidationData[value]).id),!1;if(state.stackSize=stackSize,state.callDepth++,!this.parseCharString(state,q.get(subrNumber),localSubrIndex,globalSubrIndex))return!1;state.callDepth--,stackSize=state.stackSize;continue}if(11===value)return state.stackSize=stackSize,!0;if(0===value&&j===data.length)data[j-1]=14,validationCommand=CharstringValidationData[14];else{if(9===value){data.copyWithin(j-1,j,-1),--j,--length;continue}validationCommand=CharstringValidationData[value]}}if(validationCommand){if(validationCommand.stem&&(state.hints+=stackSize>>1,3===value||23===value?state.hasVStems=!0:!state.hasVStems||1!==value&&18!==value||(warn("CFF stem hints are in wrong order"),data[j-1]=1===value?3:23)),"min"in validationCommand&&!state.undefStack&&stackSize=fdArray.length&&(warn("Invalid fd index for glyph index."),valid=!1),valid&&(privateDictToUse=fdArray[fdIndex].privateDict,localSubrToUse=privateDictToUse.subrsIndex)):localSubrIndex&&(localSubrToUse=localSubrIndex),valid=valid&&this.parseCharString(state,charstring,localSubrToUse,globalSubrIndex),null!==state.width?(fdIndex=privateDictToUse.getByName("nominalWidthX"),widths[i]=fdIndex+state.width):(charstring=privateDictToUse.getByName("defaultWidthX"),widths[i]=charstring),null!==state.seac&&(seacs[i]=state.seac),valid||charStrings.set(i,new Uint8Array([14]))}return{charStrings:charStrings,seacs:seacs,widths:widths}}emptyPrivateDictionary(parentDict){var privateDict=this.createDict(CFFPrivateDict,[],parentDict.strings);parentDict.setByKey(18,[0,0]),parentDict.privateDict=privateDict}parsePrivateDict(parentDict){var size,relativeOffset,privateOffset;parentDict.hasName("Private")?(privateOffset=parentDict.getByName("Private"),Array.isArray(privateOffset)&&2===privateOffset.length?(size=privateOffset[0],privateOffset=privateOffset[1],0===size||privateOffset>=this.bytes.length?this.emptyPrivateDictionary(parentDict):(size=this.bytes.subarray(privateOffset,privateOffset+size),size=this.parseDict(size),size=this.createDict(CFFPrivateDict,size,parentDict.strings),0===(parentDict.privateDict=size).getByName("ExpansionFactor")&&size.setByName("ExpansionFactor",.06),size.getByName("Subrs")&&(relativeOffset=privateOffset+(privateOffset=size.getByName("Subrs")),0===privateOffset||relativeOffset>=this.bytes.length?this.emptyPrivateDictionary(parentDict):(privateOffset=this.parseIndex(relativeOffset),size.subrsIndex=privateOffset.obj)))):parentDict.removeByName("Private")):this.emptyPrivateDictionary(parentDict)}parseCharsets(pos,length,strings,cid){if(0===pos)return new CFFCharset(!0,CFFCharsetPredefinedTypes.ISO_ADOBE,ISOAdobeCharset);if(1===pos)return new CFFCharset(!0,CFFCharsetPredefinedTypes.EXPERT,ExpertCharset);if(2===pos)return new CFFCharset(!0,CFFCharsetPredefinedTypes.EXPERT_SUBSET,ExpertSubsetCharset);var bytes=this.bytes,start=pos,format=bytes[pos++],charset=[cid?0:".notdef"];let id,count,i;switch(--length,format){case 0:for(i=0;i=this.charStrings.count)&&0=this.fdSelect.length?-1:this.fdSelect[glyphIndex]}}class CFFOffsetTracker{constructor(){this.offsets=Object.create(null)}isTracking(key){return key in this.offsets}track(key,location){if(key in this.offsets)throw new FormatError("Already tracking location of "+key);this.offsets[key]=location}offset(value){for(const key in this.offsets)this.offsets[key]+=value}setEntryLocation(key,values,output){if(!(key in this.offsets))throw new FormatError("Not tracking location of "+key);var data=output.data,dataOffset=this.offsets[key];for(let i=0,ii=values.length;i>24&255,data[offset2]=value>>16&255,data[offset3]=value>>8&255,data[offset4]=255&value}}}class CFFCompiler{constructor(cff){this.cff=cff}compile(){var cff=this.cff,output={data:[],length:0,add(data){try{this.data.push(...data)}catch{this.data=this.data.concat(data)}this.length=this.data.length}},header=this.compileHeader(cff.header),header=(output.add(header),this.compileNameIndex(cff.names));if(output.add(header),cff.isCIDFont&&cff.topDict.hasName("FontMatrix")){var base=cff.topDict.getByName("FontMatrix");cff.topDict.removeByName("FontMatrix");for(const subDict of cff.fdArray){let matrix=base.slice(0);subDict.hasName("FontMatrix")&&(matrix=Util.transform(matrix,subDict.getByName("FontMatrix"))),subDict.setByName("FontMatrix",matrix)}}16>8),255&value]:-1131<=value&&value<=-108?[251+((value=-value-108)>>8),255&value]:-32768<=value&&value<=32767?[28,value>>8&255,255&value]:[29,value>>24&255,value>>16&255,value>>8&255,255&value]}compileHeader(header){return[header.major,header.minor,4,header.offSize]}compileNameIndex(names){var nameIndex=new CFFIndex;for(const name of names){var length=Math.min(name.length,127);let sanitizedName=new Array(length);for(let j=0;j"===char||"/"===char||"%"===char)&&(char="_"),sanitizedName[j]=char}""===(sanitizedName=sanitizedName.join(""))&&(sanitizedName="Bad_Font_Name"),nameIndex.add(stringToBytes(sanitizedName))}return this.compileIndex(nameIndex)}compileTopDicts(dicts,length,removeCidKeys){var fontDictTrackers=[];let fdArrayIndex=new CFFIndex;for(const fontDict of dicts){removeCidKeys&&(fontDict.removeByName("CIDFontVersion"),fontDict.removeByName("CIDFontRevision"),fontDict.removeByName("CIDFontType"),fontDict.removeByName("CIDCount"),fontDict.removeByName("UIDBase"));var fontDictTracker=new CFFOffsetTracker,fontDictData=this.compileDict(fontDict,fontDictTracker);fontDictTrackers.push(fontDictTracker),fdArrayIndex.add(fontDictData),fontDictTracker.offset(length)}return{trackers:fontDictTrackers,output:fdArrayIndex=this.compileIndex(fdArrayIndex,fontDictTrackers)}}compilePrivateDicts(dicts,trackers,output){for(let i=0,ii=dicts.length;i>8&255,255&numGlyphs]);else{let charsetIndex=(out=new Uint8Array(1+2*numGlyphs))[0]=0;var name,numCharsets=charset.charset.length;let warned=!1;for(let i=1;i>8&255,out[i+1]=255&sid}}return this.compileTypedArray(out)}compileEncoding(encoding){return this.compileTypedArray(encoding.raw)}compileFDSelect(fdSelect){var format=fdSelect.format;let out,i;switch(format){case 0:for((out=new Uint8Array(1+fdSelect.fdSelect.length))[0]=format,i=0;i>8&255,255&i,currentFD),lastFD=currentFD)}var numRanges=(ranges.length-3)/3;ranges[1]=numRanges>>8&255,ranges[2]=255&numRanges,ranges.push(i>>8&255,255&i),out=new Uint8Array(ranges)}return this.compileTypedArray(out)}compileTypedArray(data){return Array.from(data)}compileIndex(index,trackers=[]){var objects=index.objects,count=objects.length;if(0===count)return[0,0];var data=[count>>8&255,255&count];let lastOffset=1,i;for(i=0;i>8&255,255&relativeOffset):3===offsetSize?data.push(relativeOffset>>16&255,relativeOffset>>8&255,255&relativeOffset):data.push(relativeOffset>>>24&255,relativeOffset>>16&255,relativeOffset>>8&255,255&relativeOffset),objects[i]&&(relativeOffset+=objects[i].length);for(i=0;i=range[i]&&value<=range[i+1])return lastPosition}for(let i=0,ii=UnicodeRanges.length;i=range[j]&&value<=range[j+1])return i}return-1}const SpecialCharRegExp=new RegExp("^(\\s)|(\\p{Mn})|(\\p{Cf})$","u"),CategoryCache=new Map;function getCharUnicodeCategory(char){var cachedCategory=CategoryCache.get(char);return cachedCategory||(cachedCategory={isWhitespace:!!(cachedCategory=char.match(SpecialCharRegExp))?.[1],isZeroWidthDiacritic:!!cachedCategory?.[2],isInvisibleFormatMark:!!cachedCategory?.[3]},CategoryCache.set(char,cachedCategory),cachedCategory)}function clearUnicodeCaches(){CategoryCache.clear()}const SEAC_ANALYSIS_ENABLED=!0,FontFlags={FixedPitch:1,Serif:2,Symbolic:4,Script:8,Nonsymbolic:32,Italic:64,AllCap:65536,SmallCap:131072,ForceBold:262144},MacStandardGlyphOrdering=[".notdef",".null","nonmarkingreturn","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quotesingle","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","grave","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","Adieresis","Aring","Ccedilla","Eacute","Ntilde","Odieresis","Udieresis","aacute","agrave","acircumflex","adieresis","atilde","aring","ccedilla","eacute","egrave","ecircumflex","edieresis","iacute","igrave","icircumflex","idieresis","ntilde","oacute","ograve","ocircumflex","odieresis","otilde","uacute","ugrave","ucircumflex","udieresis","dagger","degree","cent","sterling","section","bullet","paragraph","germandbls","registered","copyright","trademark","acute","dieresis","notequal","AE","Oslash","infinity","plusminus","lessequal","greaterequal","yen","mu","partialdiff","summation","product","pi","integral","ordfeminine","ordmasculine","Omega","ae","oslash","questiondown","exclamdown","logicalnot","radical","florin","approxequal","Delta","guillemotleft","guillemotright","ellipsis","nonbreakingspace","Agrave","Atilde","Otilde","OE","oe","endash","emdash","quotedblleft","quotedblright","quoteleft","quoteright","divide","lozenge","ydieresis","Ydieresis","fraction","currency","guilsinglleft","guilsinglright","fi","fl","daggerdbl","periodcentered","quotesinglbase","quotedblbase","perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave","Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex","apple","Ograve","Uacute","Ucircumflex","Ugrave","dotlessi","circumflex","tilde","macron","breve","dotaccent","ring","cedilla","hungarumlaut","ogonek","caron","Lslash","lslash","Scaron","scaron","Zcaron","zcaron","brokenbar","Eth","eth","Yacute","yacute","Thorn","thorn","minus","multiply","onesuperior","twosuperior","threesuperior","onehalf","onequarter","threequarters","franc","Gbreve","gbreve","Idotaccent","Scedilla","scedilla","Cacute","cacute","Ccaron","ccaron","dcroat"];function recoverGlyphName(name,glyphsUnicodeMap){if(void 0===glyphsUnicodeMap[name]){var unicode=getUnicodeForGlyph(name,glyphsUnicodeMap);if(-1!==unicode)for(const key in glyphsUnicodeMap)if(glyphsUnicodeMap[key]===unicode)return key;info("Unable to recover a standard glyph name for: "+name)}return name}function type1FontGlyphMapping(properties,builtInEncoding,glyphNames){var charCodeToGlyphId=Object.create(null);let glyphId,charCode,baseEncoding;var isSymbolicFont=!!(properties.flags&FontFlags.Symbolic);if(properties.isInternalFont)for(baseEncoding=builtInEncoding,charCode=0;charCode=this.firstChar&&v<=this.lastChar?v:-1}amend(map){unreachable("Should not call amend()")}}class CFFFont{constructor(file,properties){this.properties=properties;var parser=new CFFParser(file,properties,SEAC_ANALYSIS_ENABLED),parser=(this.cff=parser.parse(),this.cff.duplicateFirstGlyph(),new CFFCompiler(this.cff));this.seacs=this.cff.seacs;try{this.data=parser.compile()}catch{warn("Failed to compile font "+properties.loadedName),this.data=file}this._createBuiltInEncoding()}get numGlyphs(){return this.cff.charStrings.count}getCharset(){return this.cff.charset.charset}getGlyphMapping(){var cff=this.cff,properties=this.properties,{cidToGidMap,cMap}=properties,charsets=cff.charset.charset;let charCodeToGlyphId,glyphId;if(properties.composite){let invCidToGidMap;if(0>>0}function getUint16(data,offset){return data[offset]<<8|data[offset+1]}function getInt16(data,offset){return(data[offset]<<24|data[offset+1]<<16)>>16}function getInt8(data,offset){return data[offset]<<24>>24}function getFloat214(data,offset){return getInt16(data,offset)/16384}function getSubroutineBias(subrs){subrs=subrs.length;let bias=32768;return subrs<1240?bias=107:subrs<33900&&(bias=1131),bias}function parseCmap(data,start,end){var offset=1===getUint16(data,start+2)?getUint32(data,start+8):getUint32(data,start+16),format=getUint16(data,start+offset);let ranges,p,i;if(4===format){getUint16(data,start+offset+2);var segCount=getUint16(data,start+offset+6)>>1;for(p=start+offset+14,ranges=[],i=0;i2*getUint16(data,offset)))(loca,0);for(let j=itemSize;j>1;code>1,stackClean=!0;break;case 4:y+=stack.pop(),moveTo(x,y),stackClean=!0;break;case 5:for(;0Math.abs(y-y0)?x+=stack.shift():y+=stack.shift(),bezierCurveTo(xa,ya,xb,yb,x,y);break;default:throw new FormatError("unknown operator: 12 "+v)}break;case 14:var bchar,cmap;return void(4<=stack.length&&(fdIndex=stack.pop(),bchar=stack.pop(),y=stack.pop(),x=stack.pop(),cmds.add(FontRenderOps.SAVE),cmds.add(FontRenderOps.TRANSLATE,[x,y]),cmap=lookupCmap(font.cmap,String.fromCharCode(font.glyphNameMap[StandardEncoding[fdIndex]])),compileCharString(font.glyphs[cmap.glyphId],cmds,font,cmap.glyphId),cmds.add(FontRenderOps.RESTORE),cmap=lookupCmap(font.cmap,String.fromCharCode(font.glyphNameMap[StandardEncoding[bchar]])),compileCharString(font.glyphs[cmap.glyphId],cmds,font,cmap.glyphId)));case 18:stems+=stack.length>>1,stackClean=!0;break;case 19:case 20:stems+=stack.length>>1,i+=stems+7>>3,stackClean=!0;break;case 21:y+=stack.pop(),moveTo(x+=stack.pop(),y),stackClean=!0;break;case 22:moveTo(x+=stack.pop(),y),stackClean=!0;break;case 23:stems+=stack.length>>1,stackClean=!0;break;case 24:for(;2>16),i+=2;break;case 29:n=stack.pop()+font.gsubrsBias,(subrCode=font.gsubrs[n])&&parse(subrCode);break;case 30:for(;0"number"==typeof arg?arg:0),this.cmds.push(cmd,...args)):this.cmds.push(cmd)}}class CompiledFont{constructor(fontMatrix){this.constructor===CompiledFont&&unreachable("Cannot initialize CompiledFont."),this.fontMatrix=fontMatrix,this.compiledGlyphs=Object.create(null),this.compiledCharCodeToGlyphId=Object.create(null)}getPathJs(unicode){var{charCode:unicode,glyphId}=lookupCmap(this.cmap,unicode);let fn=this.compiledGlyphs[glyphId],compileEx;if(!fn){try{fn=this.compileGlyph(this.glyphs[glyphId],glyphId)}catch(ex){fn=NOOP,compileEx=ex}this.compiledGlyphs[glyphId]=fn}if(this.compiledCharCodeToGlyphId[unicode]??=glyphId,compileEx)throw compileEx;return fn}compileGlyph(code,glyphId){if(!code||0===code.length||14===code[0])return NOOP;let fontMatrix=this.fontMatrix;this.isCFFCIDFont&&(0<=(fdIndex=this.fdSelect.getFDIndex(glyphId))&&fdIndex{return a+(g.getSize()+3&-4)},0)}write(){var totalSize=this.getSize(),glyfTable=new DataView(new ArrayBuffer(totalSize)),isLocationLong=131070>1);return{isLocationLong:isLocationLong,loca:new Uint8Array(locaTable.buffer),glyf:new Uint8Array(glyfTable.buffer)}}scale(factors){for(let i=0,ii=this.glyphs.length;ia+c.getSize(),0),this.header.getSize()+size):0}write(pos,buf){if(!this.header)return 0;var spos=pos;if(pos+=this.header.write(pos,buf),this.simple)pos+=this.simple.write(pos,buf);else for(const composite of this.composites)pos+=composite.write(pos,buf);return pos-spos}scale(factor){if(this.header){var xMiddle=(this.header.xMin+this.header.xMax)/2;if(this.header.scale(xMiddle,factor),this.simple)this.simple.scale(xMiddle,factor);else for(const composite of this.composites)composite.scale(xMiddle,factor)}}}class GlyphHeader{constructor({numberOfContours,xMin,yMin,xMax,yMax}){this.numberOfContours=numberOfContours,this.xMin=xMin,this.yMin=yMin,this.xMax=xMax,this.yMax=yMax}static parse(pos,glyf){return[10,new GlyphHeader({numberOfContours:glyf.getInt16(pos),xMin:glyf.getInt16(pos+2),yMin:glyf.getInt16(pos+4),xMax:glyf.getInt16(pos+6),yMax:glyf.getInt16(pos+8)})]}getSize(){return 10}write(pos,buf){return buf.setInt16(pos,this.numberOfContours),buf.setInt16(pos+2,this.xMin),buf.setInt16(pos+4,this.yMin),buf.setInt16(pos+6,this.xMax),buf.setInt16(pos+8,this.yMax),10}scale(x,factor){this.xMin=Math.round(x+(this.xMin-x)*factor),this.xMax=Math.round(x+(this.xMax-x)*factor)}}class Contour{constructor({flags,xCoordinates,yCoordinates}){this.xCoordinates=xCoordinates,this.yCoordinates=yCoordinates,this.flags=flags}}class SimpleGlyph{constructor({contours,instructions}){this.contours=contours,this.instructions=instructions}static parse(pos,glyf,numberOfContours){var endPtsOfContours=[];for(let i=0;i>8&255,dest[offset+1]=255&num}function writeInt32(dest,offset,num){dest[offset]=num>>24&255,dest[offset+1]=num>>16&255,dest[offset+2]=num>>8&255,dest[offset+3]=255&num}function writeData(dest,offset,data){if(data instanceof Uint8Array)dest.set(data,offset);else if("string"==typeof data)for(let i=0,ii=data.length;imaxPower2;)maxPower2<<=1,log2++;var searchRange=maxPower2*entrySize;return{range:searchRange,entry:log2,rangeShift:entrySize*entriesCount-searchRange}}toArray(){let sfnt=this.sfnt;var tables=this.tables,tablesNames=Object.keys(tables),numTables=(tablesNames.sort(),tablesNames.length);let i,j,jj,table,tableName,offset=OTF_HEADER_SIZE+numTables*OTF_TABLE_ENTRY_SIZE;var tableOffsets=[offset];for(i=0;i>>0;offset+=paddedLength,tableOffsets.push(offset)}var file=new Uint8Array(offset);for(i=0;i>>0}writeInt32(file,offset+4,checksum),writeInt32(file,offset+8,tableOffsets[i]),writeInt32(file,offset+12,tables[tableName].length),offset+=OTF_TABLE_ENTRY_SIZE}return file}addTable(tag,data){if(tag in this.tables)throw new Error("Table "+tag+" already exists");this.tables[tag]=data}}const HINTING_ENABLED=!1,COMMAND_MAP={hstem:[1],vstem:[3],vmoveto:[4],rlineto:[5],hlineto:[6],vlineto:[7],rrcurveto:[8],callsubr:[10],flex:[12,35],drop:[12,18],endchar:[14],rmoveto:[21],hmoveto:[22],vhcurveto:[30],hvcurveto:[31]};class Type1CharString{constructor(){this.width=0,this.lsb=0,this.flexing=!1,this.output=[],this.stack=[]}convert(encoded,subrs,seacAnalysisEnabled){var sby,num1,flexArgs,count=encoded.length;let error=!1,wx,sbx,subrNumber;for(let i=0;i>8&255,255&value):this.output.push(255,(value=65536*value|0)>>24&255,value>>16&255,value>>8&255,255&value)}return this.output.push(...command),keepStack?this.stack.splice(start,howManyArgs):this.stack.length=0,!1}}const EEXEC_ENCRYPT_KEY=55665,CHAR_STRS_ENCRYPT_KEY=4330;function isHexDigit(code){return 48<=code&&code<=57||65<=code&&code<=70||97<=code&&code<=102}function decrypt(data,key,discardNumber){if(discardNumber>=data.length)return new Uint8Array(0);let r=0|key,i,j;for(i=0;i>8,r=52845*(value+r)+22719&65535}return decrypted}function decryptAscii(data,key,discardNumber){let r=0|key;var count=data.length,decrypted=new Uint8Array(count>>>1);let i,j;for(i=0,j=0;i>8,r=52845*(digit1+r)+22719&65535)}}return decrypted.slice(discardNumber,j)}function isSpecial(c){return 47===c||91===c||93===c||123===c||125===c||40===c||41===c}class Type1Parser{constructor(stream,encrypted,seacAnalysisEnabled){var isBinary;encrypted&&(isBinary=!((isHexDigit((encrypted=stream.getBytes())[0])||isWhiteSpace(encrypted[0]))&&isHexDigit(encrypted[1])&&isHexDigit(encrypted[2])&&isHexDigit(encrypted[3])&&isHexDigit(encrypted[4])&&isHexDigit(encrypted[5])&&isHexDigit(encrypted[6])&&isHexDigit(encrypted[7])),stream=new Stream((isBinary?decrypt:decryptAscii)(encrypted,EEXEC_ENCRYPT_KEY,4))),this.seacAnalysisEnabled=!!seacAnalysisEnabled,this.stream=stream,this.nextChar()}readNumberArray(){this.getToken();for(var array=[];;){var token=this.getToken();if(null===token||"]"===token||"}"===token)break;array.push(parseFloat(token||0))}return array}readNumber(){var token=this.getToken();return parseFloat(token||0)}readInt(){var token=this.getToken();return 0|parseInt(token||0,10)}readBoolean(){return"true"===this.getToken()?1:0}nextChar(){return this.currentChar=this.stream.getByte()}prevChar(){return this.stream.skip(-2),this.currentChar=this.stream.getByte()}getToken(){let comment=!1,ch=this.currentChar;for(;;){if(-1===ch)return null;if(comment)10!==ch&&13!==ch||(comment=!1);else if(37===ch)comment=!0;else if(!isWhiteSpace(ch))break;ch=this.nextChar()}if(isSpecial(ch))return this.nextChar(),String.fromCharCode(ch);let token="";for(;token+=String.fromCharCode(ch),0<=(ch=this.nextChar())&&!isWhiteSpace(ch)&&!isSpecial(ch););return token}readCharStrings(bytes,lenIV){return-1===lenIV?bytes:decrypt(bytes,CHAR_STRS_ENCRYPT_KEY,lenIV)}extractFontProgram(properties){var glyph,encoded,stream=this.stream,subrs=[],charstrings=[],privateData=Object.create(null),program=(privateData.lenIV=4,{subrs:[],charstrings:[],properties:{privateData:privateData}});let token,length,data,lenIV;for(;null!==(token=this.getToken());)if("/"===token)switch(token=this.getToken()){case"CharStrings":for(this.getToken(),this.getToken(),this.getToken(),this.getToken();;){if(null===(token=this.getToken())||"end"===token)break;"/"===token&&(glyph=this.getToken(),length=this.readInt(),this.getToken(),data=0=properties.firstChar&&index<=properties.lastChar&&(properties.widths[index]=charString.width)}}return program}extractFontHeader(properties){let token;for(;null!==(token=this.getToken());)if("/"===token)switch(token=this.getToken()){case"FontMatrix":var matrix=this.readNumberArray();properties.fontMatrix=matrix;break;case"Encoding":matrix=this.getToken();let encoding;if(/^\d+$/.test(matrix)){encoding=[];var size=0|parseInt(matrix,10);this.getToken();for(let j=0;j=signatureLength){for(i+=j;i=this.numGlyphs)&&(0===id||0>>8}function signedInt16(b0,b1){b0=(b0<<8)+b1;return 32768&b0?b0-65536:b0}function writeUint32(bytes,index,value){bytes[index+3]=255&value,bytes[index+2]=value>>>8,bytes[index+1]=value>>>16,bytes[index]=value>>>24}function int32(b0,b1,b2,b3){return(b0<<24)+(b1<<16)+(b2<<8)+b3}function string16(value){return String.fromCharCode(value>>8&255,255&value)}function safeString16(value){return 32767>8&255,255&value)}function isTrueTypeFile(file){file=file.peekBytes(4);return 65536===readUint32(file,0)||"true"===bytesToString(file)}function isTrueTypeCollectionFile(file){return"ttcf"===bytesToString(file.peekBytes(4))}function isOpenTypeFile(file){return"OTTO"===bytesToString(file.peekBytes(4))}function isType1File(file){file=file.peekBytes(2);return 37===file[0]&&33===file[1]||128===file[0]&&1===file[1]}function isCFFFile(file){file=file.peekBytes(4);return 1<=file[0]&&1<=file[3]&&file[3]<=4}function getFontFileType(file,{type,subtype,composite}){let fileType,fileSubtype;return isTrueTypeFile(file)||isTrueTypeCollectionFile(file)?fileType=composite?"CIDFontType2":"TrueType":isOpenTypeFile(file)?fileType=composite?"CIDFontType2":"OpenType":isType1File(file)?fileType=composite?"CIDFontType0":"MMType1"===type?"MMType1":"Type1":fileSubtype=isCFFFile(file)?composite?(fileType="CIDFontType0","CIDFontType0C"):(fileType="MMType1"===type?"MMType1":"Type1","Type1C"):(warn("getFontFileType: Unable to detect correct font file Type/Subtype."),fileType=type,subtype),[fileType,fileSubtype]}function applyStandardFontGlyphMap(map,glyphMap){for(const charCode in glyphMap)map[+charCode]=glyphMap[charCode]}function buildToFontChar(encoding,glyphsUnicodeMap,differences){var toFontChar=[];let unicode;for(let i=0,ii=encoding.length;iprivateUseOffetEnd){if(++privateUseAreaIndex>=PRIVATE_USE_AREAS.length){warn("Ran out of space in font private use area.");break}nextAvailableFontCharCode=PRIVATE_USE_AREAS[privateUseAreaIndex][0],privateUseOffetEnd=PRIVATE_USE_AREAS[privateUseAreaIndex][1]}var fontCharCode=nextAvailableFontCharCode++;0===glyphId&&(glyphId=newGlyphZeroId);let unicode=toUnicode.get(originalCharCode);!(unicode="string"==typeof unicode?unicode.codePointAt(0):unicode)||(code=unicode,PRIVATE_USE_AREAS[0][0]<=code&&code<=PRIVATE_USE_AREAS[0][1])||PRIVATE_USE_AREAS[1][0]<=code&&code<=PRIVATE_USE_AREAS[1][1]||usedGlyphIds.has(glyphId)||(toUnicodeExtraMap.set(unicode,glyphId),usedGlyphIds.add(glyphId)),newMap[fontCharCode]=glyphId,toFontChar[originalCharCode]=fontCharCode}}return{toFontChar:toFontChar,charCodeToGlyphId:newMap,toUnicodeExtraMap:toUnicodeExtraMap,nextAvailableFontCharCode:nextAvailableFontCharCode}}function getRanges(glyphs,toUnicodeExtraMap,numGlyphs){var codes=[];for(const charCode in glyphs)glyphs[charCode]>=numGlyphs||codes.push({fontCharCode:0|charCode,glyphId:glyphs[charCode]});if(toUnicodeExtraMap)for(var[unicode,glyphId]of toUnicodeExtraMap)glyphId>=numGlyphs||codes.push({fontCharCode:unicode,glyphId:glyphId});0===codes.length&&codes.push({fontCharCode:0,glyphId:0}),codes.sort(function(a,b){return a.fontCharCode-b.fontCharCode});var ranges=[],length=codes.length;for(let n=0;ncode||!firstCharIndex)&&(firstCharIndex=code),lastCharIndex 123 are reserved for internal usage");ulUnicodeRange4|=1</%]/g,"").slice(0,63)}function createNameTable(name,proto){var strings=[(proto=proto||[[],[]])[0][0]||"Original licence",proto[0][1]||name,proto[0][2]||"Unknown",proto[0][3]||"uniqueID",proto[0][4]||name,proto[0][5]||"Version 0.11",proto[0][6]||createPostscriptName(name),proto[0][7]||"Unknown",proto[0][8]||"Unknown",proto[0][9]||"Unknown"],stringsUnicode=[];let i,ii,j,jj,str;for(i=0,ii=strings.length;i{var unicode;this.composite||-1!==(unicode=getUnicodeForGlyph(this.differences[charCode]||this.defaultEncoding[charCode],glyphsUnicodeMap))&&(unicodeCharCode=unicode),map[+charCode]=unicodeCharCode}),this.composite&&this.toUnicode instanceof IdentityToUnicodeMap&&/Tahoma|Verdana/i.test(name)&&applyStandardFontGlyphMap(map,getGlyphMapForStandardFonts()),this.toFontChar=map}amendFallbackToUnicode(properties),this.loadedName=fontName.split("-",1)[0]}checkAndRepair(name,font,properties){const VALID_TABLES=["OS/2","cmap","head","hhea","hmtx","maxp","name","post","loca","glyf","fpgm","prep","cvt ","CFF "];function readTables(file,numTables){var tables=Object.create(null);tables["OS/2"]=null,tables.cmap=null,tables.head=null,tables.hhea=null,tables.hmtx=null,tables.maxp=null,tables.name=null,tables.post=null;for(let i=0;i>>0,offset=file.getInt32()>>>0,length=file.getInt32()>>>0,previousPosition=file.pos,data=(file.pos=file.start||0,file.skip(offset),file.getBytes(length));file.pos=previousPosition,"head"===tag&&(data[8]=data[9]=data[10]=data[11]=0,data[17]|=32);return{tag:tag,checksum:checksum,length:length,offset:offset,data:data}}(file);VALID_TABLES.includes(table.tag)&&0!==table.length&&(tables[table.tag]=table)}return tables}function readOpenTypeHeader(ttf){return{version:ttf.getString(4),numTables:ttf.getUint16(),searchRange:ttf.getUint16(),entrySelector:ttf.getUint16(),rangeShift:ttf.getUint16()}}function readTrueTypeCollectionData(ttc,fontName){var{numFonts,offsetTable}=function(ttc){var ttcTag=ttc.getString(4),majorVersion=(assert("ttcf"===ttcTag,"Must be a TrueType Collection font."),ttc.getUint16()),minorVersion=ttc.getUint16(),numFonts=ttc.getInt32()>>>0,offsetTable=[];for(let i=0;i>>0);var header={ttcTag:ttcTag,majorVersion:majorVersion,minorVersion:minorVersion,numFonts:numFonts,offsetTable:offsetTable};switch(majorVersion){case 1:return header;case 2:return header.dsigTag=ttc.getInt32()>>>0,header.dsigLength=ttc.getInt32()>>>0,header.dsigOffset=ttc.getInt32()>>>0,header}throw new FormatError(`Invalid TrueType Collection majorVersion: ${majorVersion}.`)}(ttc),fontNameParts=fontName.split("+");let fallbackData;for(let i=0;i>>24&255,data[offset+1]=value>>16&255,data[offset+2]=value>>8&255,data[offset+3]=255&value}):(itemSize=2,itemDecode=function(data,offset){return data[offset]<<9|data[offset+1]<<1},function(data,offset,value){data[offset]=value>>9&255,data[offset+1]=value>>1&255});var numGlyphsOut=dupFirstEntry?numGlyphs+1:numGlyphs,isGlyphLocationsLong=itemSize*(1+numGlyphsOut),locaData=new Uint8Array(isGlyphLocationsLong),oldGlyfData=(locaData.set(loca.data.subarray(0,isGlyphLocationsLong)),loca.data=locaData,glyf.data),oldGlyfDataLength=oldGlyfData.length,newGlyfData=new Uint8Array(oldGlyfDataLength);let i,j;var locaEntries=[];for(i=0,j=0;ioldGlyfDataLength&&(offset=oldGlyfDataLength),locaEntries.push({index:i,offset:offset,endOffset:0})}for(locaEntries.sort((a,b)=>a.offset-b.offset),i=0;ia.index-b.index),i=0;i=source.length||sourceEnd>source.length||sourceEnd-sourceStart<=12)){var glyf=source.subarray(sourceStart,sourceEnd),source=signedInt16(glyf[2],glyf[3]),sourceStart=signedInt16(glyf[4],glyf[5]),sourceEnd=signedInt16(glyf[6],glyf[7]),yMax=signedInt16(glyf[8],glyf[9]),contoursCount=(sourceEndglyf.length||(!hintsValid&&0maxSizeOfInstructions&&(maxSizeOfInstructions=glyphProfile.sizeOfInstructions),writeOffset+=newLength,itemEncode(locaData,j,writeOffset)}if(0===writeOffset){var simpleGlyph=new Uint8Array([0,1,0,0,0,0,0,0,0,0,0,0,0,0,49,0]);for(i=0,j=itemSize;iisGlyphLocationsLong+writeOffset?glyf.data=newGlyfData.subarray(0,isGlyphLocationsLong+writeOffset):(glyf.data=new Uint8Array(isGlyphLocationsLong+writeOffset),glyf.data.set(newGlyfData.subarray(0,writeOffset))),glyf.data.set(newGlyfData.subarray(0,isGlyphLocationsLong),writeOffset),itemEncode(loca.data,locaData.length-itemSize,writeOffset+isGlyphLocationsLong)):glyf.data=newGlyfData.subarray(0,writeOffset);return{missingGlyphs:missingGlyphs,maxSizeOfInstructions:maxSizeOfInstructions}}function readNameTable(nameTable){var start=(font.start||0)+nameTable.offset,names=(font.pos=start,[[],[]]),records=[],nameTable=nameTable.length,end=start+nameTable,format=font.getUint16();if(!(0!==format||nameTable<6)){var numRecords=font.getUint16(),stringsStart=font.getUint16();let i,ii;for(i=0;iend)){font.pos=pos;pos=record.name;if(record.encoding){let str="";for(let j=0,jj=record.length;jdata.length&&content.push(new Uint8Array(i-data.length)),lastDeff>lastEndf&&(warn("TT: complementing a missing function tail"),content.push(new Uint8Array([34,45]))),function(table,content){if(1>8&255,metrics[1+j]=255&advanceWidth,Math.round(scaleFactors[i]*signedInt16(metrics[2+j],metrics[3+j])));writeSignedInt16(metrics,2+j,advanceWidth)}}let numGlyphsOut=numGlyphs+1,dupFirstEntry=!0,maxFunctionDefs=(65535>8,tables.maxp.data[5]=255&numGlyphsOut;glyphs=function(fpgm,prep,cvt,maxFunctionDefs){var ttContext={functionsDefined:[],functionsUsed:[],functionsStackDeltas:[],tooComplexToFollowFunctions:!1,hintsValid:!0};return fpgm&&sanitizeTTProgram(fpgm,ttContext),prep&&sanitizeTTProgram(prep,ttContext),fpgm&&function(ttContext,maxFunctionDefs){if(!ttContext.tooComplexToFollowFunctions)if(ttContext.functionsDefined.length>maxFunctionDefs)warn("TT: more functions defined than expected"),ttContext.hintsValid=!1;else for(let j=0,jj=ttContext.functionsUsed.length;jmaxFunctionDefs)return warn("TT: invalid function id: "+j),ttContext.hintsValid=!1;if(ttContext.functionsUsed[j]&&!ttContext.functionsDefined[j])return warn("TT: undefined function: "+j),ttContext.hintsValid=!1}}(ttContext,maxFunctionDefs),cvt&&1&cvt.length&&((prep=new Uint8Array(cvt.length+1)).set(cvt.data),cvt.data=prep),ttContext.hintsValid}(tables.fpgm,tables.prep,tables["cvt "],maxFunctionDefs);if(glyphs||(delete tables.fpgm,delete tables.prep,delete tables["cvt "]),!function(file,header,metrics,headTable,numGlyphs,dupFirstEntry){if(header){file.pos=(file.start||0)+header.offset,file.pos+=4,file.pos+=2,file.pos+=2,file.pos+=2,file.pos+=2,file.pos+=2,file.pos+=2,file.pos+=2,file.pos+=2,file.pos+=2;var caretOffset=file.getUint16();file.pos+=8,file.pos+=2;let numOfMetrics=file.getUint16();0===caretOffset||2&int16(headTable.data[44],headTable.data[45])||(header.data[22]=0,header.data[23]=0),numOfMetrics>numGlyphs&&(info(`The numOfMetrics (${numOfMetrics}) should not be `+`greater than the numGlyphs (${numGlyphs}).`),numOfMetrics=numGlyphs,header.data[34]=(65280&numOfMetrics)>>8,header.data[35]=255&numOfMetrics);file=numGlyphs-numOfMetrics-(metrics.length-4*numOfMetrics>>1);0>16!=1&&(info("Attempting to fix invalid version in head table: "+version),head[0]=0,head[1]=1,head[2]=0,head[3]=0),(version=int16(head[50],head[51]))<0||1>8,tables.maxp.data[27]=255&loca.maxSizeOfInstructions)}if(!tables.hhea)throw new FormatError('Required "hhea" table is not found');0===tables.hhea.data[10]&&0===tables.hhea.data[11]&&(tables.hhea.data[10]=255,tables.hhea.data[11]=255);isComposite={unitsPerEm:int16(tables.head.data[18],tables.head.data[19]),yMax:signedInt16(tables.head.data[42],tables.head.data[43]),yMin:signedInt16(tables.head.data[38],tables.head.data[39]),ascent:signedInt16(tables.hhea.data[4],tables.hhea.data[5]),descent:signedInt16(tables.hhea.data[6],tables.hhea.data[7]),lineGap:signedInt16(tables.hhea.data[8],tables.hhea.data[9])};this.ascent=isComposite.ascent/isComposite.unitsPerEm,this.descent=isComposite.descent/isComposite.unitsPerEm,this.lineGap=isComposite.lineGap/isComposite.unitsPerEm,this.cssFontInfo?.lineHeight?(this.lineHeight=this.cssFontInfo.metrics.lineHeight,this.lineGap=this.cssFontInfo.metrics.lineGap):this.lineHeight=this.ascent-this.descent+this.lineGap,tables.post&&function(post,propertiesObj,maxpNumGlyphs){var start=(font.start||0)+post.offset,post=(font.pos=start,post.length),end=start+post,version=font.getInt32();font.skip(28);let glyphNames,valid=!0,i;switch(version){case 65536:glyphNames=MacStandardGlyphOrdering;break;case 131072:var numGlyphs=font.getUint16();if(numGlyphs!==maxpNumGlyphs)valid=!1;else{var glyphNameIndexes=[];for(i=0;i>>0;let useTable=!1;if(potentialTable?.platformId!==platformId||potentialTable?.encodingId!==encodingId){if(0!==platformId||0!==encodingId&&1!==encodingId&&3!==encodingId)if(1===platformId&&0===encodingId)useTable=!0;else if(3!==platformId||1!==encodingId||!hasEncoding&&potentialTable){if(isSymbolicFont&&3===platformId&&0===encodingId){let correctlySorted=useTable=!0;(correctlySorted=i>3;subHeaderKeys.push(subHeaderKey),maxSubHeaderKey=Math.max(subHeaderKey,maxSubHeaderKey)}var subHeaders=[];for(let i=0;i<=maxSubHeaderKey;i++)subHeaders.push({firstCode:file.getUint16(),entryCount:file.getUint16(),idDelta:signedInt16(file.getByte(),file.getByte()),idRangePos:file.pos+file.getUint16()});for(let i=0;i<256;i++)if(0===subHeaderKeys[i])file.pos=subHeaders[0].idRangePos+2*i,glyphId=file.getUint16(),mappings.push({charCode:i,glyphId:glyphId});else{var s=subHeaders[subHeaderKeys[i]];for(j=0;j>1,segments=(file.skip(6),[]);let segIndex;for(segIndex=0;segIndex>1)-(segCount-segIndex),segment.offsetIndex=offsetIndex,offsetsCount=Math.max(offsetsCount,offsetIndex+segment.end-segment.start+1)):segment.offsetIndex=-1}var offsets=[];for(j=0;j>>0;for(j=0;j>>0,endCharCode=file.getInt32()>>>0;let glyphCode=file.getInt32()>>>0;for(let charCode=startCharCode;charCode<=endCharCode;charCode++)mappings.push({charCode:charCode,glyphId:glyphCode++})}}mappings.sort(function(a,b){return a.charCode-b.charCode});for(let i=1;ithis.toUnicode.charCodeOf(unicode):unicode=>this.toUnicode.charCodeOf(String.fromCodePoint(unicode));for(let i=0,ii=str.length;i>8*j&255));continue}}buffers.length%2!=1&&(buffers.push(currentBuf.join("")),currentBuf.length=0),currentBuf.push(String.fromCodePoint(unicode))}return buffers.push(currentBuf.join("")),buffers}}class ErrorFont{constructor(error){this.error=error,this.loadedName="g_font_error",this.missingFile=!0}charsToGlyphs(){return[]}encodeString(chars){return[chars]}exportData(extraProperties=0){return{error:this.error}}}const ShadingType={FUNCTION_BASED:1,AXIAL:2,RADIAL:3,FREE_FORM_MESH:4,LATTICE_FORM_MESH:5,COONS_PATCH_MESH:6,TENSOR_PATCH_MESH:7};class Pattern{constructor(){unreachable("Cannot initialize Pattern.")}static parseShading(shading,xref,res,pdfFunctionFactory,localColorSpaceCache){var dict=shading instanceof BaseStream?shading.dict:shading,type=dict.get("ShadingType");try{switch(type){case ShadingType.AXIAL:case ShadingType.RADIAL:return new RadialAxialShading(dict,xref,res,pdfFunctionFactory,localColorSpaceCache);case ShadingType.FREE_FORM_MESH:case ShadingType.LATTICE_FORM_MESH:case ShadingType.COONS_PATCH_MESH:case ShadingType.TENSOR_PATCH_MESH:return new MeshShading(shading,xref,res,pdfFunctionFactory,localColorSpaceCache);default:throw new FormatError("Unsupported ShadingType: "+type)}}catch(ex){if(ex instanceof MissingDataException)throw ex;return warn(ex),new DummyShading}}}class BaseShading{static SMALL_NUMBER=1e-6;constructor(){this.constructor===BaseShading&&unreachable("Cannot initialize BaseShading.")}getIR(){unreachable("Abstract method `getIR` called.")}}class RadialAxialShading extends BaseShading{constructor(dict,xref,resources,pdfFunctionFactory,localColorSpaceCache){super(),this.coordsArr=dict.getArray("Coords"),this.shadingType=dict.get("ShadingType");var y2,r2,cs=ColorSpace.parse({cs:dict.getRaw("CS")||dict.getRaw("ColorSpace"),xref:xref,resources:resources,pdfFunctionFactory:pdfFunctionFactory,localColorSpaceCache:localColorSpaceCache}),xref=dict.getArray("BBox");this.bbox=Array.isArray(xref)&&4===xref.length?Util.normalizeRect(xref):null;let t0=0,t1=1,extendStart=(dict.has("Domain")&&(resources=dict.getArray("Domain"),t0=resources[0],t1=resources[1]),!1),extendEnd=!1;dict.has("Extend")&&(localColorSpaceCache=dict.getArray("Extend"),extendStart=localColorSpaceCache[0],extendEnd=localColorSpaceCache[1]),this.shadingType!==ShadingType.RADIAL||extendStart&&extendEnd||([xref,resources,localColorSpaceCache,x2,y2,r2]=this.coordsArr,localColorSpaceCache<=r2+(xref=Math.hypot(xref-x2,resources-y2))&&r2<=localColorSpaceCache+xref&&warn("Unsupported radial gradient.")),this.extendStart=extendStart,this.extendEnd=extendEnd;var x2=dict.getRaw("Function"),fn=pdfFunctionFactory.createFromArray(x2),step=(t1-t0)/840,colorStops=this.colorStops=[];if(t0>=t1||step<=0)info("Bad shading domain.");else{var color=new Float32Array(cs.numComps),ratio=new Float32Array(1);let rgbColor,iBase=0,rgbBase=(ratio[0]=t0,fn(ratio,0,color,0),cs.getRgb(color,0));resources=Util.makeHexColor(rgbBase[0],rgbBase[1],rgbBase[2]);colorStops.push([0,resources]);let iPrev=1,rgbPrev=(ratio[0]=t0+step,fn(ratio,0,color,0),cs.getRgb(color,0)),maxSlopeR=rgbPrev[0]-rgbBase[0]+1,maxSlopeG=rgbPrev[1]-rgbBase[1]+1,maxSlopeB=rgbPrev[2]-rgbBase[2]+1,minSlopeR=rgbPrev[0]-rgbBase[0]-1,minSlopeG=rgbPrev[1]-rgbBase[1]-1,minSlopeB=rgbPrev[2]-rgbBase[2]-1;for(let i=2;i<840;i++){ratio[0]=t0+i*step,fn(ratio,0,color,0),rgbColor=cs.getRgb(color,0);var run=i-iBase,run=(maxSlopeR=Math.min(maxSlopeR,(rgbColor[0]-rgbBase[0]+1)/run),maxSlopeG=Math.min(maxSlopeG,(rgbColor[1]-rgbBase[1]+1)/run),maxSlopeB=Math.min(maxSlopeB,(rgbColor[2]-rgbBase[2]+1)/run),minSlopeR=Math.max(minSlopeR,(rgbColor[0]-rgbBase[0]-1)/run),minSlopeG=Math.max(minSlopeG,(rgbColor[1]-rgbBase[1]-1)/run),minSlopeB=Math.max(minSlopeB,(rgbColor[2]-rgbBase[2]-1)/run),minSlopeR<=maxSlopeR&&minSlopeG<=maxSlopeG&&minSlopeB<=maxSlopeB);if(!run){const cssColor=Util.makeHexColor(rgbPrev[0],rgbPrev[1],rgbPrev[2]);colorStops.push([iPrev/840,cssColor]),maxSlopeR=rgbColor[0]-rgbPrev[0]+1,maxSlopeG=rgbColor[1]-rgbPrev[1]+1,maxSlopeB=rgbColor[2]-rgbPrev[2]+1,minSlopeR=rgbColor[0]-rgbPrev[0]-1,minSlopeG=rgbColor[1]-rgbPrev[1]-1,minSlopeB=rgbColor[2]-rgbPrev[2]-1,iBase=iPrev,rgbBase=rgbPrev}iPrev=i,rgbPrev=rgbColor}const cssColor=Util.makeHexColor(rgbPrev[0],rgbPrev[1],rgbPrev[2]);colorStops.push([1,cssColor]);let background="transparent";dict.has("Background")&&(rgbColor=cs.getRgb(dict.get("Background"),0),background=Util.makeHexColor(rgbColor[0],rgbColor[1],rgbColor[2])),extendStart||(colorStops.unshift([0,background]),colorStops[1][0]+=BaseShading.SMALL_NUMBER),extendEnd||(colorStops.at(-1)[0]-=BaseShading.SMALL_NUMBER,colorStops.push([1,background])),this.colorStops=colorStops}}getIR(){var coordsArr=this.coordsArr,shadingType=this.shadingType;let type,p0,p1,r0,r1;return shadingType===ShadingType.AXIAL?(p0=[coordsArr[0],coordsArr[1]],p1=[coordsArr[2],coordsArr[3]],r0=null,r1=null,type="axial"):shadingType===ShadingType.RADIAL?(p0=[coordsArr[0],coordsArr[1]],p1=[coordsArr[3],coordsArr[4]],r0=coordsArr[2],r1=coordsArr[5],type="radial"):unreachable("getPattern type unknown: "+shadingType),["RadialAxial",type,this.bbox,this.colorStops,p0,p1,r0,r1]}}class MeshStreamReader{constructor(stream,context){this.stream=stream,this.context=context,this.buffer=0,this.bufferLength=0;stream=context.numComps,this.tmpCompsBuf=new Float32Array(stream),stream=context.colorSpace.numComps;this.tmpCsCompsBuf=context.colorFn?new Float32Array(stream):this.tmpCompsBuf}get hasData(){if(this.stream.end)return this.stream.pos>>0;buffer=buffer<<24|this.stream.getByte()<<16|this.stream.getByte()<<8|this.stream.getByte();var nextByte=this.stream.getByte();return this.buffer=nextByte&(1<>bufferLength)>>>0}if(8===n&&0===bufferLength)return this.stream.getByte();for(;bufferLength>bufferLength}align(){this.buffer=0,this.bufferLength=0}readFlag(){return this.readBits(this.context.bitsPerFlag)}readCoordinate(){var bitsPerCoordinate=this.context.bitsPerCoordinate,xi=this.readBits(bitsPerCoordinate),yi=this.readBits(bitsPerCoordinate),decode=this.context.decode,bitsPerCoordinate=bitsPerCoordinate<32?1/((1<x?x:minX,minY=minY>y?y:minY,maxX=maxXw*factors[i]):baseWidths;let currentCode=-2,currentArray;var unicode,glyphIndex,newWidths=[];for([unicode,glyphIndex]of baseMapping.map((charUnicode,index)=>[charUnicode,index]).sort(([unicode1],[unicode2])=>unicode1-unicode2))-1!==unicode&&(unicode===currentCode+1?(currentArray.push(rescaledBaseWidths[glyphIndex]),currentCode+=1):(currentCode=unicode,currentArray=[rescaledBaseWidths[glyphIndex]],newWidths.push(unicode,currentArray)));return newWidths}function getXfaFontDict(name){var widths=getXfaFontWidths(name),dict=new Dict(null),name=(dict.set("BaseFont",Name.get(name)),dict.set("Type",Name.get("Font")),dict.set("Subtype",Name.get("CIDFontType2")),dict.set("Encoding",Name.get("Identity-H")),dict.set("CIDToGIDMap",Name.get("Identity")),dict.set("W",widths),dict.set("FirstChar",widths[0]),dict.set("LastChar",widths.at(-2)+widths.at(-1).length-1),new Dict(null)),widths=(dict.set("FontDescriptor",name),new Dict(null));return widths.set("Ordering","Identity"),widths.set("Registry","Adobe"),widths.set("Supplement",0),dict.set("CIDSystemInfo",widths),dict}class PostScriptParser{constructor(lexer){this.lexer=lexer,this.operators=[],this.token=null,this.prev=null}nextToken(){this.prev=this.token,this.token=this.lexer.getToken()}accept(type){return this.token.type===type&&(this.nextToken(),!0)}expect(type){if(this.accept(type))return!0;throw new FormatError(`Unexpected symbol: found ${this.token.type} expected ${type}.`)}parse(){return this.nextToken(),this.expect(PostScriptTokenTypes.LBRACE),this.parseBlock(),this.expect(PostScriptTokenTypes.RBRACE),this.operators}parseBlock(){for(;;)if(this.accept(PostScriptTokenTypes.NUMBER))this.operators.push(this.prev.value);else if(this.accept(PostScriptTokenTypes.OPERATOR))this.operators.push(this.prev.value);else{if(!this.accept(PostScriptTokenTypes.LBRACE))return;this.parseCondition()}}parseCondition(){var conditionLocation=this.operators.length;if(this.operators.push(null,null),this.parseBlock(),this.expect(PostScriptTokenTypes.RBRACE),this.accept(PostScriptTokenTypes.IF))this.operators[conditionLocation]=this.operators.length;else{if(!this.accept(PostScriptTokenTypes.LBRACE))throw new FormatError("PS Function: error parsing conditional.");var jumpLocation=this.operators.length,endOfTrue=(this.operators.push(null,null),this.operators.length);this.parseBlock(),this.expect(PostScriptTokenTypes.RBRACE),this.expect(PostScriptTokenTypes.IFELSE),this.operators[jumpLocation]=this.operators.length,this.operators[jumpLocation+1]="j",this.operators[conditionLocation]=endOfTrue}this.operators[conditionLocation+1]="jz"}}const PostScriptTokenTypes={LBRACE:0,RBRACE:1,NUMBER:2,OPERATOR:3,IF:4,IFELSE:5};class PostScriptToken{static get opCache(){return shadow(this,"opCache",Object.create(null))}constructor(type,value){this.type=type,this.value=value}static getOperator(op){return PostScriptToken.opCache[op]||=new PostScriptToken(PostScriptTokenTypes.OPERATOR,op)}static get LBRACE(){return shadow(this,"LBRACE",new PostScriptToken(PostScriptTokenTypes.LBRACE,"{"))}static get RBRACE(){return shadow(this,"RBRACE",new PostScriptToken(PostScriptTokenTypes.RBRACE,"}"))}static get IF(){return shadow(this,"IF",new PostScriptToken(PostScriptTokenTypes.IF,"IF"))}static get IFELSE(){return shadow(this,"IFELSE",new PostScriptToken(PostScriptTokenTypes.IFELSE,"IFELSE"))}}class PostScriptLexer{constructor(stream){this.stream=stream,this.nextChar(),this.strBuf=[]}nextChar(){return this.currentChar=this.stream.getByte()}getToken(){let comment=!1,ch=this.currentChar;for(;;){if(ch<0)return EOF;if(comment)10!==ch&&13!==ch||(comment=!1);else if(37===ch)comment=!0;else if(!isWhiteSpace(ch))break;ch=this.nextChar()}switch(0|ch){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:case 43:case 45:case 46:return new PostScriptToken(PostScriptTokenTypes.NUMBER,this.getNumber());case 123:return this.nextChar(),PostScriptToken.LBRACE;case 125:return this.nextChar(),PostScriptToken.RBRACE}var strBuf=this.strBuf;for(strBuf.length=0,strBuf[0]=String.fromCharCode(ch);0<=(ch=this.nextChar())&&(65<=ch&&ch<=90||97<=ch&&ch<=122);)strBuf.push(String.fromCharCode(ch));var str=strBuf.join("");switch(str.toLowerCase()){case"if":return PostScriptToken.IF;case"ifelse":return PostScriptToken.IFELSE;default:return PostScriptToken.getOperator(str)}}getNumber(){var ch=this.currentChar,strBuf=this.strBuf;for(strBuf.length=0,strBuf[0]=String.fromCharCode(ch);0<=(ch=this.nextChar())&&(48<=ch&&ch<=57||45===ch||46===ch);)strBuf.push(String.fromCharCode(ch));var value=parseFloat(strBuf.join(""));if(isNaN(value))throw new FormatError("Invalid floating point number: "+value);return value}}class BaseLocalCache{constructor(options){this.constructor===BaseLocalCache&&unreachable("Cannot initialize BaseLocalCache."),this._onlyRefs=!0===options?.onlyRefs,this._onlyRefs||(this._nameRefMap=new Map,this._imageMap=new Map),this._imageCache=new RefSetCache}getByName(name){this._onlyRefs&&unreachable("Should not call `getByName` method.");var ref=this._nameRefMap.get(name);return ref?this.getByRef(ref):this._imageMap.get(name)||null}getByRef(ref){return this._imageCache.get(ref)||null}set(name,ref,data){unreachable("Abstract method `set` called.")}}class LocalImageCache extends BaseLocalCache{set(name,ref=null,data){if("string"!=typeof name)throw new Error('LocalImageCache.set - expected "name" argument.');if(ref)return this._imageCache.has(ref)?void 0:(this._nameRefMap.set(name,ref),void this._imageCache.put(ref,data));this._imageMap.has(name)||this._imageMap.set(name,data)}}class LocalColorSpaceCache extends BaseLocalCache{set(name=null,ref=null,data){if("string"!=typeof name&&!ref)throw new Error('LocalColorSpaceCache.set - expected "name" and/or "ref" argument.');if(ref)return this._imageCache.has(ref)?void 0:(null!==name&&this._nameRefMap.set(name,ref),void this._imageCache.put(ref,data));this._imageMap.has(name)||this._imageMap.set(name,data)}}class LocalFunctionCache extends BaseLocalCache{constructor(options){super({onlyRefs:!0})}set(name=0,ref,data){if(!ref)throw new Error('LocalFunctionCache.set - expected "ref" argument.');this._imageCache.has(ref)||this._imageCache.put(ref,data)}}class LocalGStateCache extends BaseLocalCache{set(name,ref=null,data){if("string"!=typeof name)throw new Error('LocalGStateCache.set - expected "name" argument.');if(ref)return this._imageCache.has(ref)?void 0:(this._nameRefMap.set(name,ref),void this._imageCache.put(ref,data));this._imageMap.has(name)||this._imageMap.set(name,data)}}class LocalTilingPatternCache extends BaseLocalCache{constructor(options){super({onlyRefs:!0})}set(name=0,ref,data){if(!ref)throw new Error('LocalTilingPatternCache.set - expected "ref" argument.');this._imageCache.has(ref)||this._imageCache.put(ref,data)}}class RegionalImageCache extends BaseLocalCache{constructor(options){super({onlyRefs:!0})}set(name=0,ref,data){if(!ref)throw new Error('RegionalImageCache.set - expected "ref" argument.');this._imageCache.has(ref)||this._imageCache.put(ref,data)}}class GlobalImageCache{static NUM_PAGES_THRESHOLD=2;static MIN_IMAGES_TO_CACHE=10;static MAX_BYTE_SIZE=5*MAX_IMAGE_SIZE_TO_CACHE;constructor(){this._refCache=new RefSetCache,this._imageCache=new RefSetCache}get _byteSize(){let byteSize=0;for(const imageData of this._imageCache)byteSize+=imageData.byteSize;return byteSize}get _cacheLimitReached(){return!(this._imageCache.size+x):null}class PDFFunction{static getSampleArray(size,outputSize,bps,stream){let i,ii,length=1;for(i=0,ii=size.length;i>codeSize)*sampleMul,codeBuf&=(1<>1,numInputs=domain.length>>1,evaluator=new PostScriptEvaluator(fn),cache=Object.create(null);let cache_available=8192;const tmpBuf=new Float32Array(numInputs);return function(src,srcOffset,dest,destOffset){let i,value,key="";var input=tmpBuf;for(i=0;ibound))&&(value=bound),output[i]=value}0=PostScriptStack.MAX_STACK_SIZE)throw new Error("PostScript function stack overflow.");this.stack.push(value)}pop(){if(this.stack.length<=0)throw new Error("PostScript function stack underflow.");return this.stack.pop()}copy(n){if(this.stack.length+n>=PostScriptStack.MAX_STACK_SIZE)throw new Error("PostScript function stack overflow.");var stack=this.stack;for(let i=stack.length-n,j=n-1;0<=j;j--,i++)stack.push(stack[i])}index(n){this.push(this.stack[this.stack.length-n-1])}roll(n,p){var stack=this.stack,l=stack.length-n,r=stack.length-1,p=l+(p-Math.floor(p/n)*n);for(let i=l,j=r;i>b);break;case"ceiling":a=stack.pop(),stack.push(Math.ceil(a));break;case"copy":a=stack.pop(),stack.copy(a);break;case"cos":a=stack.pop(),stack.push(Math.cos(a%360/180*Math.PI));break;case"cvi":a=0|stack.pop(),stack.push(a);break;case"cvr":break;case"div":b=stack.pop(),a=stack.pop(),stack.push(a/b);break;case"dup":stack.copy(1);break;case"eq":b=stack.pop(),a=stack.pop(),stack.push(a===b);break;case"exch":stack.roll(2,1);break;case"exp":b=stack.pop(),a=stack.pop(),stack.push(a**b);break;case"false":stack.push(!1);break;case"floor":a=stack.pop(),stack.push(Math.floor(a));break;case"ge":b=stack.pop(),a=stack.pop(),stack.push(a>=b);break;case"gt":b=stack.pop(),a=stack.pop(),stack.push(a>b);break;case"idiv":b=stack.pop(),a=stack.pop(),stack.push(a/b|0);break;case"index":a=stack.pop(),stack.index(a);break;case"le":b=stack.pop(),a=stack.pop(),stack.push(a<=b);break;case"ln":a=stack.pop(),stack.push(Math.log(a));break;case"log":a=stack.pop(),stack.push(Math.log10(a));break;case"lt":b=stack.pop(),a=stack.pop(),stack.push(a=max?new AstLiteral(max):num1.max<=max?num1:new AstMin(num1,max)}class PostScriptCompiler{compile(code,domain,range){var stack=[],instructions=[],inputSize=domain.length>>1,outputSize=range.length>>1;let lastRegister=0,n,j,num1,num2,ast1,ast2,tmpVar,item;for(let i=0;iexpr.min&&(out.unshift("Math.max(",min,", "),out.push(")")),maxlevel&&isOdd(level)&&(lowestOddLevel=level);for(level=highestLevel;level>=lowestOddLevel;--level){let start=-1;for(i=0,ii=levels.length;i"!==ch||(chars[i]="")}return createBidiText(chars.join(""),isLTR)}const NORMAL={style:"normal",weight:"normal"},BOLD={style:"normal",weight:"bold"},ITALIC={style:"italic",weight:"normal"},BOLDITALIC={style:"italic",weight:"bold"},substitutionMap=new Map([["Times-Roman",{local:["Times New Roman","Times-Roman","Times","Liberation Serif","Nimbus Roman","Nimbus Roman L","Tinos","Thorndale","TeX Gyre Termes","FreeSerif","Linux Libertine O","Libertinus Serif","DejaVu Serif","Bitstream Vera Serif","Ubuntu"],style:NORMAL,ultimate:"serif"}],["Times-Bold",{alias:"Times-Roman",style:BOLD,ultimate:"serif"}],["Times-Italic",{alias:"Times-Roman",style:ITALIC,ultimate:"serif"}],["Times-BoldItalic",{alias:"Times-Roman",style:BOLDITALIC,ultimate:"serif"}],["Helvetica",{local:["Helvetica","Helvetica Neue","Arial","Arial Nova","Liberation Sans","Arimo","Nimbus Sans","Nimbus Sans L","A030","TeX Gyre Heros","FreeSans","DejaVu Sans","Albany","Bitstream Vera Sans","Arial Unicode MS","Microsoft Sans Serif","Apple Symbols","Cantarell"],path:"LiberationSans-Regular.ttf",style:NORMAL,ultimate:"sans-serif"}],["Helvetica-Bold",{alias:"Helvetica",path:"LiberationSans-Bold.ttf",style:BOLD,ultimate:"sans-serif"}],["Helvetica-Oblique",{alias:"Helvetica",path:"LiberationSans-Italic.ttf",style:ITALIC,ultimate:"sans-serif"}],["Helvetica-BoldOblique",{alias:"Helvetica",path:"LiberationSans-BoldItalic.ttf",style:BOLDITALIC,ultimate:"sans-serif"}],["Courier",{local:["Courier","Courier New","Liberation Mono","Nimbus Mono","Nimbus Mono L","Cousine","Cumberland","TeX Gyre Cursor","FreeMono","Linux Libertine Mono O","Libertinus Mono"],style:NORMAL,ultimate:"monospace"}],["Courier-Bold",{alias:"Courier",style:BOLD,ultimate:"monospace"}],["Courier-Oblique",{alias:"Courier",style:ITALIC,ultimate:"monospace"}],["Courier-BoldOblique",{alias:"Courier",style:BOLDITALIC,ultimate:"monospace"}],["ArialBlack",{local:["Arial Black"],style:{style:"normal",weight:"900"},fallback:"Helvetica-Bold"}],["ArialBlack-Bold",{alias:"ArialBlack"}],["ArialBlack-Italic",{alias:"ArialBlack",style:{style:"italic",weight:"900"},fallback:"Helvetica-BoldOblique"}],["ArialBlack-BoldItalic",{alias:"ArialBlack-Italic"}],["ArialNarrow",{local:["Arial Narrow","Liberation Sans Narrow","Helvetica Condensed","Nimbus Sans Narrow","TeX Gyre Heros Cn"],style:NORMAL,fallback:"Helvetica"}],["ArialNarrow-Bold",{alias:"ArialNarrow",style:BOLD,fallback:"Helvetica-Bold"}],["ArialNarrow-Italic",{alias:"ArialNarrow",style:ITALIC,fallback:"Helvetica-Oblique"}],["ArialNarrow-BoldItalic",{alias:"ArialNarrow",style:BOLDITALIC,fallback:"Helvetica-BoldOblique"}],["Calibri",{local:["Calibri","Carlito"],style:NORMAL,fallback:"Helvetica"}],["Calibri-Bold",{alias:"Calibri",style:BOLD,fallback:"Helvetica-Bold"}],["Calibri-Italic",{alias:"Calibri",style:ITALIC,fallback:"Helvetica-Oblique"}],["Calibri-BoldItalic",{alias:"Calibri",style:BOLDITALIC,fallback:"Helvetica-BoldOblique"}],["Wingdings",{local:["Wingdings","URW Dingbats"],style:NORMAL}],["Wingdings-Regular",{alias:"Wingdings"}],["Wingdings-Bold",{alias:"Wingdings"}]]),fontAliases=new Map([["Arial-Black","ArialBlack"]]);function getStyleToAppend(style){switch(style){case BOLD:return"Bold";case ITALIC:return"Italic";case BOLDITALIC:return"Bold Italic";default:if("bold"===style?.weight)return"Bold";if("italic"===style?.style)return"Italic"}return""}function getFamilyName(str){const keywords=new Set(["thin","extralight","ultralight","demilight","semilight","light","book","regular","normal","medium","demibold","semibold","bold","extrabold","ultrabold","black","heavy","extrablack","ultrablack","roman","italic","oblique","ultracondensed","extracondensed","condensed","semicondensed","normal","semiexpanded","expanded","extraexpanded","ultraexpanded","bolditalic"]);return str.split(/[- ,+]+/g).filter(tok=>!keywords.has(tok.toLowerCase())).join(" ")}function generateFont({alias,local,path,fallback,style,ultimate},src,localFontPath,useFallback=!0,usePath=!0,append=""){var result={style:null,ultimate:null};if(local){var extra=append?" "+append:"";for(const name of local)src.push(`local(${name}${extra})`)}return alias&&(local=substitutionMap.get(alias),alias=append||getStyleToAppend(style),Object.assign(result,generateFont(local,src,localFontPath,useFallback&&!fallback,usePath&&!path,alias))),style&&(result.style=style),ultimate&&(result.ultimate=ultimate),useFallback&&fallback&&(local=generateFont(substitutionMap.get(fallback),src,localFontPath,useFallback,usePath&&!path,append)["ultimate"],result.ultimate||=local),usePath&&path&&localFontPath&&src.push(`url(${localFontPath}${path})`),result}function getFontSubstitution(systemFontCache,idFactory,localFontPath,baseFontName,standardFontName,type){if(baseFontName.startsWith("InvalidPDFjsFont_"))return null;type=baseFontName=normalizeFontName(baseFontName="TrueType"!==type&&"Type1"!==type||!/^[A-Z]{6}\+/.test(baseFontName)?baseFontName:baseFontName.slice(7));let substitutionInfo=systemFontCache.get(type);if(!substitutionInfo){let substitution=substitutionMap.get(baseFontName);if(!substitution)for(var[alias,subst]of fontAliases)if(baseFontName.startsWith(alias)){baseFontName=""+subst+baseFontName.substring(alias.length),substitution=substitutionMap.get(baseFontName);break}let mustAddBaseFont=!1;substitution||(substitution=substitutionMap.get(standardFontName),mustAddBaseFont=!0);standardFontName=idFactory.getDocId()+"_s"+idFactory.createFontId();if(substitution){idFactory=[];mustAddBaseFont&&validateFontName(baseFontName)&&idFactory.push(`local(${baseFontName})`);const{style,ultimate}=generateFont(substitution,idFactory,localFontPath);var localFontPath=null===ultimate,fallback=localFontPath?"":","+ultimate;substitutionInfo={css:`"${getFamilyName(baseFontName)}",`+standardFontName+fallback,guessFallback:localFontPath,loadedName:standardFontName,baseFontName:baseFontName,src:idFactory.join(","),style:style}}else{if(!validateFontName(baseFontName))return warn("Cannot substitute the font because of its name: "+baseFontName),systemFontCache.set(type,null),null;fallback=/bold/gi.test(baseFontName),localFontPath=/oblique|italic/gi.test(baseFontName);const style=fallback&&localFontPath&&BOLDITALIC||fallback&&BOLD||localFontPath&&ITALIC||NORMAL;substitutionInfo={css:`"${getFamilyName(baseFontName)}",`+standardFontName,guessFallback:!0,loadedName:standardFontName,baseFontName:baseFontName,src:`local(${baseFontName})`,style:style}}systemFontCache.set(type,substitutionInfo)}return substitutionInfo}const MIN_IMAGE_DIM=2048,MAX_IMAGE_DIM=65537,MAX_ERROR=128;class ImageResizer{constructor(imgData,isMask){this._imgData=imgData,this._isMask=isMask}static needsToBeResized(width,height){var MAX_DIM,area;return!(width<=this._goodSquareLength&&height<=this._goodSquareLength)&&(MAX_DIM=this["MAX_DIM"],MAX_DIMthis.MAX_AREA:!(area>2)}static _areGoodDims(width,height){try{var canvas=new OffscreenCanvas(width,height),ctx=canvas.getContext("2d"),opacity=(ctx.fillRect(0,0,1,1),ctx.getImageData(0,0,1,1).data[3]);return canvas.width=canvas.height=1,0!==opacity}catch{return!1}}static _guessMax(start,end,tolerance,defaultHeight){for(;start+tolerance+1>3,rowSize=3+rowLen&-4;if(rowLen!=rowSize){var newData=new Uint8Array(rowSize*height);let k=0;for(let i=0,ii=height*rowLen;i>>8,data[length++]=255&code)}}else{if(!ArrayBuffer.isView(input))throw new Error("Invalid data format, must be a string or TypedArray.");data=input.slice(),length=data.byteLength}var blockCounts=length>>2,tailLength=length-4*blockCounts,dataUint32=new Uint32Array(data.buffer,0,blockCounts);let k1=0,k2,h1=this.h1,h2=this.h2;var C1=3432918353,C2=461845907,C1_LOW=C1&MASK_LOW,C2_LOW=C2&MASK_LOW;for(let i=0;i>>17)*C2&MASK_HIGH|k1*C2_LOW&MASK_LOW,h1=5*(h1=(h1^=k1)<<13|h1>>>19)+3864292196):(k2=(k2=(k2=(k2=dataUint32[i])*C1&MASK_HIGH|k2*C1_LOW&MASK_LOW)<<15|k2>>>17)*C2&MASK_HIGH|k2*C2_LOW&MASK_LOW,h2=5*(h2=(h2^=k2)<<13|h2>>>19)+3864292196);switch(k1=0,tailLength){case 3:k1^=data[4*blockCounts+2]<<16;case 2:k1^=data[4*blockCounts+1]<<8;case 1:k1=(k1=(k1=(k1^=data[4*blockCounts])*C1&MASK_HIGH|k1*C1_LOW&MASK_LOW)<<15|k1>>>17)*C2&MASK_HIGH|k1*C2_LOW&MASK_LOW,1&blockCounts?h1^=k1:h2^=k1}this.h1=h1,this.h2=h2}hexdigest(){var h1=this.h1,h2=this.h2,h1=3981806797*(h1^=h2>>>1)&MASK_HIGH|36045*h1&MASK_LOW;return h1=444984403*(h1^=(h2=4283543511*h2&MASK_HIGH|(2950163797*(h2<<16|h1>>>16)&MASK_HIGH)>>>16)>>>1)&MASK_HIGH|60499*h1&MASK_LOW,((h1^=(h2=3301882366*h2&MASK_HIGH|(3120437893*(h2<<16|h1>>>16)&MASK_HIGH)>>>16)>>>1)>>>0).toString(16).padStart(8,"0")+(h2>>>0).toString(16).padStart(8,"0")}}function addState(parentState,pattern,checkFn,iterateFn,processFn){let state=parentState;for(let i=0,ii=pattern.length-1;i=ii)break}!(state=(state||InitialState)[fnArray[i]])||Array.isArray(state)?i++:(context.iCurr=i,i++,state=(state.checkFn&&!(0,state.checkFn)(context)||(match=state),null))}this.state=state,this.match=match,this.lastProcessed=i}else this.lastProcessed=ii}flush(){for(;this.match;){var length=this.queue.fnArray.length;this.lastProcessed=(0,this.match.processFn)(this.context,length),this.match=null,this.state=null,this._optimize()}}reset(){this.state=null,this.match=null,this.lastProcessed=0}}class OperatorList{static CHUNK_SIZE=1e3;static CHUNK_SIZE_ABOUT=this.CHUNK_SIZE-5;constructor(intent=0,streamSink){this._streamSink=streamSink,this.fnArray=[],this.argsArray=[],this.optimizer=new(!streamSink||intent&RenderingIntentFlag.OPLIST?NullOptimizer:QueueOptimizer)(this),this.dependencies=new Set,this._totalLength=0,this.weight=0,this._resolved=streamSink?null:Promise.resolve()}set isOffscreenCanvasSupported(value){this.optimizer.isOffscreenCanvasSupported=value}get length(){return this.argsArray.length}get ready(){return this._resolved||this._streamSink.ready}get totalLength(){return this._totalLength+this.length}addOp(fn,args){this.optimizer.push(fn,args),this.weight++,this._streamSink&&(this.weight>=OperatorList.CHUNK_SIZE||this.weight>=OperatorList.CHUNK_SIZE_ABOUT&&(fn===OPS.restore||fn===OPS.endText))&&this.flush()}addImageOps(fn,args,optionalContent){void 0!==optionalContent&&this.addOp(OPS.beginMarkedContentProps,["OC",optionalContent]),this.addOp(fn,args),void 0!==optionalContent&&this.addOp(OPS.endMarkedContent,[])}addDependency(dependency){this.dependencies.has(dependency)||(this.dependencies.add(dependency),this.addOp(OPS.dependency,[dependency]))}addDependencies(dependencies){for(const dependency of dependencies)this.addDependency(dependency)}addOpList(opList){if(opList instanceof OperatorList){for(const dependency of opList.dependencies)this.dependencies.add(dependency);for(let i=0,ii=opList.length;i>3)*height,actualLength=imgArray.byteLength;let data,i;if(!imageIsFromDecodeStream||inverseDecode&&!(computedLength===actualLength)?inverseDecode?((data=new Uint8Array(computedLength)).set(imgArray),data.fill(255,actualLength)):data=new Uint8Array(imgArray):data=imgArray,inverseDecode)for(i=0;i>7&1,output[i+1]=buf>>6&1,output[i+2]=buf>>5&1,output[i+3]=buf>>4&1,output[i+4]=buf>>3&1,output[i+5]=buf>>2&1,output[i+6]=buf>>1&1,output[i+7]=1&buf,i+=8;if(i>=1}}else{let bits=0;for(buf=0,i=0,ii=length;i>remainingBits;value<0?value=0:value>max&&(value=max),output[i]=value,buf&=(1<mask[1+maskOffset]){opacity=255;break}}alphaBuf[i]=opacity}}if(alphaBuf)for(i=0,j=3,ii=width*actualHeight;i>3,mustBeResized=isOffscreenCanvasSupported&&ImageResizer.needsToBeResized(drawWidth,drawHeight);if(!forceRGBA){let kind;if("DeviceGray"===this.colorSpace.name&&1===bpc?kind=ImageKind.GRAYSCALE_1BPP:"DeviceRGB"!==this.colorSpace.name||8!==bpc||this.needsDecode||(kind=ImageKind.RGB_24BPP),kind&&!this.smask&&!this.mask&&drawWidth===originalWidth&&drawHeight===originalHeight){const data=this.getImageBytes(originalHeight*numComps,{});if(isOffscreenCanvasSupported)return mustBeResized?ImageResizer.createImage({data:data,kind:kind,width:drawWidth,height:drawHeight,interpolate:this.interpolate},this.needsDecode):this.createBitmap(kind,originalWidth,originalHeight,data);if(imgData.kind=kind,imgData.data=data,this.needsDecode){assert(kind===ImageKind.GRAYSCALE_1BPP,"PDFImage.createImageData: The image must be grayscale.");var buffer=imgData.data;for(let i=0,ii=buffer.length;i>3),{internal:!0}),comps=this.getComponents(numComps);let i,length;if(1===bpc)if(length=width*height,this.needsDecode)for(i=0;i>3)*h),decode=dict.getArray("D","Decode");if(this.parsingType3Font)return(imgData=PDFImage.createRawMask({imgArray:imgArray,width:w,height:h,imageIsFromDecodeStream:image instanceof DecodeStream,inverseDecode:0((imgData=await imageObj.createImageData(!1,this.options.isOffscreenCanvasSupported)).dataLen=imgData.bitmap?imgData.width*imgData.height*4:imgData.data.length,imgData.ref=imageRef,cacheGlobally&&this.globalImageCache.addByteSize(imageRef,imgData.dataLen),this._sendImgData(objId,imgData,cacheGlobally))).catch(reason=>(warn(`Unable to decode image "${objId}": "${reason}".`),this._sendImgData(objId,null,cacheGlobally))),cacheKey){const cacheData={fn:OPS.paintImageXObject,args:args,optionalContent:optionalContent};localImageCache.set(cacheKey,imageRef,cacheData),imageRef&&(this._regionalImageCache.set(null,imageRef,cacheData),cacheGlobally)&&this.globalImageCache.setData(imageRef,{objId:objId,fn:OPS.paintImageXObject,args:args,optionalContent:optionalContent,byteSize:0})}}}else warn("Image dimensions are missing, or not numbers.")}handleSMask(smask,resources,operatorList,task,stateManager,localColorSpaceCache){var smaskContent=smask.get("G"),smaskOptions={subtype:smask.get("S").name,backdrop:smask.get("BC")},smask=smask.get("TR");if(isPDFFunction(smask)){var transferFn=this._pdfFunctionFactory.create(smask),transferMap=new Uint8Array(256),tmp=new Float32Array(1);for(let i=0;i<256;i++)tmp[0]=i/255,transferFn(tmp,0,tmp,0),transferMap[i]=255*tmp[0]|0;smaskOptions.transferMap=transferMap}return this.buildFormXObject(resources,smaskContent,smaskOptions,operatorList,task,stateManager.state.clone(),localColorSpaceCache)}handleTransferFunction(tr){let transferArray;if(Array.isArray(tr))transferArray=tr;else{if(!isPDFFunction(tr))return null;transferArray=[tr]}var transferMaps=[];let numFns=0,numEffectfulFns=0;for(const entry of transferArray){var transferObj=this.xref.fetchIfRef(entry);if(numFns++,isName(transferObj,"Identity"))transferMaps.push(null);else{if(!isPDFFunction(transferObj))return null;var transferFn=this._pdfFunctionFactory.create(transferObj),transferMap=new Uint8Array(256),tmp=new Float32Array(1);for(let j=0;j<256;j++)tmp[0]=j/255,transferFn(tmp,0,tmp,0),transferMap[j]=255*tmp[0]|0;transferMaps.push(transferMap),numEffectfulFns++}}return 1!==numFns&&4!==numFns||0===numEffectfulFns?null:transferMaps}handleTilingType(fn,color,resources,pattern,patternDict,operatorList,task,localTilingPatternCache){const tilingOpList=new OperatorList;resources=Dict.merge({xref:this.xref,dictArray:[patternDict.get("Resources"),resources]});return this.getOperatorList({stream:pattern,task:task,resources:resources,operatorList:tilingOpList}).then(function(){var operatorListIR=tilingOpList.getIR(),tilingPatternIR=getTilingPatternIR(operatorListIR,patternDict,color);operatorList.addDependencies(tilingOpList.dependencies),operatorList.addOp(fn,tilingPatternIR),patternDict.objId&&localTilingPatternCache.set(null,patternDict.objId,{operatorListIR:operatorListIR,dict:patternDict})}).catch(reason=>{if(!(reason instanceof AbortException)){if(!this.options.ignoreErrors)throw reason;warn(`handleTilingType - ignoring pattern: "${reason}".`)}})}async handleSetFont(resources,fontArgs,fontRef,operatorList,task,state,fallbackFontDict=null,cssFontInfo=null){fontArgs=fontArgs?.[0]instanceof Name?fontArgs[0].name:null;let translated=await this.loadFont(fontArgs,fontRef,resources,fallbackFontDict,cssFontInfo);if(translated.font.isType3Font)try{await translated.loadType3Data(this,resources,task),operatorList.addDependencies(translated.type3Dependencies)}catch(reason){translated=new TranslatedFont({loadedName:"g_font_error",font:new ErrorFont("Type3 font load error: "+reason),dict:translated.font,evaluatorOptions:this.options})}return state.font=translated.font,translated.send(this.handler),translated.loadedName}handleText(chars,state){var font=state.font,chars=font.charsToGlyphs(chars);return font.data&&(!!(state.textRenderingMode&TextRenderingMode.ADD_TO_PATH_FLAG)||"Pattern"===state.fillColorSpace.name||font.disableFontFace||this.options.disableFontFace)&&PartialEvaluator.buildFontPaths(font,chars,this.handler,this.options),chars}ensureStateFont(state){if(!state.font){state=new FormatError("Missing setFont (Tf) operator before text rendering operator.");if(!this.options.ignoreErrors)throw state;warn(`ensureStateFont: "${state}".`)}}async setGState({resources,gState,operatorList,cacheKey,task,stateManager,localGStateCache,localColorSpaceCache}){var gStateRef=gState.objId;let isSimpleGState=!0;const gStateObj=[];let promise=Promise.resolve();for(const key of gState.getKeys()){const value=gState.get(key);switch(key){case"Type":break;case"LW":case"LC":case"LJ":case"ML":case"D":case"RI":case"FL":case"CA":case"ca":gStateObj.push([key,value]);break;case"Font":isSimpleGState=!1,promise=promise.then(()=>this.handleSetFont(resources,null,value[0],operatorList,task,stateManager.state).then(function(loadedName){operatorList.addDependency(loadedName),gStateObj.push([key,[loadedName,value[1]]])}));break;case"BM":gStateObj.push([key,normalizeBlendMode(value)]);break;case"SMask":isName(value,"None")?gStateObj.push([key,!1]):value instanceof Dict?(isSimpleGState=!1,promise=promise.then(()=>this.handleSMask(value,resources,operatorList,task,stateManager,localColorSpaceCache)),gStateObj.push([key,!0])):warn("Unsupported SMask type");break;case"TR":var transferMaps=this.handleTransferFunction(value);gStateObj.push([key,transferMaps]);break;case"OP":case"op":case"OPM":case"BG":case"BG2":case"UCR":case"UCR2":case"TR2":case"HT":case"SM":case"SA":case"AIS":case"TK":info("graphic state operator "+key);break;default:info("Unknown graphic state operator "+key)}}await promise,0new TranslatedFont({loadedName:"g_font_error",font:new ErrorFont(`Font "${fontName}" is not available.`),dict:font,evaluatorOptions:this.options});let fontRef;if(font?font instanceof Ref&&(fontRef=font):(resources=resources.get("Font"))&&(fontRef=resources.getRaw(fontName)),fontRef){if(this.parsingType3Font&&this.type3FontRefs.has(fontRef))return errorFont();if(this.fontCache.has(fontRef))return this.fontCache.get(fontRef);font=this.xref.fetchIfRef(fontRef)}if(!(font instanceof Dict)){if(!this.options.ignoreErrors&&!this.parsingType3Font)return warn(`Font "${fontName}" is not available.`),errorFont();warn(`Font "${fontName}" is not available -- attempting to fallback to a default font.`),font=fallbackFontDict||PartialEvaluator.fallbackFontDict}if(font.cacheKey&&this.fontCache.has(font.cacheKey))return this.fontCache.get(font.cacheKey);const{promise,resolve}=Promise.withResolvers();let preEvaluatedFont;try{(preEvaluatedFont=this.preEvaluateFont(font)).cssFontInfo=cssFontInfo}catch(reason){return warn(`loadFont - preEvaluateFont failed: "${reason}".`),errorFont()}var{descriptor:resources,hash:fallbackFontDict}=preEvaluatedFont,cssFontInfo=fontRef instanceof Ref;let fontID;if(fallbackFontDict&&resources instanceof Dict){errorFont=resources.fontAliases||=Object.create(null);if(errorFont[fallbackFontDict]){resources=errorFont[fallbackFontDict].aliasRef;if(cssFontInfo&&resources&&this.fontCache.has(resources))return this.fontCache.putAlias(fontRef,resources),this.fontCache.get(fontRef)}else errorFont[fallbackFontDict]={fontID:this.idFactory.createFontId()};cssFontInfo&&(errorFont[fallbackFontDict].aliasRef=fontRef),fontID=errorFont[fallbackFontDict].fontID}else fontID=this.idFactory.createFontId();return assert(fontID?.startsWith("f"),'The "fontID" must be (correctly) defined.'),cssFontInfo?this.fontCache.put(fontRef,promise):(font.cacheKey="cacheKey_"+fontID,this.fontCache.put(font.cacheKey,promise)),font.loadedName=this.idFactory.getDocId()+"_"+fontID,this.translateFont(preEvaluatedFont).then(translatedFont=>{resolve(new TranslatedFont({loadedName:font.loadedName,font:translatedFont,dict:font,evaluatorOptions:this.options}))}).catch(reason=>{warn(`loadFont - translateFont failed: "${reason}".`),resolve(new TranslatedFont({loadedName:font.loadedName,font:new ErrorFont(reason instanceof Error?reason.message:reason),dict:font,evaluatorOptions:this.options}))}),promise}buildPath(operatorList,fn,args,parsingText=!1){var lastIndex=operatorList.length-1;if(args=args||[],lastIndex<0||operatorList.fnArray[lastIndex]!==OPS.constructPath){parsingText&&(warn(`Encountered path operator "${fn}" inside of a text object.`),operatorList.addOp(OPS.save,null));let minMax;switch(fn){case OPS.rectangle:var x=args[0]+args[2],y=args[1]+args[3];minMax=[Math.min(args[0],x),Math.min(args[1],y),Math.max(args[0],x),Math.max(args[1],y)];break;case OPS.moveTo:case OPS.lineTo:minMax=[args[0],args[1],args[0],args[1]];break;default:minMax=[1/0,1/0,-1/0,-1/0]}operatorList.addOp(OPS.constructPath,[[fn],args,minMax]),parsingText&&operatorList.addOp(OPS.restore,null)}else{var parsingText=operatorList.argsArray[lastIndex],minMax=(parsingText[0].push(fn),parsingText[1].push(...args),parsingText[2]);switch(fn){case OPS.rectangle:const x=args[0]+args[2],y=args[1]+args[3];minMax[0]=Math.min(minMax[0],args[0],x),minMax[1]=Math.min(minMax[1],args[1],y),minMax[2]=Math.max(minMax[2],args[0],x),minMax[3]=Math.max(minMax[3],args[1],y);break;case OPS.moveTo:case OPS.lineTo:minMax[0]=Math.min(minMax[0],args[0]),minMax[1]=Math.min(minMax[1],args[1]),minMax[2]=Math.max(minMax[2],args[0]),minMax[3]=Math.max(minMax[3],args[1])}}}parseColorSpace({cs,resources,localColorSpaceCache}){return ColorSpace.parseAsync({cs:cs,xref:this.xref,resources:resources,pdfFunctionFactory:this._pdfFunctionFactory,localColorSpaceCache:localColorSpaceCache}).catch(reason=>{if(reason instanceof AbortException)return null;if(this.options.ignoreErrors)return warn(`parseColorSpace - ignoring ColorSpace: "${reason}".`),null;throw reason})}parseShading({shading,resources,localColorSpaceCache,localShadingPatternCache}){let id=localShadingPatternCache.get(shading);if(!id){let patternIR;try{var shadingFill=Pattern.parseShading(shading,this.xref,resources,this._pdfFunctionFactory,localColorSpaceCache);patternIR=shadingFill.getIR()}catch(reason){if(reason instanceof AbortException)return null;if(this.options.ignoreErrors)return warn(`parseShading - ignoring shading: "${reason}".`),localShadingPatternCache.set(shading,null),null;throw reason}id="pattern_"+this.idFactory.createObjId(),this.parsingType3Font&&(id=this.idFactory.getDocId()+"_type3_"+id),localShadingPatternCache.set(shading,id),this.parsingType3Font?this.handler.send("commonobj",[id,"Pattern",patternIR]):this.handler.send("obj",[id,this.pageIndex,"Pattern",patternIR])}return id}handleColorN(operatorList,fn,args,cs,patterns,resources,task,localColorSpaceCache,localTilingPatternCache,localShadingPatternCache){var patternName=args.pop();if(patternName instanceof Name){var patterns=patterns.getRaw(patternName.name),localTilingPattern=patterns instanceof Ref&&localTilingPatternCache.getByRef(patterns);if(localTilingPattern)try{var color=cs.base?cs.base.getRgb(args,0):null,tilingPatternIR=getTilingPatternIR(localTilingPattern.operatorListIR,localTilingPattern.dict,color);return void operatorList.addOp(fn,tilingPatternIR)}catch{}localTilingPattern=this.xref.fetchIfRef(patterns);if(localTilingPattern){tilingPatternIR=localTilingPattern instanceof BaseStream?localTilingPattern.dict:localTilingPattern,color=tilingPatternIR.get("PatternType");if(color===PatternType.TILING){const color=cs.base?cs.base.getRgb(args,0):null;return this.handleTilingType(fn,color,resources,localTilingPattern,tilingPatternIR,operatorList,task,localTilingPatternCache)}if(color===PatternType.SHADING)return patterns=tilingPatternIR.get("Shading"),void((cs=this.parseShading({shading:patterns,resources:resources,localColorSpaceCache:localColorSpaceCache,localShadingPatternCache:localShadingPatternCache}))&&(args=tilingPatternIR.getArray("Matrix"),operatorList.addOp(fn,["Shading",cs,args])));throw new FormatError("Unknown PatternType: "+color)}}throw new FormatError("Unknown PatternName: "+patternName)}_parseVisibilityExpression(array,nestingCounter,currentResult){if(10<++nestingCounter)warn("Visibility expression is too deeply nested");else{var length=array.length,operator=this.xref.fetchIfRef(array[0]);if(length<2||!(operator instanceof Name))warn("Invalid visibility expression");else{switch(operator.name){case"And":case"Or":case"Not":currentResult.push(operator.name);break;default:return void warn(`Invalid operator ${operator.name} in visibility expression`)}for(let i=1;i{operatorList.addOp(OPS.beginMarkedContentProps,["OC",data])}).catch(reason=>{if(!(reason instanceof AbortException)){if(!self.options.ignoreErrors)throw reason;warn(`getOperatorList - ignoring beginMarkedContentProps: "${reason}".`),operatorList.addOp(OPS.beginMarkedContentProps,["OC",null])}}));args=[args[0].name,args[1]instanceof Dict?args[1].get("MCID"):null];break;case OPS.beginMarkedContent:case OPS.endMarkedContent:default:if(null!==args){for(i=0,ii=args.length;i{if(!(reason instanceof AbortException)){if(!this.options.ignoreErrors)throw reason;warn(`getOperatorList - ignoring errors during "${task.name}" `+`task: "${reason}".`),closePendingRestoreOPS()}})}getTextContent({stream,task,resources,stateManager=null,includeMarkedContent=!1,sink,seenStyles=new Set,viewBox,markedContentData=null,disableNormalization=!1,keepWhiteSpace=!1}){resources||=Dict.empty,stateManager||=new StateManager(new TextState),includeMarkedContent&&(markedContentData||={level:0});const textContent={items:[],styles:Object.create(null)},textContentItem={initialized:!1,str:[],totalWidth:0,totalHeight:0,width:0,height:0,vertical:!1,prevTransform:null,textAdvanceScale:0,spaceInFlowMin:0,spaceInFlowMax:0,trackingSpaceMin:1/0,negativeSpaceMax:-1/0,notASpace:-1/0,transform:null,fontName:null,hasEOL:!1},twoLastChars=[" "," "];let twoLastCharsPos=0;function saveLastChar(char){var nextPos=(twoLastCharsPos+1)%2,ret=" "!==twoLastChars[twoLastCharsPos]&&" "===twoLastChars[nextPos];return twoLastChars[twoLastCharsPos]=char,twoLastCharsPos=nextPos,!keepWhiteSpace&&ret}function shouldAddWhitepsace(){return!keepWhiteSpace&&" "!==twoLastChars[twoLastCharsPos]&&" "===twoLastChars[(twoLastCharsPos+1)%2]}function resetLastChars(){twoLastChars[0]=twoLastChars[1]=" ",twoLastCharsPos=0}const TRACKING_SPACE_FACTOR=.102,NOT_A_SPACE_FACTOR=.03,NEGATIVE_SPACE_FACTOR=-.2,SPACE_IN_FLOW_MIN_FACTOR=.102,SPACE_IN_FLOW_MAX_FACTOR=.6,VERTICAL_SHIFT_RATIO=.25,self=this,xref=this.xref,showSpacedTextBuffer=[];let xobjs=null;const emptyXObjectCache=new LocalImageCache,emptyGStateCache=new LocalGStateCache,preprocessor=new EvaluatorPreprocessor(stream,xref,stateManager);let textState;function pushWhitespace({width=0,height=0,transform=textContentItem.prevTransform,fontName=textContentItem.fontName}){textContent.items.push({str:" ",dir:"ltr",width:width,height:height,transform:transform,fontName:fontName,hasEOL:!1})}function getCurrentTextTransform(){var font=textState.font,tsm=[textState.fontSize*textState.textHScale,0,0,textState.fontSize,0,textState.textRise];return font.isType3Font&&(textState.fontSize<=1||font.isCharBBox)&&!isArrayEqual(textState.fontMatrix,FONT_IDENTITY_MATRIX)&&0<(font=font.bbox[3]-font.bbox[1])&&(tsm[3]*=font*textState.fontMatrix[3]),Util.transform(textState.ctm,Util.transform(textState.textMatrix,tsm))}async function handleSetFont(fontName,fontRef){fontName=await self.loadFont(fontName,fontRef,resources);if(fontName.font.isType3Font)try{await fontName.loadType3Data(self,resources,task)}catch{}textState.loadedName=fontName.loadedName,textState.font=fontName.font,textState.fontMatrix=fontName.font.fontMatrix||FONT_IDENTITY_MATRIX}function applyInverseRotation(x,y,matrix){var scale=Math.hypot(matrix[0],matrix[1]);return[(matrix[0]*x+matrix[1]*y)/scale,(matrix[2]*x+matrix[3]*y)/scale]}function compareWithLastPosition(glyphWidth){var currentTransform=getCurrentTextTransform();let posX=currentTransform[4],posY=currentTransform[5];if(textState.font?.vertical){if(posXviewBox[2]||posY+glyphWidthviewBox[3])return}else if(posX+glyphWidthviewBox[2]||posYviewBox[3])return;if(textState.font&&textContentItem.prevTransform){let lastPosX=textContentItem.prevTransform[4],lastPosY=textContentItem.prevTransform[5];if(lastPosX!==posX||lastPosY!==posY){let rotate=-1;switch(currentTransform[0]&&0===currentTransform[1]&&0===currentTransform[2]?rotate=0.5*textContentItem.width?appendEOL:(resetLastChars(),flushTextContentItem))():Math.abs(advanceX)>textContentItem.width?appendEOL():(advanceY<=textOrientation*textContentItem.notASpace&&resetLastChars(),advanceY<=textOrientation*textContentItem.trackingSpaceMin?shouldAddWhitepsace()?(resetLastChars(),flushTextContentItem(),pushWhitespace({height:Math.abs(advanceY)})):textContentItem.height+=advanceY:addFakeSpaces(advanceY,textContentItem.prevTransform,textOrientation)||(0===textContentItem.str.length?(resetLastChars(),pushWhitespace({height:Math.abs(advanceY)})):textContentItem.height+=advanceY),Math.abs(advanceX)>textContentItem.width*VERTICAL_SHIFT_RATIO&&flushTextContentItem())}else{const advanceX=(posX-lastPosX)/textContentItem.textAdvanceScale,advanceY=posY-lastPosY,textOrientation=Math.sign(textContentItem.width);advanceX.5*textContentItem.height?appendEOL:(resetLastChars(),flushTextContentItem))():Math.abs(advanceY)>textContentItem.height?appendEOL():(advanceX<=textOrientation*textContentItem.notASpace&&resetLastChars(),advanceX<=textOrientation*textContentItem.trackingSpaceMin?shouldAddWhitepsace()?(resetLastChars(),flushTextContentItem(),pushWhitespace({width:Math.abs(advanceX)})):textContentItem.width+=advanceX:addFakeSpaces(advanceX,textContentItem.prevTransform,textOrientation)||(0===textContentItem.str.length?(resetLastChars(),pushWhitespace({width:Math.abs(advanceX)})):textContentItem.width+=advanceX),Math.abs(advanceY)>textContentItem.height*VERTICAL_SHIFT_RATIO&&flushTextContentItem())}}}return 1}function buildTextContentItem({chars,extraSpacing}){var font=textState.font;if(chars){var glyphs=font.charsToGlyphs(chars),scale=textState.fontMatrix[0]*textState.fontSize;for(let i=0,ii=glyphs.length;i=sink.desiredSize){stop=!0;break}}stop?next(deferred):(flushTextContentItem(),enqueueChunk(),resolve())}).catch(reason=>{if(!(reason instanceof AbortException)){if(!this.options.ignoreErrors)throw reason;warn(`getTextContent - ignoring errors during "${task.name}" `+`task: "${reason}".`),flushTextContentItem(),enqueueChunk()}})}async extractDataStructures(dict,properties){var xref=this.xref;let cidToGidBytes;var toUnicodePromise=this.readToUnicode(properties.toUnicode);if(properties.composite){var cidSystemInfo=dict.get("CIDSystemInfo");cidSystemInfo instanceof Dict&&(properties.cidSystemInfo={registry:stringToPDFString(cidSystemInfo.get("Registry")),ordering:stringToPDFString(cidSystemInfo.get("Ordering")),supplement:cidSystemInfo.get("Supplement")});try{var cidToGidMap=dict.get("CIDToGIDMap");cidToGidMap instanceof BaseStream&&(cidToGidBytes=cidToGidMap.getBytes())}catch(ex){if(!this.options.ignoreErrors)throw ex;warn(`extractDataStructures - ignoring CIDToGIDMap data: "${ex}".`)}}var differences=[];let baseEncodingName=null,encoding;if(dict.has("Encoding")){if((encoding=dict.get("Encoding"))instanceof Dict){if(baseEncodingName=(baseEncodingName=encoding.get("BaseEncoding"))instanceof Name?baseEncodingName.name:null,encoding.has("Differences")){let index=0;for(const entry of encoding.get("Differences")){var data=xref.fetchIfRef(entry);if("number"==typeof data)index=data;else{if(!(data instanceof Name))throw new FormatError("Invalid entry in 'Differences' array: "+data);differences[index++]=data.name}}}}else if(encoding instanceof Name)baseEncodingName=encoding.name;else{cidSystemInfo="Encoding is not a Name nor a Dict";if(!this.options.ignoreErrors)throw new FormatError(cidSystemInfo);warn(cidSystemInfo)}"MacRomanEncoding"!==baseEncodingName&&"MacExpertEncoding"!==baseEncodingName&&"WinAnsiEncoding"!==baseEncodingName&&(baseEncodingName=null)}var isSymbolicFont,cidToGidMap=!properties.file||properties.isInternalFont,cidSystemInfo=getSymbolsFonts()[properties.name],isNonsymbolicFont=((baseEncodingName=baseEncodingName&&cidToGidMap&&cidSystemInfo?null:baseEncodingName)?properties.defaultEncoding=getEncoding(baseEncodingName):(isSymbolicFont=!!(properties.flags&FontFlags.Symbolic),isNonsymbolicFont=!!(properties.flags&FontFlags.Nonsymbolic),encoding=StandardEncoding,"TrueType"!==properties.type||isNonsymbolicFont||(encoding=WinAnsiEncoding),(isSymbolicFont||cidSystemInfo)&&(encoding=MacRomanEncoding,cidToGidMap)&&(/Symbol/i.test(properties.name)?encoding=SymbolSetEncoding:/Dingbats/i.test(properties.name)?encoding=ZapfDingbatsEncoding:/Wingdings/i.test(properties.name)&&(encoding=WinAnsiEncoding)),properties.defaultEncoding=encoding),properties.differences=differences,properties.baseEncodingName=baseEncodingName,properties.hasEncoding=!!baseEncodingName||0>1;0==glyphID&&!toUnicode.has(code)||(result[code]=glyphID)}return result}extractWidths(dict,descriptor,properties){var xref=this.xref;let glyphsWidths=[],defaultWidth=0;var glyphsVMetrics=[];let defaultVMetrics;if(properties.composite){var dw=dict.get("DW"),widths=(defaultWidth=Number.isInteger(dw)?dw:1e3,dict.get("W"));if(Array.isArray(widths))for(let i=0,ii=widths.length;i{var glyphStream=charProcs.get(key);const operatorList=new OperatorList;return type3Evaluator.getOperatorList({stream:glyphStream,task:task,resources:fontResources,operatorList:operatorList}).then(()=>{operatorList.fnArray[0]===OPS.setCharWidthAndBounds&&this._removeType3ColorOperators(operatorList,fontBBoxSize),charProcOperatorList[key]=operatorList.getIR();for(const dependency of operatorList.dependencies)type3Dependencies.add(dependency)}).catch(function(reason){warn(`Type3 font resource "${key}" is not available.`);var dummyOperatorList=new OperatorList;charProcOperatorList[key]=dummyOperatorList.getIR()})});this.type3Loaded=loadCharProcsPromise.then(()=>{translatedFont.charProcOperatorList=charProcOperatorList,this._bbox&&(translatedFont.isCharBBox=!0,translatedFont.bbox=this._bbox)})}return this.type3Loaded}_removeType3ColorOperators(operatorList,fontBBoxSize=NaN){var charBBox=Util.normalizeRect(operatorList.argsArray[0].slice(2)),width=charBBox[2]-charBBox[0],height=charBBox[3]-charBBox[1],charBBoxSize=Math.hypot(width,height);0==width||0==height?(operatorList.fnArray.splice(0,1),operatorList.argsArray.splice(0,1)):(0===fontBBoxSize||10<=Math.round(charBBoxSize/fontBBoxSize))&&(this._bbox||(this._bbox=[1/0,1/0,-1/0,-1/0]),this._bbox[0]=Math.min(this._bbox[0],charBBox[0]),this._bbox[1]=Math.min(this._bbox[1],charBBox[1]),this._bbox[2]=Math.max(this._bbox[2],charBBox[2]),this._bbox[3]=Math.max(this._bbox[3],charBBox[3]));let i=0,ii=operatorList.length;for(;i=OPS.moveTo&&fn<=OPS.endPath,opSpec.variableArgs)argsLength>numArgs&&info(`Command ${cmd}: expected [0, ${numArgs}] args, `+`but received ${argsLength} args.`);else{if(argsLength!==numArgs){for(var nonProcessedArgs=this.nonProcessedArgs;argsLength>numArgs;)nonProcessedArgs.push(args.shift()),argsLength--;for(;argsLengthEvaluatorPreprocessor.MAX_INVALID_PATH_OPS)throw new FormatError("Invalid "+opSpec);warn("Skipping "+opSpec),null!==args&&(args.length=0);continue}}return this.preprocessCommand(fn,args),operation.fn=fn,operation.args=args,!0}if(obj===EOF)return!1;if(null!==obj&&((args=null===args?[]:args).push(obj),33numberToString(c/255)).join(" ")+" "+(isFill?"rg":"RG")}function createDefaultAppearance({fontSize,fontName,fontColor}){return`/${escapePDFName(fontName)} ${fontSize} Tf `+getPdfColor(fontColor,!0)}class FakeUnicodeFont{constructor(xref,fontFamily){this.xref=xref,this.widths=null,this.firstChar=1/0,this.lastChar=-1/0,this.fontFamily=fontFamily;xref=new OffscreenCanvas(1,1);this.ctxMeasure=xref.getContext("2d"),FakeUnicodeFont._fontNameId||(FakeUnicodeFont._fontNameId=1),this.fontName=Name.get(`InvalidPDFjsFont_${fontFamily}_`+FakeUnicodeFont._fontNameId++)}get fontDescriptorRef(){var fontDescriptor;return FakeUnicodeFont._fontDescriptorRef||((fontDescriptor=new Dict(this.xref)).set("Type",Name.get("FontDescriptor")),fontDescriptor.set("FontName",this.fontName),fontDescriptor.set("FontFamily","MyriadPro Regular"),fontDescriptor.set("FontBBox",[0,0,0,0]),fontDescriptor.set("FontStretch",Name.get("Normal")),fontDescriptor.set("FontWeight",400),fontDescriptor.set("ItalicAngle",0),FakeUnicodeFont._fontDescriptorRef=this.xref.getNewPersistentRef(fontDescriptor)),FakeUnicodeFont._fontDescriptorRef}get descendantFontRef(){var char,width,descendantFont=new Dict(this.xref),widths=(descendantFont.set("BaseFont",this.fontName),descendantFont.set("Type",Name.get("Font")),descendantFont.set("Subtype",Name.get("CIDFontType0")),descendantFont.set("CIDToGIDMap",Name.get("Identity")),descendantFont.set("FirstChar",this.firstChar),descendantFont.set("LastChar",this.lastChar),descendantFont.set("FontDescriptor",this.fontDescriptorRef),descendantFont.set("DW",1e3),[]);let currentChar=null,currentWidths=null;for([char,width]of[...this.widths.entries()].sort())currentChar?char===currentChar+currentWidths.length?currentWidths.push(width):(widths.push(currentChar,currentWidths),currentChar=char,currentWidths=[width]):(currentChar=char,currentWidths=[width]);currentChar&&widths.push(currentChar,currentWidths),descendantFont.set("W",widths);var cidSystemInfo=new Dict(this.xref);return cidSystemInfo.set("Ordering","Identity"),cidSystemInfo.set("Registry","Adobe"),cidSystemInfo.set("Supplement",0),descendantFont.set("CIDSystemInfo",cidSystemInfo),this.xref.getNewPersistentRef(descendantFont)}get baseFontRef(){var baseFont=new Dict(this.xref);return baseFont.set("BaseFont",this.fontName),baseFont.set("Type",Name.get("Font")),baseFont.set("Subtype",Name.get("Type0")),baseFont.set("Encoding",Name.get("Identity-H")),baseFont.set("DescendantFonts",[this.descendantFontRef]),baseFont.set("ToUnicode",Name.get("Identity-H")),this.xref.getNewPersistentRef(baseFont)}get resources(){var resources=new Dict(this.xref),font=new Dict(this.xref);return font.set(this.fontName.name,this.baseFontRef),resources.set("Font",font),resources}_createContext(){return this.widths=new Map,this.ctxMeasure.font="1000px "+this.fontFamily,this.ctxMeasure}createFontResources(text){var ctx=this._createContext();for(const line of text.split(/\r\n?|\n/))for(const char of line.split("")){var metrics,code=char.charCodeAt(0);this.widths.has(code)||(metrics=ctx.measureText(char),metrics=Math.ceil(metrics.width),this.widths.set(code,metrics),this.firstChar=Math.min(code,this.firstChar),this.lastChar=Math.max(code,this.lastChar))}return this.resources}static getFirstPositionInfo(rect,rotation,fontSize){var[rect,y1,x2,y2]=rect;let w=x2-rect,h=y2-y1;rotation%180!=0&&([w,h]=[h,w]);x2=LINE_FACTOR*fontSize,rect=LINE_DESCENT_FACTOR*fontSize;return{coords:[0,h+rect-x2],bbox:[0,0,w,h],matrix:0!==rotation?getRotationMatrix(rotation,h,x2):void 0}}createAppearance(text,rect,rotation,fontSize,bgColor,strokeAlpha){var ctx=this._createContext(),lines=[];let maxWidth=-1/0;for(const line of text.split(/\r\n?|\n/)){lines.push(line);var lineWidth=ctx.measureText(line).width;maxWidth=Math.max(maxWidth,lineWidth);for(const code of codePointIter(line)){var char=String.fromCodePoint(code),width=this.widths.get(code);void 0===width&&(char=ctx.measureText(char),width=Math.ceil(char.width),this.widths.set(code,width),this.firstChar=Math.min(code,this.firstChar),this.lastChar=Math.max(code,this.lastChar))}}maxWidth*=fontSize/1e3;var[text,rect,x2,y2]=rect;let w=x2-text,h=y2-rect,hscale=(rotation%180!=0&&([w,h]=[h,w]),1),vscale=(maxWidth>w&&(hscale=w/maxWidth),1);var x2=LINE_FACTOR*fontSize,text=LINE_DESCENT_FACTOR*fontSize,y2=x2*lines.length,rect=(y2>h&&(vscale=h/y2),Math.min(hscale,vscale)),y2=fontSize*rect,buffer=["q",`0 0 ${numberToString(w)} ${numberToString(h)} re W n`,"BT",`1 0 0 1 0 ${numberToString(h+text)} Tm 0 Tc `+getPdfColor(bgColor,!0),`/${this.fontName.name} ${numberToString(y2)} Tf`],fontSize=this["resources"],vShift=(1!==(strokeAlpha="number"==typeof strokeAlpha&&0<=strokeAlpha&&strokeAlpha<=1?strokeAlpha:1)&&(buffer.push("/R0 gs"),rect=new Dict(this.xref),(text=new Dict(this.xref)).set("ca",strokeAlpha),text.set("CA",strokeAlpha),text.set("Type",Name.get("ExtGState")),rect.set("R0",text),fontSize.set("ExtGState",rect)),numberToString(x2));for(const line of lines)buffer.push(`0 -${vShift} Td <${stringToUTF16HexString(line)}> Tj`);buffer.push("ET","Q");bgColor=buffer.join("\n"),y2=new Dict(this.xref),y2.set("Subtype",Name.get("Form")),y2.set("Type",Name.get("XObject")),y2.set("BBox",[0,0,w,h]),y2.set("Length",bgColor.length),y2.set("Resources",fontSize),rotation&&(strokeAlpha=getRotationMatrix(rotation,w,h),y2.set("Matrix",strokeAlpha)),text=new StringStream(bgColor);return text.dict=y2,text}}class NameOrNumberTree{constructor(root,xref,type){this.constructor===NameOrNumberTree&&unreachable("Cannot initialize NameOrNumberTree."),this.root=root,this.xref=xref,this._type=type}getAll(){var map=new Map;if(this.root)for(var xref=this.xref,processed=new RefSet,queue=(processed.put(this.root),[this.root]);0>1,kid=xref.fetchIfRef(kids[m]),limits=kid.get("Limits");if(keyxref.fetchIfRef(limits[1]))){kidsOrEntries=kid;break}l=1+m}}if(l>r)return null}var entries=kidsOrEntries.get(this._type);if(Array.isArray(entries)){let l=0,r=entries.length-2;for(;l<=r;){const tmp=l+r>>1,m=tmp+(1&tmp);var currentKey=xref.fetchIfRef(entries[m]);if(key{if("#x"===entity.substring(0,2))return String.fromCodePoint(parseInt(entity.substring(2),16));if("#"===entity.substring(0,1))return String.fromCodePoint(parseInt(entity.substring(1),10));switch(entity){case"lt":return"<";case"gt":return">";case"amp":return"&";case"quot":return'"';case"apos":return"'"}return this.onResolveEntity(entity)})}_parseContent(s,start){var attributes=[];let pos=start;function skipWs(){for(;pos"!==s[pos]&&"/"!==s[pos];)++pos;var name=s.substring(start,pos);for(skipWs();pos"!==s[pos]&&"/"!==s[pos]&&"?"!==s[pos];){skipWs();let attrName="",attrValue;for(;pos"!==s[pos]&&"?"!==s[pos]&&"/"!==s[pos];)++pos;for(var name=s.substring(start,pos);pos"!==s[pos+1]);)++pos;return{name:name,value:s.substring(attrStart,pos),parsed:pos-start}}parseXml(s){let i=0;for(;i",j))<0)return void this.onError(XMLParserErrorCode.UnterminatedElement);this.onEndElement(s.substring(j,q)),j=q+1;break;case"?":++j;var pi=this._parseProcessingInstruction(s,j);if("?>"!==s.substring(j+pi.parsed,j+pi.parsed+2))return void this.onError(XMLParserErrorCode.UnterminatedXmlDeclaration);this.onPi(pi.name,pi.value),j+=pi.parsed+2;break;case"!":if("--"===s.substring(j+1,j+3)){if((q=s.indexOf("--\x3e",j+3))<0)return void this.onError(XMLParserErrorCode.UnterminatedComment);this.onComment(s.substring(j+3,q)),j=q+3}else if("[CDATA["===s.substring(j+1,j+8)){if((q=s.indexOf("]]>",j+8))<0)return void this.onError(XMLParserErrorCode.UnterminatedCdat);this.onCdata(s.substring(j+8,q)),j=q+3}else{if("DOCTYPE"!==s.substring(j+1,j+8))return void this.onError(XMLParserErrorCode.MalformedElement);{pi=s.indexOf("[",j+8);let complexDoctype=!1;if((q=s.indexOf(">",j+8))<0)return void this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration);if(0pi){if((q=s.indexOf("]>",j+8))<0)return void this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration);complexDoctype=!0}var doctypeContent=s.substring(j+8,q+(complexDoctype?1:0));this.onDoctype(doctypeContent),j=q+(complexDoctype?2:1)}}break;default:doctypeContent=this._parseContent(s,j);if(null===doctypeContent)return void this.onError(XMLParserErrorCode.MalformedElement);let isClosed=!1;if("/>"===s.substring(j+doctypeContent.parsed,j+doctypeContent.parsed+2))isClosed=!0;else if(">"!==s.substring(j+doctypeContent.parsed,j+doctypeContent.parsed+1))return void this.onError(XMLParserErrorCode.UnterminatedElement);this.onBeginElement(doctypeContent.name,doctypeContent.attributes,isClosed),j+=doctypeContent.parsed+(isClosed?2:1)}}else{for(;j=paths.length)return this;var component=paths[pos];if(component.name.startsWith("#")&&pos");for(const child of this.childNodes)child.dump(buffer);buffer.push(``)}else this.nodeValue?buffer.push(`>${encodeToXmlString(this.nodeValue)}`):buffer.push("/>")}}}class SimpleXMLParser extends XMLParserBase{constructor({hasAttributes=!1,lowerCaseName=!1}){super(),this._currentFragment=null,this._stack=null,this._errorCode=XMLParserErrorCode.NoError,this._hasAttributes=hasAttributes,this._lowerCaseName=lowerCaseName}parseFromString(data){if(this._currentFragment=[],this._stack=[],this._errorCode=XMLParserErrorCode.NoError,this.parseXml(data),this._errorCode===XMLParserErrorCode.NoError){var[data]=this._currentFragment;if(data)return{documentElement:data}}}onText(text){isWhitespaceString(text)||(text=new SimpleDOMNode("#text",text),this._currentFragment.push(text))}onCdata(text){text=new SimpleDOMNode("#text",text);this._currentFragment.push(text)}onBeginElement(name,attributes,isEmpty){this._lowerCaseName&&(name=name.toLowerCase());name=new SimpleDOMNode(name);name.childNodes=[],this._hasAttributes&&(name.attributes=attributes),this._currentFragment.push(name),isEmpty||(this._stack.push(this._currentFragment),this._currentFragment=name.childNodes)}onEndElement(name){this._currentFragment=this._stack.pop()||[];var lastElement=this._currentFragment.at(-1);if(!lastElement)return null;for(const childNode of lastElement.childNodes)childNode.parentNode=lastElement;return lastElement}onError(code){this._errorCode=code}}class MetadataParser{constructor(data){data=this._repair(data);var xmlDocument=new SimpleXMLParser({lowerCaseName:!0}).parseFromString(data);this._metadataMap=new Map,this._data=data,xmlDocument&&this._parse(xmlDocument)}_repair(data){return data.replace(/^[^<]+/,"").replaceAll(/>\\376\\377([^<]+)/g,function(all,codes){var bytes=codes.replaceAll(/\\([0-3])([0-7])([0-7])/g,function(code,d1,d2,d3){return String.fromCharCode(64*d1+8*d2+ +d3)}).replaceAll(/&(amp|apos|gt|lt|quot);/g,function(str,name){switch(name){case"amp":return"&";case"apos":return"'";case"gt":return">";case"lt":return"<";case"quot":return'"'}throw new Error(`_repair: ${name} isn't defined.`)}),charBuf=[">"];for(let i=0,ii=bytes.length;i"rdf:li"===node.nodeName)}_parseArray(entry){var seqNode;entry.hasChildNodes()&&([seqNode]=entry.childNodes,seqNode=this._getSequence(seqNode)||[],this._metadataMap.set(entry.nodeName,seqNode.map(node=>node.textContent.trim())))}_parse(xmlDocument){let rdf=xmlDocument.documentElement;if("rdf:rdf"!==rdf.nodeName)for(rdf=rdf.firstChild;rdf&&"rdf:rdf"!==rdf.nodeName;)rdf=rdf.nextSibling;if(rdf&&"rdf:rdf"===rdf.nodeName&&rdf.hasChildNodes())for(const desc of rdf.childNodes)if("rdf:description"===desc.nodeName)for(const entry of desc.childNodes){var name=entry.nodeName;switch(name){case"#text":continue;case"dc:creator":case"dc:subject":this._parseArray(entry);continue}this._metadataMap.set(name,entry.textContent.trim())}}get serializable(){return{parsedData:this._metadataMap,rawData:this._data}}}const chunkSize=512;class DecryptStream extends DecodeStream{constructor(str,maybeLength,decrypt){super(maybeLength),this.str=str,this.dict=str.dict,this.decrypt=decrypt,this.nextChunk=null,this.initialized=!1}readBlock(){let chunk;var decrypt,hasMoreData;this.initialized?chunk=this.nextChunk:(chunk=this.str.getBytes(chunkSize),this.initialized=!0),chunk&&0!==chunk.length?(this.nextChunk=this.str.getBytes(chunkSize),hasMoreData=0>5&255,padded[i++]=length>>13&255,padded[i++]=length>>21&255,padded[i++]=length>>>29&255,padded[i++]=0,padded[i++]=0,padded[i++]=0;var w=new Int32Array(16);for(i=0;i>>32-rotate)|0,a=tmp}h0=h0+a|0,h1=h1+b|0,h2=h2+c|0,h3=h3+d|0}return new Uint8Array([255&h0,h0>>8&255,h0>>16&255,h0>>>24&255,255&h1,h1>>8&255,h1>>16&255,h1>>>24&255,255&h2,h2>>8&255,h2>>16&255,h2>>>24&255,255&h3,h3>>8&255,h3>>16&255,h3>>>24&255])}}();class Word64{constructor(highInteger,lowInteger){this.high=0|highInteger,this.low=0|lowInteger}and(word){this.high&=word.high,this.low&=word.low}xor(word){this.high^=word.high,this.low^=word.low}or(word){this.high|=word.high,this.low|=word.low}shiftRight(places){32<=places?(this.low=this.high>>>places-32|0,this.high=0):(this.low=this.low>>>places|this.high<<32-places,this.high=this.high>>>places|0)}shiftLeft(places){32<=places?(this.high=this.low<>>32-places,this.low<<=places)}rotateRight(places){let low,high;32&places?(high=this.low,low=this.high):(low=this.low,high=this.high),places&=31,this.low=low>>>places|high<<32-places,this.high=high>>>places|low<<32-places}not(){this.high=~this.high,this.low=~this.low}add(word){var lowAdd=(this.low>>>0)+(word.low>>>0);let highAdd=(this.high>>>0)+(word.high>>>0);4294967295>>24&255,bytes[offset+1]=this.high>>16&255,bytes[offset+2]=this.high>>8&255,bytes[offset+3]=255&this.high,bytes[offset+4]=this.low>>>24&255,bytes[offset+5]=this.low>>16&255,bytes[offset+6]=this.low>>8&255,bytes[offset+7]=255&this.low}assign(word){this.high=word.high,this.low=word.low}}const calculateSHA256=function(){function rotr(x,n){return x>>>n|x<<32-n}const k=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];return function(data,offset,length){let h0=1779033703,h1=3144134277,h2=1013904242,h3=2773480762,h4=1359893119,h5=2600822924,h6=528734635,h7=1541459225;var paddedLength=64*Math.ceil((length+9)/64),padded=new Uint8Array(paddedLength);let i,j;for(i=0;i>>29&255,padded[i++]=length>>21&255,padded[i++]=length>>13&255,padded[i++]=length>>5&255,padded[i++]=length<<3&255;var x,w=new Uint32Array(64);for(i=0;i>>10)+w[j-7]+function(x){return rotr(x,7)^rotr(x,18)^x>>>3}(w[j-15])+w[j-16];let a=h0,b=h1,c=h2,d=h3,e=h4,f=h5,g=h6,h=h7,t1,t2;for(j=0;j<64;++j)t1=h+function(x){return rotr(x,6)^rotr(x,11)^rotr(x,25)}(e)+function(x,y,z){return x&y^~x&z}(e,f,g)+k[j]+w[j],t2=function(x){return rotr(x,2)^rotr(x,13)^rotr(x,22)}(a)+function(x,y,z){return x&y^x&z^y&z}(a,b,c),h=g,g=f,f=e,e=d+t1|0,d=c,c=b,b=a,a=t1+t2|0;h0=h0+a|0,h1=h1+b|0,h2=h2+c|0,h3=h3+d|0,h4=h4+e|0,h5=h5+f|0,h6=h6+g|0,h7=h7+h|0}return new Uint8Array([h0>>24&255,h0>>16&255,h0>>8&255,255&h0,h1>>24&255,h1>>16&255,h1>>8&255,255&h1,h2>>24&255,h2>>16&255,h2>>8&255,255&h2,h3>>24&255,h3>>16&255,h3>>8&255,255&h3,h4>>24&255,h4>>16&255,h4>>8&255,255&h4,h5>>24&255,h5>>16&255,h5>>8&255,255&h5,h6>>24&255,h6>>16&255,h6>>8&255,255&h6,h7>>24&255,h7>>16&255,h7>>8&255,255&h7])}}(),calculateSHA512=function(){const k=[new Word64(1116352408,3609767458),new Word64(1899447441,602891725),new Word64(3049323471,3964484399),new Word64(3921009573,2173295548),new Word64(961987163,4081628472),new Word64(1508970993,3053834265),new Word64(2453635748,2937671579),new Word64(2870763221,3664609560),new Word64(3624381080,2734883394),new Word64(310598401,1164996542),new Word64(607225278,1323610764),new Word64(1426881987,3590304994),new Word64(1925078388,4068182383),new Word64(2162078206,991336113),new Word64(2614888103,633803317),new Word64(3248222580,3479774868),new Word64(3835390401,2666613458),new Word64(4022224774,944711139),new Word64(264347078,2341262773),new Word64(604807628,2007800933),new Word64(770255983,1495990901),new Word64(1249150122,1856431235),new Word64(1555081692,3175218132),new Word64(1996064986,2198950837),new Word64(2554220882,3999719339),new Word64(2821834349,766784016),new Word64(2952996808,2566594879),new Word64(3210313671,3203337956),new Word64(3336571891,1034457026),new Word64(3584528711,2466948901),new Word64(113926993,3758326383),new Word64(338241895,168717936),new Word64(666307205,1188179964),new Word64(773529912,1546045734),new Word64(1294757372,1522805485),new Word64(1396182291,2643833823),new Word64(1695183700,2343527390),new Word64(1986661051,1014477480),new Word64(2177026350,1206759142),new Word64(2456956037,344077627),new Word64(2730485921,1290863460),new Word64(2820302411,3158454273),new Word64(3259730800,3505952657),new Word64(3345764771,106217008),new Word64(3516065817,3606008344),new Word64(3600352804,1432725776),new Word64(4094571909,1467031594),new Word64(275423344,851169720),new Word64(430227734,3100823752),new Word64(506948616,1363258195),new Word64(659060556,3750685593),new Word64(883997877,3785050280),new Word64(958139571,3318307427),new Word64(1322822218,3812723403),new Word64(1537002063,2003034995),new Word64(1747873779,3602036899),new Word64(1955562222,1575990012),new Word64(2024104815,1125592928),new Word64(2227730452,2716904306),new Word64(2361852424,442776044),new Word64(2428436474,593698344),new Word64(2756734187,3733110249),new Word64(3204031479,2999351573),new Word64(3329325298,3815920427),new Word64(3391569614,3928383900),new Word64(3515267271,566280711),new Word64(3940187606,3454069534),new Word64(4118630271,4000239992),new Word64(116418474,1914138554),new Word64(174292421,2731055270),new Word64(289380356,3203993006),new Word64(460393269,320620315),new Word64(685471733,587496836),new Word64(852142971,1086792851),new Word64(1017036298,365543100),new Word64(1126000580,2618297676),new Word64(1288033470,3409855158),new Word64(1501505948,4234509866),new Word64(1607167915,987167468),new Word64(1816402316,1246189591)];return function(data,offset,length,mode384=!1){let h0,h1,h2,h3,h4,h5,h6,h7;h7=mode384?(h0=new Word64(3418070365,3238371032),h1=new Word64(1654270250,914150663),h2=new Word64(2438529370,812702999),h3=new Word64(355462360,4144912697),h4=new Word64(1731405415,4290775857),h5=new Word64(2394180231,1750603025),h6=new Word64(3675008525,1694076839),new Word64(1203062813,3204075428)):(h0=new Word64(1779033703,4089235720),h1=new Word64(3144134277,2227873595),h2=new Word64(1013904242,4271175723),h3=new Word64(2773480762,1595750129),h4=new Word64(1359893119,2917565137),h5=new Word64(2600822924,725511199),h6=new Word64(528734635,4215389547),new Word64(1541459225,327033209));var paddedLength=128*Math.ceil((length+17)/128),padded=new Uint8Array(paddedLength);let i,j;for(i=0;i>>29&255,padded[i++]=length>>21&255,padded[i++]=length>>13&255,padded[i++]=length>>5&255,padded[i++]=length<<3&255;var w=new Array(80);for(i=0;i<80;i++)w[i]=new Word64(0,0);let a=new Word64(0,0),b=new Word64(0,0),c=new Word64(0,0),d=new Word64(0,0),e=new Word64(0,0),f=new Word64(0,0),g=new Word64(0,0),h=new Word64(0,0);var t1=new Word64(0,0),t2=new Word64(0,0),tmp1=new Word64(0,0),tmp2=new Word64(0,0);let tmp3;for(i=0;i>>8^s1<<24^s2>>>16^s2<<16^s3>>>24^s3<<8,state[j]=t>>>24&255,state[j+1]=t>>16&255,state[j+2]=t>>8&255,state[j+3]=255&t}}t=state[13],state[13]=state[9],state[9]=state[5],state[5]=state[1],state[1]=t,t=state[14],u=state[10],state[14]=state[6],state[10]=state[2],state[6]=t,state[2]=u,t=state[15],u=state[11],v=state[7],state[15]=state[3],state[11]=t,state[7]=u,state[3]=v;for(let j=0;j<16;++j)state[j]=this._inv_s[state[j]],state[j]^=key[j];return state}_encrypt(input,key){var s=this._s;let t,u,v;var state=new Uint8Array(16);state.set(input);for(let j=0;j<16;++j)state[j]^=key[j];for(let i=1;i=ii;--i)if(lastBlock[i]!==psLen){psLen=0;break}outputLength-=psLen,result[result.length-1]=lastBlock.subarray(0,16-psLen)}}var output=new Uint8Array(outputLength);for(let i=0,j=0,ii=result.length;ii-32;){var combinedLength=password.length+k.length+userBytes.length,combinedArray=new Uint8Array(combinedLength),writeOffset=0,k1=(combinedArray.set(password,0),writeOffset+=password.length,combinedArray.set(k,writeOffset),writeOffset+=k.length,combinedArray.set(userBytes,writeOffset),new Uint8Array(64*combinedLength));for(let j=0,pos=0;j<64;j++,pos+=combinedLength)k1.set(combinedArray,pos);writeOffset=new AES128Cipher(k.subarray(0,16)),writeOffset=(e=writeOffset.encrypt(k1,k.subarray(16,32))).slice(0,16).reduce((a,b)=>a+b,0)%3;0==writeOffset?k=calculateSHA256(e,0,e.length):1==writeOffset?k=calculateSHA384(e,0,e.length):2==writeOffset&&(k=calculateSHA512(e,0,e.length)),i++}return k.subarray(0,32)}checkOwnerPassword(password,ownerValidationSalt,userBytes,ownerPassword){var hashData=new Uint8Array(password.length+56),ownerValidationSalt=(hashData.set(password,0),hashData.set(ownerValidationSalt,password.length),hashData.set(userBytes,password.length+ownerValidationSalt.length),this._hash(password,hashData,userBytes));return isArrayEqual(ownerValidationSalt,ownerPassword)}checkUserPassword(password,userValidationSalt,userPassword){var hashData=new Uint8Array(password.length+8),userValidationSalt=(hashData.set(password,0),hashData.set(userValidationSalt,password.length),this._hash(password,hashData,[]));return isArrayEqual(userValidationSalt,userPassword)}getOwnerKey(password,ownerKeySalt,userBytes,ownerEncryption){var hashData=new Uint8Array(password.length+56),ownerKeySalt=(hashData.set(password,0),hashData.set(ownerKeySalt,password.length),hashData.set(userBytes,password.length+ownerKeySalt.length),this._hash(password,hashData,userBytes));return new AES256Cipher(ownerKeySalt).decryptBlock(ownerEncryption,!1,new Uint8Array(16))}getUserKey(password,userKeySalt,userEncryption){var hashData=new Uint8Array(password.length+8),userKeySalt=(hashData.set(password,0),hashData.set(userKeySalt,password.length),this._hash(password,hashData,[]));return new AES256Cipher(userKeySalt).decryptBlock(userEncryption,!1,new Uint8Array(16))}}class CipherTransform{constructor(stringCipherConstructor,streamCipherConstructor){this.StringCipherConstructor=stringCipherConstructor,this.StreamCipherConstructor=streamCipherConstructor}createStream(stream,length){const cipher=new this.StreamCipherConstructor;return new DecryptStream(stream,length,function(data,finalize){return cipher.decryptBlock(data,finalize)})}decryptString(s){var cipher=new this.StringCipherConstructor,s=stringToBytes(s);return bytesToString(cipher.decryptBlock(s,!0))}encryptString(s){var cipher=new this.StringCipherConstructor;if(cipher instanceof AESBaseCipher){var pad=16-s.length%16,iv=(s+=String.fromCharCode(pad).repeat(pad),new Uint8Array(16));if("undefined"!=typeof crypto)crypto.getRandomValues(iv);else for(let i=0;i<16;i++)iv[i]=Math.floor(256*Math.random());let data=stringToBytes(s);data=cipher.encrypt(data,iv);pad=new Uint8Array(16+data.length);return pad.set(iv),pad.set(data,16),bytesToString(pad)}pad=stringToBytes(s);return bytesToString(cipher.encrypt(pad))}}class CipherTransformFactory{static#defaultPasswordBytes=new Uint8Array([40,191,78,94,78,117,138,65,100,0,78,86,255,250,1,8,46,46,0,182,208,104,62,128,47,12,169,254,100,83,105,122]);#createEncryptionKey20(revision,password,ownerPassword,ownerValidationSalt,ownerKeySalt,uBytes,userPassword,userValidationSalt,userKeySalt,ownerEncryption,userEncryption,perms){password=password?(passwordLength=Math.min(127,password.length),password.subarray(0,passwordLength)):[];var passwordLength=new(6===revision?PDF20:PDF17);return passwordLength.checkUserPassword(password,userValidationSalt,userPassword)?passwordLength.getUserKey(password,userKeySalt,userEncryption):password.length&&passwordLength.checkOwnerPassword(password,ownerValidationSalt,uBytes,ownerPassword)?passwordLength.getOwnerKey(password,ownerKeySalt,uBytes,ownerEncryption):null}#prepareKeyData(fileId,password,ownerPassword,userPassword,flags,revision,keyLength,encryptMetadata){var hashDataSize=40+ownerPassword.length+fileId.length,hashData=new Uint8Array(hashDataSize);let i=0,j,n;if(password)for(n=Math.min(32,password.length);i>8&255,hashData[i++]=flags>>16&255,hashData[i++]=flags>>>24&255,j=0,n=fileId.length;j>3;if(3<=revision)for(j=0;j<50;++j)hash=calculateMD5(hash,0,keyLengthInBytes);var encryptionKey=hash.subarray(0,keyLengthInBytes);let cipher,checkData;if(3<=revision){for(i=0;i<32;++i)hashData[i]=CipherTransformFactory.#defaultPasswordBytes[i];for(j=0,n=fileId.length;j>3;if(3<=revision)for(j=0;j<50;++j)hash=calculateMD5(hash,0,hash.length);let cipher,userPassword;if(3<=revision){userPassword=ownerPassword;var derivedKey=new Uint8Array(keyLengthInBytes);for(j=19;0<=j;j--){for(let k=0;k>8&255,key[i++]=num>>16&255,key[i++]=255&gen,key[i++]=gen>>8&255,isAes&&(key[i++]=115,key[i++]=65,key[i++]=108,key[i++]=84),calculateMD5(key,0,i).subarray(0,Math.min(encryptionKey.length+5,16))}#buildCipherConstructor(cf,name,num,gen,key){if(!(name instanceof Name))throw new FormatError("Invalid crypt filter name.");const self=this;cf=cf.get(name.name)?.get("CFM");if(!cf||"None"===cf.name)return function(){return new NullCipher};if("V2"===cf.name)return function(){return new ARCFourCipher(self.#buildObjectKey(num,gen,key,!1))};if("AESV2"===cf.name)return function(){return new AES128Cipher(self.#buildObjectKey(num,gen,key,!0))};if("AESV3"===cf.name)return function(){return new AES256Cipher(key)};throw new FormatError("Unknown crypto method")}constructor(dict,fileId,password){var filter=dict.get("Filter");if(!isName(filter,"Standard"))throw new FormatError("unknown encryption method");this.filterName=filter.name;filter=(this.dict=dict).get("V");if(!Number.isInteger(filter)||1!==filter&&2!==filter&&4!==filter&&5!==filter)throw new FormatError("unsupported encryption algorithm");this.algorithm=filter;let keyLength=dict.get("Length");if(keyLength||(filter<=3?keyLength=40:(cfDict=dict.get("CF"),streamCryptoName=dict.get("StmF"),cfDict instanceof Dict&&streamCryptoName instanceof Name&&(cfDict.suppressEncryption=!0,cfDict=cfDict.get(streamCryptoName.name),(keyLength=cfDict?.get("Length")||128)<40)&&(keyLength<<=3))),!Number.isInteger(keyLength)||keyLength<40||keyLength%8!=0)throw new FormatError("invalid key length");var uBytes,userValidationSalt,ownerEncryption,userEncryption,perms,ownerValidationSalt,streamCryptoName=stringToBytes(dict.get("O")),cfDict=stringToBytes(dict.get("U")),ownerPassword=streamCryptoName.subarray(0,32),userPassword=cfDict.subarray(0,32),flags=dict.get("P"),revision=dict.get("R"),encryptMetadata=(4===filter||5===filter)&&!1!==dict.get("EncryptMetadata"),fileId=(this.encryptMetadata=encryptMetadata,stringToBytes(fileId));let passwordBytes;if(password){if(6===revision)try{password=utf8StringToString(password)}catch{warn("CipherTransformFactory: Unable to convert UTF8 encoded password.")}passwordBytes=stringToBytes(password)}let encryptionKey;if(!(encryptionKey=5!==filter?this.#prepareKeyData(fileId,passwordBytes,ownerPassword,userPassword,flags,revision,keyLength,encryptMetadata):(ownerValidationSalt=streamCryptoName.subarray(32,40),streamCryptoName=streamCryptoName.subarray(40,48),uBytes=cfDict.subarray(0,48),userValidationSalt=cfDict.subarray(32,40),cfDict=cfDict.subarray(40,48),ownerEncryption=stringToBytes(dict.get("OE")),userEncryption=stringToBytes(dict.get("UE")),perms=stringToBytes(dict.get("Perms")),this.#createEncryptionKey20(revision,passwordBytes,ownerPassword,ownerValidationSalt,streamCryptoName,uBytes,userPassword,userValidationSalt,cfDict,ownerEncryption,userEncryption,perms)))&&!password)throw new PasswordException("No password given",PasswordResponses.NEED_PASSWORD);if(!encryptionKey&&password&&(ownerValidationSalt=this.#decodeUserPassword(passwordBytes,ownerPassword,revision,keyLength),encryptionKey=this.#prepareKeyData(fileId,ownerValidationSalt,ownerPassword,userPassword,flags,revision,keyLength,encryptMetadata)),!encryptionKey)throw new PasswordException("Incorrect Password",PasswordResponses.INCORRECT_PASSWORD);this.encryptionKey=encryptionKey,4<=filter&&((streamCryptoName=dict.get("CF"))instanceof Dict&&(streamCryptoName.suppressEncryption=!0),this.cf=streamCryptoName,this.stmf=dict.get("StmF")||Name.get("Identity"),this.strf=dict.get("StrF")||Name.get("Identity"),this.eff=dict.get("EFF")||this.stmf)}createCipherTransform(num,gen){if(4===this.algorithm||5===this.algorithm)return new CipherTransform(this.#buildCipherConstructor(this.cf,this.strf,num,gen,this.encryptionKey),this.#buildCipherConstructor(this.cf,this.stmf,num,gen,this.encryptionKey));const key=this.#buildObjectKey(num,gen,this.encryptionKey,!1);function cipherConstructor(){return new ARCFourCipher(key)}return new CipherTransform(cipherConstructor,cipherConstructor)}}async function writeObject(ref,obj,buffer,{encrypt=null}){encrypt=encrypt?.createCipherTransform(ref.num,ref.gen);buffer.push(`${ref.num} ${ref.gen} obj\n`),obj instanceof Dict?await writeDict(obj,buffer,encrypt):obj instanceof BaseStream?await writeStream(obj,buffer,encrypt):(Array.isArray(obj)||ArrayBuffer.isView(obj))&&await writeArray(obj,buffer,encrypt),buffer.push("\nendobj\n")}async function writeDict(dict,buffer,transform){buffer.push("<<");for(const key of dict.getKeys())buffer.push(` /${escapePDFName(key)} `),await writeValue(dict.getRaw(key),buffer,transform);buffer.push(">>")}async function writeStream(stream,buffer,transform){let bytes=stream.getBytes();var stream=stream["dict"],[filter,params]=await Promise.all([stream.getAsync("Filter"),stream.getAsync("DecodeParms")]),isFilterZeroFlateDecode=isName(Array.isArray(filter)?await stream.xref.fetchIfRefAsync(filter[0]):filter,"FlateDecode");if(256<=bytes.length||isFilterZeroFlateDecode)try{var cs=new CompressionStream("deflate"),writer=cs.writable.getWriter(),buf=(writer.write(bytes),writer.close(),await new Response(cs.readable).arrayBuffer());bytes=new Uint8Array(buf);let newFilter,newParams;filter?isFilterZeroFlateDecode||(newFilter=Array.isArray(filter)?[Name.get("FlateDecode"),...filter]:[Name.get("FlateDecode"),filter],params&&(newParams=Array.isArray(params)?[null,...params]:[null,params])):newFilter=Name.get("FlateDecode"),newFilter&&stream.set("Filter",newFilter),newParams&&stream.set("DecodeParms",newParams)}catch(ex){info(`writeStream - cannot compress data: "${ex}".`)}let string=bytesToString(bytes);transform&&(string=transform.encryptString(string)),stream.set("Length",string.length),await writeDict(stream,buffer,transform),buffer.push(" stream\n",string,"\nendstream")}async function writeArray(array,buffer,transform){buffer.push("[");let first=!0;for(const val of array)first?first=!1:buffer.push(" "),await writeValue(val,buffer,transform);buffer.push("]")}async function writeValue(value,buffer,transform){value instanceof Name?buffer.push("/"+escapePDFName(value.name)):value instanceof Ref?buffer.push(`${value.num} ${value.gen} R`):Array.isArray(value)||ArrayBuffer.isView(value)?await writeArray(value,buffer,transform):"string"==typeof value?(transform&&(value=transform.encryptString(value)),buffer.push(`(${escapeString(value)})`)):"number"==typeof value?buffer.push(numberToString(value)):"boolean"==typeof value?buffer.push(value.toString()):value instanceof Dict?await writeDict(value,buffer,transform):value instanceof BaseStream?await writeStream(value,buffer,transform):null===value?buffer.push("null"):warn(`Unhandled value in writer: ${typeof value}, please file a bug.`)}function writeInt(number,size,offset,buffer){for(let i=size+offset-1;i>offset-1;i--)buffer[i]=255&number,number>>=8;return offset+size}function writeString(string,offset,buffer){for(let i=0,len=string.length;ia+str.length,0);for(const value of Object.values(xrefInfo.info))md5Buffer.push(value),md5BufferLen+=value.length;var array=new Uint8Array(md5BufferLen);let offset=0;for(const str of md5Buffer)writeString(str,offset,array),offset+=str.length;return bytesToString(calculateMD5(array))}function writeXFADataForAcroform(str,newRefs){var xfa,xml=new SimpleXMLParser({hasAttributes:!0}).parseFromString(str);for({xfa}of newRefs)if(xfa){var{path,value}=xfa;if(path){var nodePath=parseXFAPath(path);let node=xml.documentElement.searchNode(nodePath,0);(node=!node&&1new SimpleDOMNode("value",val)):[new SimpleDOMNode("#text",value)]:warn("Node not found for path: "+path)}}str=[];return xml.documentElement.dump(str),str.join("")}async function updateAcroform({xref,acroForm,acroFormRef,hasXfa,hasXfaDatasetsEntry,xfaDatasetsRef,needAppearances,newRefs}){var dict;!hasXfa||hasXfaDatasetsEntry||xfaDatasetsRef||warn("XFA - Cannot save it"),(needAppearances||hasXfa&&xfaDatasetsRef&&!hasXfaDatasetsEntry)&&(dict=acroForm.clone(),hasXfa&&!hasXfaDatasetsEntry&&((hasXfa=acroForm.get("XFA").slice()).splice(2,0,"datasets"),hasXfa.splice(3,0,xfaDatasetsRef),dict.set("XFA",hasXfa)),needAppearances&&dict.set("NeedAppearances",!0),await writeObject(acroFormRef,dict,hasXfaDatasetsEntry=[],xref),newRefs.push({ref:acroFormRef,data:hasXfaDatasetsEntry.join("")}))}function updateXFA({xfaData,xfaDatasetsRef,newRefs,xref}){null===xfaData&&(xfaData=writeXFADataForAcroform(xref.fetchIfRef(xfaDatasetsRef).getString(),newRefs));xref=xref.encrypt,xref&&(xfaData=xref.createCipherTransform(xfaDatasetsRef.num,xfaDatasetsRef.gen).encryptString(xfaData)),xref=`${xfaDatasetsRef.num} ${xfaDatasetsRef.gen} obj\n`+`<< /Type /EmbeddedFile /Length ${xfaData.length}>> -stream -`+xfaData+"\nendstream\nendobj\n";newRefs.push({ref:xfaDatasetsRef,data:xref})}async function getXRefTable(xrefInfo,baseOffset,newRefs,newXref,buffer){buffer.push("xref\n");var ref,data,indexes=getIndexes(newRefs);let indexesPosition=0;for({ref,data}of newRefs)ref.num===indexes[indexesPosition]&&(buffer.push(`${indexes[indexesPosition]} ${indexes[indexesPosition+1]}\n`),indexesPosition+=2),null!==data?(buffer.push(`${baseOffset.toString().padStart(10,"0")} ${Math.min(ref.gen,65535).toString().padStart(5,"0")} n\r\n`),baseOffset+=data.length):buffer.push(`0000000000 ${Math.min(ref.gen+1,65535).toString().padStart(5,"0")} f\r -`);computeIDs(baseOffset,xrefInfo,newXref),buffer.push("trailer\n"),await writeDict(newXref,buffer),buffer.push("\nstartxref\n",baseOffset.toString(),"\n%%EOF\n")}function getIndexes(newRefs){var ref,indexes=[];for({ref}of newRefs)ref.num===indexes.at(-2)+indexes.at(-1)?indexes[indexes.length-1]+=1:indexes.push(ref.num,1);return indexes}async function getXRefStreamTable(xrefInfo,baseOffset,newRefs,newXref,buffer){var xrefTableData=[];let maxOffset=0,maxGen=0;for(const{ref,data}of newRefs){let gen;maxOffset=Math.max(maxOffset,baseOffset),null!==data?(gen=Math.min(ref.gen,65535),xrefTableData.push([1,baseOffset,gen]),baseOffset+=data.length):(gen=Math.min(ref.gen+1,65535),xrefTableData.push([0,0,gen])),maxGen=Math.max(maxGen,gen)}newXref.set("Index",getIndexes(newRefs));var sizes=[1,getSizeInBytes(maxOffset),getSizeInBytes(maxGen)],newRefs=(newXref.set("W",sizes),computeIDs(baseOffset,xrefInfo,newXref),sizes.reduce((a,x)=>a+x,0));const data=new Uint8Array(newRefs*xrefTableData.length);var type,objOffset,gen,newRefs=new Stream(data);newRefs.dict=newXref;let offset=0;for([type,objOffset,gen]of xrefTableData)offset=writeInt(type,sizes[0],offset,data),offset=writeInt(objOffset,sizes[1],offset,data),offset=writeInt(gen,sizes[2],offset,data);await writeObject(xrefInfo.newRef,newRefs,buffer,{}),buffer.push("startxref\n",baseOffset.toString(),"\n%%EOF\n")}function computeIDs(baseOffset,xrefInfo,newXref){Array.isArray(xrefInfo.fileIds)&&0a.ref.num-b.ref.num))null!==data&&buffer.push(data);await(useXrefStream?getXRefStreamTable:getXRefTable)(xrefInfo,baseOffset,newRefs,acroFormRef,buffer);var hasXfaDatasetsEntry=buffer.reduce((a,str)=>a+str.length,originalData.length),array=new Uint8Array(hasXfaDatasetsEntry);array.set(originalData);let offset=originalData.length;for(const str of buffer)writeString(str,offset,array),offset+=str.length;return array}const MAX_DEPTH=40,StructElementType={PAGE_CONTENT:1,STREAM_CONTENT:2,OBJECT:3,ANNOTATION:4,ELEMENT:5};class StructTreeRoot{constructor(rootDict,rootRef){this.dict=rootDict,this.ref=rootRef instanceof Ref?rootRef:null,this.roleMap=new Map,this.structParentIds=null}init(){this.readRoleMap()}#addIdToPage(pageRef,id,type){if(pageRef instanceof Ref&&!(id<0)){this.structParentIds||=new RefSetCache;let ids=this.structParentIds.get(pageRef);ids||(ids=[],this.structParentIds.put(pageRef,ids)),ids.push([id,type])}}addAnnotationIdToPage(pageRef,id){this.#addIdToPage(pageRef,id,StructElementType.ANNOTATION)}readRoleMap(){var roleMapDict=this.dict.get("RoleMap");roleMapDict instanceof Dict&&roleMapDict.forEach((key,value)=>{value instanceof Name&&this.roleMap.set(key,value.name)})}static async canCreateStructureTree({catalogRef,pdfManager,newAnnotationsByPage}){if(!(catalogRef instanceof Ref))return warn("Cannot save the struct tree: no catalog reference."),!1;let nextKey=0,hasNothingToUpdate=!0;for(var[pageIndex,elements]of newAnnotationsByPage){var pageRef=(await pdfManager.getPage(pageIndex))["ref"];if(!(pageRef instanceof Ref)){warn(`Cannot save the struct tree: page ${pageIndex} has no ref.`),hasNothingToUpdate=!0;break}for(const element of elements)element.accessibilityData?.type&&(element.parentTreeId=nextKey++,hasNothingToUpdate=!1)}if(hasNothingToUpdate){for(const elements of newAnnotationsByPage.values())for(const element of elements)delete element.parentTreeId;return!1}return!0}static async createStructureTree({newAnnotationsByPage,xref,catalogRef,pdfManager,newRefs}){var ref,obj,root=pdfManager.catalog.cloneDict(),cache=new RefSetCache,catalogRef=(cache.put(catalogRef,root),xref.getNewTemporaryRef()),root=(root.set("StructTreeRoot",catalogRef),new Dict(xref)),parentTreeRef=(root.set("Type",Name.get("StructTreeRoot")),xref.getNewTemporaryRef()),kids=(root.set("ParentTree",parentTreeRef),[]),parentTree=(root.set("K",kids),cache.put(catalogRef,root),new Dict(xref)),nums=[],newAnnotationsByPage=(parentTree.set("Nums",nums),await this.#writeKids({newAnnotationsByPage:newAnnotationsByPage,structTreeRootRef:catalogRef,kids:kids,nums:nums,xref:xref,pdfManager:pdfManager,cache:cache})),buffer=(root.set("ParentTreeNextKey",newAnnotationsByPage),cache.put(parentTreeRef,parentTree),[]);for([ref,obj]of cache.items())buffer.length=0,await writeObject(ref,obj,buffer,xref),newRefs.push({ref:ref,data:buffer.join("")})}async canUpdateStructTree({pdfManager,xref,newAnnotationsByPage}){if(!this.ref)return warn("Cannot update the struct tree: no root reference."),!1;let nextKey=this.dict.get("ParentTreeNextKey");if(!Number.isInteger(nextKey)||nextKey<0)return warn("Cannot update the struct tree: invalid next key."),!1;var parentTree=this.dict.get("ParentTree");if(!(parentTree instanceof Dict))return warn("Cannot update the struct tree: ParentTree isn't a dict."),!1;var nums=parentTree.get("Nums");if(!Array.isArray(nums))return warn("Cannot update the struct tree: nums isn't an array."),!1;var pageIndex,elements,numberTree=new NumberTree(parentTree,xref);for(const pageIndex of newAnnotationsByPage.keys()){var pageDict=(await pdfManager.getPage(pageIndex))["pageDict"];if(pageDict.has("StructParents")){pageDict=pageDict.get("StructParents");if(!Number.isInteger(pageDict)||!Array.isArray(numberTree.get(pageDict)))return warn(`Cannot save the struct tree: page ${pageIndex} has a wrong id.`),!1}}let hasNothingToUpdate=!0;for([pageIndex,elements]of newAnnotationsByPage){const pageDict=(await pdfManager.getPage(pageIndex))["pageDict"];StructTreeRoot.#collectParents({elements:elements,xref:this.dict.xref,pageDict:pageDict,numberTree:numberTree});for(const element of elements)element.accessibilityData?.type&&(element.parentTreeId=nextKey++,hasNothingToUpdate=!1)}if(hasNothingToUpdate){for(const elements of newAnnotationsByPage.values())for(const element of elements)delete element.parentTreeId,delete element.structTreeParent;return!1}return!0}async updateStructureTree({newAnnotationsByPage,pdfManager,newRefs}){var xref=this.dict.xref,structTreeRoot=this.dict.clone(),structTreeRootRef=this.ref,cache=new RefSetCache;cache.put(structTreeRootRef,structTreeRoot);let parentTreeRef=structTreeRoot.getRaw("ParentTree"),parentTree,nums=(parentTreeRef instanceof Ref?parentTree=xref.fetch(parentTreeRef):(parentTree=parentTreeRef,parentTreeRef=xref.getNewTemporaryRef(),structTreeRoot.set("ParentTree",parentTreeRef)),parentTree=parentTree.clone(),cache.put(parentTreeRef,parentTree),parentTree.getRaw("Nums")),numsRef=null;nums instanceof Ref&&(numsRef=nums,nums=xref.fetch(numsRef)),nums=nums.slice(),numsRef||parentTree.set("Nums",nums);var ref,obj,newAnnotationsByPage=await StructTreeRoot.#writeKids({newAnnotationsByPage:newAnnotationsByPage,structTreeRootRef:structTreeRootRef,kids:null,nums:nums,xref:xref,pdfManager:pdfManager,cache:cache}),buffer=(structTreeRoot.set("ParentTreeNextKey",newAnnotationsByPage),numsRef&&cache.put(numsRef,nums),[]);for([ref,obj]of cache.items())buffer.length=0,await writeObject(ref,obj,buffer,xref),newRefs.push({ref:ref,data:buffer.join("")})}static async#writeKids({newAnnotationsByPage,structTreeRootRef,kids,nums,xref,pdfManager,cache}){var pageIndex,elements,objr=Name.get("OBJR");let nextKey=-1/0;for([pageIndex,elements]of newAnnotationsByPage){var accessibilityData,ref,parentTreeId,structTreeParent,title,lang,alt,expanded,actualText,tagRef,tagDict,type,pageRef=(await pdfManager.getPage(pageIndex))["ref"],isPageRef=pageRef instanceof Ref;for({accessibilityData,ref,parentTreeId,structTreeParent}of elements)accessibilityData?.type&&({type,title,lang,alt,expanded,actualText}=accessibilityData,nextKey=Math.max(nextKey,parentTreeId),tagRef=xref.getNewTemporaryRef(),(tagDict=new Dict(xref)).set("S",Name.get(type)),title&&tagDict.set("T",title),lang&&tagDict.set("Lang",lang),alt&&tagDict.set("Alt",alt),expanded&&tagDict.set("E",expanded),actualText&&tagDict.set("ActualText",actualText),await this.#updateParentTag({structTreeParent:structTreeParent,tagDict:tagDict,newTagRef:tagRef,structTreeRootRef:structTreeRootRef,fallbackKids:kids,xref:xref,cache:cache}),type=new Dict(xref),tagDict.set("K",type),type.set("Type",objr),isPageRef&&type.set("Pg",pageRef),type.set("Obj",ref),cache.put(tagRef,tagDict),nums.push(parentTreeId,tagRef))}return nextKey+1}static#collectParents({elements,xref,pageDict,numberTree}){const idToElements=new Map;for(const element of elements)if(element.structTreeParentId){const id=parseInt(element.structTreeParentId.split("_mc")[1],10);let elems=idToElements.get(id);elems||(elems=[],idToElements.set(id,elems)),elems.push(element)}const id=pageDict.get("StructParents");if(Number.isInteger(id)){var updateElement=(kid,pageKid,kidRef)=>{kid=idToElements.get(kid);if(kid){var parentRef=pageKid.getRaw("P"),parentDict=xref.fetchIfRef(parentRef);if(parentRef instanceof Ref&&parentDict instanceof Dict){var params={ref:kidRef,dict:pageKid};for(const element of kid)element.structTreeParent=params}return!0}return!1};for(const kidRef of numberTree.get(id))if(kidRef instanceof Ref){var pageKid=xref.fetch(kidRef),k=pageKid.get("K");if(Number.isInteger(k))updateElement(k,pageKid,kidRef);else if(Array.isArray(k))for(var kid of k){if(kid=xref.fetchIfRef(kid),Number.isInteger(kid)&&updateElement(kid,pageKid,kidRef))break;if(kid instanceof Dict){if(!isName(kid.get("Type"),"MCR"))break;kid=kid.get("MCID");if(Number.isInteger(kid)&&updateElement(kid,pageKid,kidRef))break}}}}}static async#updateParentTag({structTreeParent,tagDict,newTagRef,structTreeRootRef,fallbackKids,xref,cache}){let ref=null,parentRef;parentRef=structTreeParent&&({ref}=structTreeParent,structTreeParent.dict.getRaw("P"))||structTreeRootRef,tagDict.set("P",parentRef);structTreeParent=xref.fetchIfRef(parentRef);if(structTreeParent){let cachedParentDict=cache.get(parentRef);cachedParentDict||(cachedParentDict=structTreeParent.clone(),cache.put(parentRef,cachedParentDict));structTreeRootRef=cachedParentDict.getRaw("K");let cachedParentKids=structTreeRootRef instanceof Ref?cache.get(structTreeRootRef):null;cachedParentKids||(cachedParentKids=xref.fetchIfRef(structTreeRootRef),cachedParentKids=Array.isArray(cachedParentKids)?cachedParentKids.slice():[structTreeRootRef],tagDict=xref.getNewTemporaryRef(),cachedParentDict.set("K",tagDict),cache.put(tagDict,cachedParentKids));structTreeParent=cachedParentKids.indexOf(ref);cachedParentKids.splice(0<=structTreeParent?structTreeParent+1:cachedParentKids.length,0,newTagRef)}else fallbackKids.push(newTagRef)}}class StructElementNode{constructor(tree,dict){this.tree=tree,this.dict=dict,this.kids=[],this.parseKids()}get role(){var nameObj=this.dict.get("S"),nameObj=nameObj instanceof Name?nameObj.name:"",root=this.tree["root"];return root.roleMap.has(nameObj)?root.roleMap.get(nameObj):nameObj}parseKids(){let pageObjId=null;var objRef=this.dict.getRaw("Pg"),objRef=(objRef instanceof Ref&&(pageObjId=objRef.toString()),this.dict.get("K"));if(Array.isArray(objRef))for(const kid of objRef){var element=this.parseKid(pageObjId,kid);element&&this.kids.push(element)}else{const element=this.parseKid(pageObjId,objRef);element&&this.kids.push(element)}}parseKid(pageObjId,kid){if(Number.isInteger(kid))return this.tree.pageDict.objId!==pageObjId?null:new StructElement({type:StructElementType.PAGE_CONTENT,mcid:kid,pageObjId:pageObjId});let kidDict=null;if(kid instanceof Ref?kidDict=this.dict.xref.fetch(kid):kid instanceof Dict&&(kidDict=kid),!kidDict)return null;var kidRef,kid=kidDict.getRaw("Pg"),kid=(kid instanceof Ref&&(pageObjId=kid.toString()),kidDict.get("Type")instanceof Name?kidDict.get("Type").name:null);if("MCR"===kid)return this.tree.pageDict.objId!==pageObjId?null:(kidRef=kidDict.getRaw("Stm"),new StructElement({type:StructElementType.STREAM_CONTENT,refObjId:kidRef instanceof Ref?kidRef.toString():null,pageObjId:pageObjId,mcid:kidDict.get("MCID")}));if("OBJR"!==kid)return new StructElement({type:StructElementType.ELEMENT,dict:kidDict});{if(this.tree.pageDict.objId!==pageObjId)return null;const kidRef=kidDict.getRaw("Obj");return new StructElement({type:StructElementType.OBJECT,refObjId:kidRef instanceof Ref?kidRef.toString():null,pageObjId:pageObjId})}}}class StructElement{constructor({type,dict=null,mcid=null,pageObjId=null,refObjId=null}){this.type=type,this.dict=dict,this.mcid=mcid,this.pageObjId=pageObjId,this.refObjId=refObjId,this.parentNode=null}}class StructTreePage{constructor(structTreeRoot,pageDict){this.root=structTreeRoot,this.rootDict=structTreeRoot?structTreeRoot.dict:null,this.pageDict=pageDict,this.nodes=[]}parse(pageRef){if(this.root&&this.rootDict){var parentTree=this.rootDict.get("ParentTree");if(parentTree){var id=this.pageDict.get("StructParents"),pageRef=pageRef instanceof Ref&&this.root.structParentIds?.get(pageRef);if(Number.isInteger(id)||pageRef){var map=new Map,numberTree=new NumberTree(parentTree,this.rootDict.xref);if(Number.isInteger(id)){parentTree=numberTree.get(id);if(Array.isArray(parentTree))for(const ref of parentTree)ref instanceof Ref&&this.addNode(this.rootDict.xref.fetch(ref),map)}if(pageRef)for(var[elemId,type]of pageRef){var elemId=numberTree.get(elemId);elemId&&1===(elemId=this.addNode(this.rootDict.xref.fetchIfRef(elemId),map))?.kids?.length&&elemId.kids[0].type===StructElementType.OBJECT&&(elemId.kids[0].type=type)}}}}}addNode(dict,map,level=0){if(level>MAX_DEPTH)return warn("StructTree MAX_DEPTH reached."),null;if(map.has(dict))return map.get(dict);var element=new StructElementNode(this,dict),parent=(map.set(dict,element),dict.get("P"));if(!parent||isName(parent.get("Type"),"StructTreeRoot"))this.addTopLevelNode(dict,element)||map.delete(dict);else{parent=this.addNode(parent,map,level+1);if(parent){let save=!1;for(const kid of parent.kids)kid.type===StructElementType.ELEMENT&&kid.dict===dict&&(kid.parentNode=element,save=!0);save||map.delete(dict)}}return element}addTopLevelNode(dict,element){var obj=this.rootDict.get("K");if(!obj)return!1;if(obj instanceof Dict)return obj.objId===dict.objId&&(this.nodes[0]=element,!0);if(!Array.isArray(obj))return!0;let save=!1;for(let i=0;iMAX_DEPTH)warn("StructTree too deep to be fully serialized.");else{var obj=Object.create(null);obj.role=node.role,obj.children=[],parent.children.push(obj),"string"==typeof(parent=node.dict.get("Alt"))&&(obj.alt=stringToPDFString(parent)),"string"==typeof(parent=node.dict.get("Lang"))&&(obj.lang=stringToPDFString(parent));for(const kid of node.kids){var kidElement=kid.type===StructElementType.ELEMENT?kid.parentNode:null;kidElement?nodeToSerializable(kidElement,obj,level+1):kid.type===StructElementType.PAGE_CONTENT||kid.type===StructElementType.STREAM_CONTENT?obj.children.push({type:"content",id:`p${kid.pageObjId}_mc`+kid.mcid}):kid.type===StructElementType.OBJECT?obj.children.push({type:"object",id:kid.refObjId}):kid.type===StructElementType.ANNOTATION&&obj.children.push({type:"annotation",id:""+AnnotationPrefix+kid.refObjId})}}}(child,root);return root}}function isValidExplicitDest(dest){if(!Array.isArray(dest)||dest.length<2)return!1;var[dest,zoom,...args]=dest;if(!(dest instanceof Ref||Number.isInteger(dest)))return!1;if(!(zoom instanceof Name))return!1;let allowNull=!0;switch(zoom.name){case"XYZ":if(3!==args.length)return!1;break;case"Fit":case"FitB":return 0===args.length;case"FitH":case"FitBH":case"FitV":case"FitBV":if(1!==args.length)return!1;break;case"FitR":if(4!==args.length)return!1;allowNull=!1;break;default:return!1}for(const arg of args)if(!("number"==typeof arg||allowNull&&null===arg))return!1;return!0}function fetchDest(dest){return isValidExplicitDest(dest=dest instanceof Dict?dest.get("D"):dest)?dest:null}function fetchRemoteDest(action){let dest=action.get("D");if(dest){if("string"==typeof(dest=dest instanceof Name?dest.name:dest))return stringToPDFString(dest);if(isValidExplicitDest(dest))return JSON.stringify(dest)}return null}class Catalog{constructor(pdfManager,xref){if(this.pdfManager=pdfManager,this.xref=xref,this._catDict=xref.getCatalogObj(),!(this._catDict instanceof Dict))throw new FormatError("Catalog object is not a dictionary.");this.toplevelPagesDict,this._actualNumPages=null,this.fontCache=new RefSetCache,this.builtInCMapCache=new Map,this.standardFontDataCache=new Map,this.globalImageCache=new GlobalImageCache,this.pageKidsCountCache=new RefSetCache,this.pageIndexCache=new RefSetCache,this.nonBlendModesSet=new RefSet,this.systemFontCache=new Map}cloneDict(){return this._catDict.clone()}get version(){var version=this._catDict.get("Version");if(version instanceof Name){if(PDF_VERSION_REGEXP.test(version.name))return shadow(this,"version",version.name);warn("Invalid PDF catalog version: "+version.name)}return shadow(this,"version",null)}get lang(){var lang=this._catDict.get("Lang");return shadow(this,"lang","string"==typeof lang?stringToPDFString(lang):null)}get needsRendering(){var needsRendering=this._catDict.get("NeedsRendering");return shadow(this,"needsRendering","boolean"==typeof needsRendering&&needsRendering)}get collection(){let collection=null;try{var obj=this._catDict.get("Collection");obj instanceof Dict&&0i instanceof Name)&&(groupRef.intent=intent.map(i=>i.name));name=group.get("Usage");if(name instanceof Dict){var usageObj=groupRef.usage,group=name.get("Print");if(group instanceof Dict){var printState=group.get("PrintState");if(printState instanceof Name)switch(printState.name){case"ON":case"OFF":usageObj.print={printState:printState.name}}}group=name.get("View");if(group instanceof Dict){var viewState=group.get("ViewState");if(viewState instanceof Name)switch(viewState.name){case"ON":case"OFF":usageObj.view={viewState:viewState.name}}}}return groupRef}#readOptionalContentConfig(config,contentGroupRefs){function parseOnOff(refs){var onParsed=[];if(Array.isArray(refs))for(const value of refs)value instanceof Ref&&contentGroupRefs.has(value)&&onParsed.push(value.toString());return onParsed}function parseOrder(refs,nestedLevels=0){if(!Array.isArray(refs))return null;var nestedOrder,order=[];for(const value of refs)value instanceof Ref&&contentGroupRefs.has(value)?(parsedOrderRefs.put(value),order.push(value.toString())):(nestedOrder=function(ref,nestedLevels){if(++nestedLevels>MAX_NESTED_LEVELS)return warn("parseNestedOrder - reached MAX_NESTED_LEVELS."),null;ref=xref.fetchIfRef(ref);if(!Array.isArray(ref))return null;var nestedName=xref.fetchIfRef(ref[0]);if("string"!=typeof nestedName)return null;ref=parseOrder(ref.slice(1),nestedLevels);return ref&&ref.length?{name:stringToPDFString(nestedName),order:ref}:null}(value,nestedLevels))&&order.push(nestedOrder);if(!(0Number.isInteger(page)&&0=arr[i-1])&&page<=this.numPages)&&(prefValue=value);break;case"NumCopies":Number.isInteger(value)&&0=kids.length)queue.pop();else{var currentNode=kids[posInKids];let obj;if(currentNode instanceof Ref){if(visitedNodes.has(currentNode)){addPageError(new FormatError("Pages tree contains circular reference."));break}visitedNodes.put(currentNode);try{obj=await xref.fetchAsync(currentNode)}catch(ex){addPageError(ex);break}}else obj=currentNode;if(!(obj instanceof Dict)){addPageError(new FormatError("Page dictionary kid reference points to wrong type of object."));break}let type=obj.getRaw("Type");if(type instanceof Ref)try{type=await xref.fetchAsync(type)}catch(ex){addPageError(ex);break}isName(type,"Page")||!obj.has("Kids")?(posInKids=obj,(currentNode=currentNode instanceof Ref?currentNode:null)&&!pageIndexCache.has(currentNode)&&pageIndexCache.put(currentNode,pageIndex),map.set(pageIndex++,[posInKids,currentNode])):queue.push({currentNode:obj,posInKids:0}),queueItem.posInKids++}}return map}getPageIndex(pageRef){var cachedPageIndex=this.pageIndexCache.get(pageRef);if(void 0!==cachedPageIndex)return Promise.resolve(cachedPageIndex);const xref=this.xref;let total=0;const next=ref=>function(kidRef){let total=0,parentRef;return xref.fetchAsync(kidRef).then(function(node){if(isRefsEqual(kidRef,pageRef)&&!isDict(node,"Page")&&!(node instanceof Dict&&!node.has("Type")&&node.has("Contents")))throw new FormatError("The reference does not point to a /Page dictionary.");if(!node)return null;if(node instanceof Dict)return parentRef=node.getRaw("Parent"),node.getAsync("Parent");throw new FormatError("Node must be a dictionary.")}).then(function(parent){if(!parent)return null;if(parent instanceof Dict)return parent.getAsync("Kids");throw new FormatError("Parent must be a dictionary.")}).then(function(kids){if(!kids)return null;var kidPromises=[];let found=!1;for(const kid of kids){if(!(kid instanceof Ref))throw new FormatError("Kid must be a reference.");if(isRefsEqual(kid,kidRef)){found=!0;break}kidPromises.push(xref.fetchAsync(kid).then(function(obj){if(!(obj instanceof Dict))throw new FormatError("Kid node must be a dictionary.");obj.has("Count")?total+=obj.get("Count"):total++}))}if(found)return Promise.all(kidPromises).then(function(){return[total,parentRef]});throw new FormatError("Kid reference not found in parent's kids.")})}(ref).then(args=>{var parentRef;return args?([args,parentRef]=args,total+=args,next(parentRef)):(this.pageIndexCache.put(pageRef,total),total)});return next(pageRef)}get baseUrl(){var uri=this._catDict.get("URI");if(uri instanceof Dict){uri=uri.get("Base");if("string"==typeof uri){uri=createValidAbsoluteUrl(uri,null,{tryConvertEncoding:!0});if(uri)return shadow(this,"baseUrl",uri.href)}}return shadow(this,"baseUrl",this.pdfManager.docBaseUrl)}static parseDestDictionary({destDict,resultObj,docBaseUrl=null,docAttachments=null}){if(destDict instanceof Dict){let action=destDict.get("A"),url,dest;if(action instanceof Dict||(destDict.has("Dest")?action=destDict.get("Dest"):(action=destDict.get("AA"))instanceof Dict&&(action.has("D")?action=action.get("D"):action.has("U")&&(action=action.get("U")))),action instanceof Dict){var actionType=action.get("S");if(!(actionType instanceof Name))return void warn("parseDestDictionary: Invalid type in Action dictionary.");var actionName=actionType.name;switch(actionName){case"ResetForm":var flags=action.get("Flags"),flags=0==(1&("number"==typeof flags?flags:0)),fields=[],refs=[];for(const obj of action.get("Fields")||[])obj instanceof Ref?refs.push(obj.toString()):"string"==typeof obj&&fields.push(stringToPDFString(obj));resultObj.resetForm={fields:fields,refs:refs,include:flags};break;case"URI":(url=action.get("URI"))instanceof Name&&(url="/"+url.name);break;case"GoTo":dest=action.get("D");break;case"Launch":case"GoToR":var flags=action.get("F"),filename=(flags instanceof Dict?(filename=new FileSpec(flags,null,!0).serializable["filename"],url=filename):"string"==typeof flags&&(url=flags),fetchRemoteDest(action)),flags=(filename&&"string"==typeof url&&(url=url.split("#",1)[0]+"#"+filename),action.get("NewWindow"));"boolean"==typeof flags&&(resultObj.newWindow=flags);break;case"GoToE":var filename=action.get("T");let attachment;(attachment=docAttachments&&filename instanceof Dict&&(flags=filename.get("R"),filename=filename.get("N"),isName(flags,"C"))&&"string"==typeof filename?docAttachments[stringToPDFString(filename)]:attachment)?(resultObj.attachment=attachment,(flags=fetchRemoteDest(action))&&(resultObj.attachmentDest=flags)):warn('parseDestDictionary - unimplemented "GoToE" action.');break;case"Named":filename=action.get("N");filename instanceof Name&&(resultObj.action=filename.name);break;case"SetOCGState":flags=action.get("State"),filename=action.get("PreserveRB");if(Array.isArray(flags)&&0!==flags.length){var stateArr=[];for(const elem of flags)if(elem instanceof Name)switch(elem.name){case"ON":case"OFF":case"Toggle":stateArr.push(elem.name)}else elem instanceof Ref&&stateArr.push(elem.toString());stateArr.length===flags.length&&(resultObj.setOCGState={state:stateArr,preserveRB:"boolean"!=typeof filename||filename})}break;case"JavaScript":flags=action.get("JS");let js;flags instanceof BaseStream?js=flags.getString():"string"==typeof flags&&(js=flags);filename=js&&recoverJsURL(stringToPDFString(js));if(filename){url=filename.url,resultObj.newWindow=filename.newWindow;break}default:"JavaScript"!==actionName&&"SubmitForm"!==actionName&&warn(`parseDestDictionary - unsupported action: "${actionName}".`)}}else destDict.has("Dest")&&(dest=destDict.get("Dest"));"string"==typeof url&&((actionType=createValidAbsoluteUrl(url,docBaseUrl,{addDefaultProtocol:!0,tryConvertEncoding:!0}))&&(resultObj.url=actionType.href),resultObj.unsafeUrl=url),dest&&("string"==typeof(dest=dest instanceof Name?dest.name:dest)?resultObj.dest=stringToPDFString(dest):isValidExplicitDest(dest)&&(resultObj.dest=dest))}else warn("parseDestDictionary: `destDict` must be a dictionary.")}}function mayHaveChildren(value){return value instanceof Ref||value instanceof Dict||value instanceof BaseStream||Array.isArray(value)}function addChildren(node,nodesToVisit){if(node instanceof Dict)node=node.getRawValues();else if(node instanceof BaseStream)node=node.dict.getRawValues();else if(!Array.isArray(node))return;for(const rawValue of node)mayHaveChildren(rawValue)&&nodesToVisit.push(rawValue)}class ObjectLoader{constructor(dict,keys,xref){this.dict=dict,this.keys=keys,this.xref=xref,this.refSet=null}async load(){if(!this.xref.stream.isDataLoaded){var{keys,dict}=this,nodesToVisit=(this.refSet=new RefSet,[]);for(const key of keys){var rawValue=dict.getRaw(key);void 0!==rawValue&&nodesToVisit.push(rawValue)}return this._walk(nodesToVisit)}}async _walk(nodesToVisit){for(var nodesToRevisit=[],pendingRequests=[];nodesToVisit.length;){let currentNode=nodesToVisit.pop();if(currentNode instanceof Ref){if(this.refSet.has(currentNode))continue;try{this.refSet.put(currentNode),currentNode=this.xref.fetch(currentNode)}catch(ex){if(!(ex instanceof MissingDataException))return warn(`ObjectLoader._walk - requesting all data: "${ex}".`),this.refSet=null,manager=this.xref.stream["manager"],manager.requestAllChunks();nodesToRevisit.push(currentNode),pendingRequests.push({begin:ex.begin,end:ex.end})}}if(currentNode instanceof BaseStream){var manager=currentNode.getBaseStreams();if(manager){let foundMissingData=!1;for(const stream of manager)stream.isDataLoaded||(foundMissingData=!0,pendingRequests.push({begin:stream.start,end:stream.end}));foundMissingData&&nodesToRevisit.push(currentNode)}}addChildren(currentNode,nodesToVisit)}if(pendingRequests.length){await this.xref.stream.manager.requestRanges(pendingRequests);for(const node of nodesToRevisit)node instanceof Ref&&this.refSet.remove(node);return this._walk(nodesToRevisit)}this.refSet=null}}const $acceptWhitespace=Symbol(),$addHTML=Symbol(),$appendChild=Symbol(),$childrenToHTML=Symbol(),$clean=Symbol(),$cleanPage=Symbol(),$cleanup=Symbol(),$clone=Symbol(),$consumed=Symbol(),$content=Symbol("content"),$data=Symbol("data"),$dump=Symbol(),$extra=Symbol("extra"),$finalize=Symbol(),$flushHTML=Symbol(),$getAttributeIt=Symbol(),$getAttributes=Symbol(),$getAvailableSpace=Symbol(),$getChildrenByClass=Symbol(),$getChildrenByName=Symbol(),$getChildrenByNameIt=Symbol(),$getDataValue=Symbol(),$getExtra=Symbol(),$getRealChildrenByNameIt=Symbol(),$getChildren=Symbol(),$getContainedChildren=Symbol(),$getNextPage=Symbol(),$getSubformParent=Symbol(),$getParent=Symbol(),$getTemplateRoot=Symbol(),$globalData=Symbol(),$hasSettableValue=Symbol(),$ids=Symbol(),$indexOf=Symbol(),$insertAt=Symbol(),$isCDATAXml=Symbol(),$isBindable=Symbol(),$isDataValue=Symbol(),$isDescendent=Symbol(),$isNsAgnostic=Symbol(),$isSplittable=Symbol(),$isThereMoreWidth=Symbol(),$isTransparent=Symbol(),$isUsable=Symbol(),$lastAttribute=Symbol(),$namespaceId=Symbol("namespaceId"),$nodeName=Symbol("nodeName"),$nsAttributes=Symbol(),$onChild=Symbol(),$onChildCheck=Symbol(),$onText=Symbol(),$pushGlyphs=Symbol(),$popPara=Symbol(),$pushPara=Symbol(),$removeChild=Symbol(),$root=Symbol("root"),$resolvePrototypes=Symbol(),$searchNode=Symbol(),$setId=Symbol(),$setSetAttributes=Symbol(),$setValue=Symbol(),$tabIndex=Symbol(),$text=Symbol(),$toPages=Symbol(),$toHTML=Symbol(),$toString=Symbol(),$toStyle=Symbol(),$uid=Symbol("uid"),$buildXFAObject=Symbol(),NamespaceIds={config:{id:0,check:ns=>ns.startsWith("http://www.xfa.org/schema/xci/")},connectionSet:{id:1,check:ns=>ns.startsWith("http://www.xfa.org/schema/xfa-connection-set/")},datasets:{id:2,check:ns=>ns.startsWith("http://www.xfa.org/schema/xfa-data/")},form:{id:3,check:ns=>ns.startsWith("http://www.xfa.org/schema/xfa-form/")},localeSet:{id:4,check:ns=>ns.startsWith("http://www.xfa.org/schema/xfa-locale-set/")},pdf:{id:5,check:ns=>"http://ns.adobe.com/xdp/pdf/"===ns},signature:{id:6,check:ns=>"http://www.w3.org/2000/09/xmldsig#"===ns},sourceSet:{id:7,check:ns=>ns.startsWith("http://www.xfa.org/schema/xfa-source-set/")},stylesheet:{id:8,check:ns=>"http://www.w3.org/1999/XSL/Transform"===ns},template:{id:9,check:ns=>ns.startsWith("http://www.xfa.org/schema/xfa-template/")},xdc:{id:10,check:ns=>ns.startsWith("http://www.xfa.org/schema/xdc/")},xdp:{id:11,check:ns=>"http://ns.adobe.com/xdp/"===ns},xfdf:{id:12,check:ns=>"http://ns.adobe.com/xfdf/"===ns},xhtml:{id:13,check:ns=>"http://www.w3.org/1999/xhtml"===ns},xmpmeta:{id:14,check:ns=>"http://ns.adobe.com/xmpmeta/"===ns}},dimConverters={pt:x=>x,cm:x=>x/2.54*72,mm:x=>x/25.4*72,in:x=>72*x,px:x=>x},measurementPattern=/([+-]?\d+\.?\d*)(.*)/;function stripQuotes(str){return str.startsWith("'")||str.startsWith('"')?str.slice(1,-1):str}function getInteger({data,defaultValue,validate}){if(!data)return defaultValue;data=data.trim();data=parseInt(data,10);return!isNaN(data)&&validate(data)?data:defaultValue}function getFloat({data,defaultValue,validate}){if(!data)return defaultValue;data=data.trim();data=parseFloat(data);return!isNaN(data)&&validate(data)?data:defaultValue}function getKeyword({data,defaultValue,validate}){return data&&validate(data=data.trim())?data:defaultValue}function getStringOption(data,options){return getKeyword({data:data,defaultValue:options[0],validate:k=>options.includes(k)})}function getMeasurement(str,def="0"){var unit;return def||="0",!str||!(str=str.trim().match(measurementPattern))||([,str,unit]=str,str=parseFloat(str),isNaN(str))?getMeasurement(def):0===str?0:(unit=dimConverters[unit])?unit(str):str}function getRatio(data){var den;return!data||(1===(data=data.trim().split(/\s*:\s*/).map(x=>parseFloat(x)).filter(x=>!isNaN(x))).length&&data.push(1),0===data.length)?{num:1,den:1}:([data,den]=data,{num:data,den:den})}function getRelevant(data){return data?data.trim().split(/\s+/).map(e=>({excluded:"-"===e[0],viewname:e.substring(1)})):[]}function getColor(data,def=[0,0,0]){var[def,g,b]=def;return!data||(data=data.trim().split(/\s*,\s*/).map(c=>Math.min(Math.max(0,parseInt(c.trim(),10)),255)).map(c=>isNaN(c)?0:c)).length<3||([def,g,b]=data),{r:def,g:g,b:b}}function getBBox(data){var y,width,height;return!data||(data=data.trim().split(/\s*,\s*/).map(m=>getMeasurement(m,"-1"))).length<4||data[2]<0||data[3]<0?{x:-1,y:-1,width:-1,height:-1}:([data,y,width,height]=data,{x:data,y:y,width:width,height:height})}class HTMLResult{static get FAILURE(){return shadow(this,"FAILURE",new HTMLResult(!1,null,null,null))}static get EMPTY(){return shadow(this,"EMPTY",new HTMLResult(!0,null,null,null))}constructor(success,html,bbox,breakNode){this.success=success,this.html=html,this.bbox=bbox,this.breakNode=breakNode}isBreak(){return!!this.breakNode}static breakNode(node){return new HTMLResult(!1,null,null,node)}static success(html,bbox=null){return new HTMLResult(!0,html,bbox,null)}}class FontFinder{constructor(pdfFonts){this.fonts=new Map,this.cache=new Map,this.warned=new Set,this.defaultFont=null,this.add(pdfFonts)}add(pdfFonts,reallyMissingFonts=null){for(const pdfFont of pdfFonts)this.addPdfFont(pdfFont);for(const pdfFont of this.fonts.values())pdfFont.regular||(pdfFont.regular=pdfFont.italic||pdfFont.bold||pdfFont.bolditalic);if(reallyMissingFonts&&0!==reallyMissingFonts.size){var myriad=this.fonts.get("PdfJS-Fallback-PdfJS-XFA");for(const missing of reallyMissingFonts)this.fonts.set(missing,myriad)}}addPdfFont(pdfFont){var cssFontInfo=pdfFont.cssFontInfo,name=cssFontInfo.fontFamily;let font=this.fonts.get(name),property=(font||(font=Object.create(null),this.fonts.set(name,font),this.defaultFont)||(this.defaultFont=font),"");name=parseFloat(cssFontInfo.fontWeight);0!==parseFloat(cssFontInfo.italicAngle)?property=700<=name?"bolditalic":"italic":700<=name&&(property="bold"),!property&&((pdfFont.name.includes("Bold")||pdfFont.psName?.includes("Bold"))&&(property="bold"),pdfFont.name.includes("Italic")||pdfFont.name.endsWith("It")||pdfFont.psName?.includes("Italic")||pdfFont.psName?.endsWith("It"))&&(property+="italic"),property=property||"regular",font[property]=pdfFont}getDefault(){return this.defaultFont}find(fontName,mustWarn=!0){var font=this.fonts.get(fontName)||this.cache.get(fontName);if(font)return font;var pattern=/,|-|_| |bolditalic|bold|italic|regular|it/gi;let name=fontName.replaceAll(pattern,"");if(font=this.fonts.get(name))return this.cache.set(fontName,font),font;name=name.toLowerCase();var family,pdfFont,maybe=[];for([family,pdfFont]of this.fonts.entries())family.replaceAll(pattern,"").toLowerCase().startsWith(name)&&maybe.push(pdfFont);if(0===maybe.length)for(const[,pdfFont]of this.fonts.entries())pdfFont.regular.name?.replaceAll(pattern,"").toLowerCase().startsWith(name)&&maybe.push(pdfFont);if(0===maybe.length){name=name.replaceAll(/psmt|mt/gi,"");for(const[family,pdfFont]of this.fonts.entries())family.replaceAll(pattern,"").toLowerCase().startsWith(name)&&maybe.push(pdfFont)}if(0===maybe.length)for(const pdfFont of this.fonts.values())pdfFont.regular.name?.replaceAll(pattern,"").toLowerCase().startsWith(name)&&maybe.push(pdfFont);return 1<=maybe.length?(1!==maybe.length&&mustWarn&&warn("XFA - Too many choices to guess the correct font: "+fontName),this.cache.set(fontName,maybe[0]),maybe[0]):(mustWarn&&!this.warned.has(fontName)&&(this.warned.add(fontName),warn("XFA - Cannot find the font: "+fontName)),null)}}function selectFont(xfaFont,typeface){return"italic"===xfaFont.posture?"bold"===xfaFont.weight?typeface.bolditalic:typeface.italic:"bold"===xfaFont.weight?typeface.bold:typeface.regular}function fonts_getMetrics(xfaFont,real=!1){let pdfFont=null;var name;return xfaFont&&(name=stripQuotes(xfaFont.typeface),name=xfaFont[$globalData].fontFinder.find(name),pdfFont=selectFont(xfaFont,name)),pdfFont?(name=xfaFont.size||10,{lineHeight:(xfaFont=pdfFont.lineHeight?Math.max(real?0:1.2,pdfFont.lineHeight):1.2)*name,lineGap:(real=void 0===pdfFont.lineGap?.2:pdfFont.lineGap)*name,lineNoGap:Math.max(1,xfaFont-real)*name}):{lineHeight:12,lineGap:2,lineNoGap:10}}const WIDTH_FACTOR=1.02;class FontInfo{constructor(xfaFont,margin,lineHeight,fontFinder){this.lineHeight=lineHeight,this.paraMargin=margin||{top:0,bottom:0,left:0,right:0},xfaFont&&(this.xfaFont={typeface:xfaFont.typeface,posture:xfaFont.posture,weight:xfaFont.weight,size:xfaFont.size,letterSpacing:xfaFont.letterSpacing},lineHeight=fontFinder.find(xfaFont.typeface))&&(this.pdfFont=selectFont(xfaFont,lineHeight),this.pdfFont)||([this.pdfFont,this.xfaFont]=this.defaultFont(fontFinder))}defaultFont(fontFinder){fontFinder=fontFinder.find("Helvetica",!1)||fontFinder.find("Myriad Pro",!1)||fontFinder.find("Arial",!1)||fontFinder.getDefault();if(fontFinder?.regular){fontFinder=fontFinder.regular;const xfaFont={typeface:fontFinder.cssFontInfo.fontFamily,posture:"normal",weight:"normal",size:10,letterSpacing:0};return[fontFinder,xfaFont]}const xfaFont={typeface:"Courier",posture:"normal",weight:"normal",size:10,letterSpacing:0};return[null,xfaFont]}}class FontSelector{constructor(defaultXfaFont,defaultParaMargin,defaultLineHeight,fontFinder){this.fontFinder=fontFinder,this.stack=[new FontInfo(defaultXfaFont,defaultParaMargin,defaultLineHeight,fontFinder)]}pushData(xfaFont,margin,lineHeight){var lastFont=this.stack.at(-1);for(const name of["typeface","posture","weight","size","letterSpacing"])xfaFont[name]||(xfaFont[name]=lastFont.xfaFont[name]);for(const name of["top","bottom","left","right"])isNaN(margin[name])&&(margin[name]=lastFont.paraMargin[name]);lineHeight=new FontInfo(xfaFont,margin,lineHeight||lastFont.lineHeight,this.fontFinder);lineHeight.pdfFont||(lineHeight.pdfFont=lastFont.pdfFont),this.stack.push(lineHeight)}popFont(){this.stack.pop()}topFont(){return this.stack.at(-1)}}class TextMeasure{constructor(defaultXfaFont,defaultParaMargin,defaultLineHeight,fonts){this.glyphs=[],this.fontSelector=new FontSelector(defaultXfaFont,defaultParaMargin,defaultLineHeight,fonts),this.extraHeight=0}pushData(xfaFont,margin,lineHeight){this.fontSelector.pushData(xfaFont,margin,lineHeight)}popFont(xfaFont){return this.fontSelector.popFont()}addPara(){var lastFont=this.fontSelector.topFont();this.extraHeight+=lastFont.paraMargin.top+lastFont.paraMargin.bottom}addString(str){if(str){var lastFont=this.fontSelector.topFont(),fontSize=lastFont.xfaFont.size;if(lastFont.pdfFont){var letterSpacing=lastFont.xfaFont.letterSpacing,pdfFont=lastFont.pdfFont,fontLineHeight=pdfFont.lineHeight||1.2,lineHeight=lastFont.lineHeight||Math.max(1.2,fontLineHeight)*fontSize,lastFont=void 0===pdfFont.lineGap?.2:pdfFont.lineGap,firstLineHeight=Math.max(1,fontLineHeight-lastFont)*fontSize,scale=fontSize/1e3,fallbackWidth=pdfFont.defaultWidth||pdfFont.charsToGlyphs(" ")[0].width;for(const line of str.split(/[\u2029\n]/)){var encodedLine=pdfFont.encodeString(line).join("");for(const glyph of pdfFont.charsToGlyphs(encodedLine)){var width=glyph.width||fallbackWidth;this.glyphs.push([width*scale+letterSpacing,lineHeight,firstLineHeight,glyph.unicode,!1])}this.glyphs.push([0,0,0,"\n",!0])}}else for(const line of str.split(/[\u2029\n]/)){for(const char of line.split(""))this.glyphs.push([fontSize,1.2*fontSize,fontSize,char,!1]);this.glyphs.push([0,0,0,"\n",!0])}this.glyphs.pop()}}compute(maxWidth){let lastSpacePos=-1,lastSpaceWidth=0,width=0,height=0,currentLineWidth=0,currentLineHeight=0,isBroken=!1,isFirstLine=!0;for(let i=0,ii=this.glyphs.length;imaxWidth?(width=Math.max(width,currentLineWidth),currentLineWidth=0,height+=currentLineHeight,currentLineHeight=firstLineHeight,lastSpacePos=-1,lastSpaceWidth=0,isBroken=!0,isFirstLine=!1):(currentLineHeight=Math.max(firstLineHeight,currentLineHeight),lastSpaceWidth=currentLineWidth,currentLineWidth+=glyphWidth,lastSpacePos=i):currentLineWidth+glyphWidth>maxWidth?(height+=currentLineHeight,currentLineHeight=firstLineHeight,-1!==lastSpacePos?(i=lastSpacePos,width=Math.max(width,lastSpaceWidth),currentLineWidth=0,lastSpacePos=-1,lastSpaceWidth=0):(width=Math.max(width,currentLineWidth),currentLineWidth=glyphWidth),isBroken=!0,isFirstLine=!1):(currentLineWidth+=glyphWidth,currentLineHeight=Math.max(firstLineHeight,currentLineHeight))}return width=Math.max(width,currentLineWidth),height+=currentLineHeight+this.extraHeight,{width:WIDTH_FACTOR*width,height:height,isBroken:isBroken}}}const namePattern=/^[^.[]+/,indexPattern=/^[^\]]+/,operators={dot:0,dotDot:1,dotHash:2,dotBracket:3,dotParen:4},shortcuts=new Map([["$data",(root,current)=>root.datasets?root.datasets.data:root],["$record",(root,current)=>(root.datasets?root.datasets.data:root)[$getChildren]()[0]],["$template",(root,current)=>root.template],["$connectionSet",(root,current)=>root.connectionSet],["$form",(root,current)=>root.form],["$layout",(root,current)=>root.layout],["$host",(root,current)=>root.host],["$dataWindow",(root,current)=>root.dataWindow],["$event",(root,current)=>root.event],["!",(root,current)=>root.datasets],["$xfa",(root,current)=>root],["xfa",(root,current)=>root],["$",(root,current)=>current]]),somCache=new WeakMap;function parseIndex(index){return"*"===(index=index.trim())?1/0:parseInt(index,10)||0}function parseExpression(expr,dotDotAllowed,noExpr=!0){let match=expr.match(namePattern);if(!match)return null;var[name]=match,parsed=[{name:name,cacheName:"."+name,index:0,js:null,formCalc:null,operator:operators.dot}];let pos=name.length;for(;posindexnode[index]):nodes.flat();else{if(!(container=container[$getParent]()))return null;i=-1,root=[container]}}return 0===root.length?null:root}function createDataNode(root,container,expr){var parsed=parseExpression(expr);if(parsed&&!parsed.some(x=>x.operator===operators.dotDot)){expr=shortcuts.get(parsed[0].name);let i=0;expr?(root=expr(root,container),i=1):root=container||root;for(var ii=parsed.length;ic[$text]()).join("")}get[_attributeNames](){var proto=Object.getPrototypeOf(this);if(!proto._attributes){var attributes=proto._attributes=new Set;for(const name of Object.getOwnPropertyNames(this)){if(null===this[name]||this[name]instanceof XFAObject||this[name]instanceof XFAObjectArray)break;attributes.add(name)}}return shadow(this,_attributeNames,proto._attributes)}[$isDescendent](parent){let node=this;for(;node;){if(node===parent)return!0;node=node[$getParent]()}return!1}[$getParent](){return this[_parent]}[$getSubformParent](){return this[$getParent]()}[$getChildren](name=null){return name?this[name]:this[_children]}[$dump](){var dumped=Object.create(null);this[$content]&&(dumped.$content=this[$content]);for(const name of Object.getOwnPropertyNames(this)){var value=this[name];null!==value&&(value instanceof XFAObject?dumped[name]=value[$dump]():value instanceof XFAObjectArray?value.isEmpty()||(dumped[name]=value.dump()):dumped[name]=value)}return dumped}[$toStyle](){return null}[$toHTML](){return HTMLResult.EMPTY}*[$getContainedChildren](){for(const node of this[$getChildren]())yield node}*[_filteredChildrenGenerator](filter,include){for(const node of this[$getContainedChildren]()){var availableSpace;filter&&include!==filter.has(node[$nodeName])||(availableSpace=this[$getAvailableSpace](),(availableSpace=node[$toHTML](availableSpace)).success||(this[$extra].failingNode=node),yield availableSpace)}}[$flushHTML](){return null}[$addHTML](html,bbox){this[$extra].children.push(html)}[$getAvailableSpace](){}[$childrenToHTML]({filter=null,include=!0}){if(this[$extra].generator){var availableSpace=this[$getAvailableSpace](),availableSpace=this[$extra].failingNode[$toHTML](availableSpace);if(!availableSpace.success)return availableSpace;availableSpace.html&&this[$addHTML](availableSpace.html,availableSpace.bbox),delete this[$extra].failingNode}else this[$extra].generator=this[_filteredChildrenGenerator](filter,include);for(;;){var gen=this[$extra].generator.next();if(gen.done)break;const res=gen.value;if(!res.success)return res;res.html&&this[$addHTML](res.html,res.bbox)}return this[$extra].generator=null,HTMLResult.EMPTY}[$setSetAttributes](attributes){this[_setAttributes]=new Set(Object.keys(attributes))}[_getUnsetAttributes](protoAttributes){const allAttr=this[_attributeNames],setAttr=this[_setAttributes];return[...protoAttributes].filter(x=>allAttr.has(x)&&!setAttr.has(x))}[$resolvePrototypes](ids,ancestors=new Set){for(const child of this[_children])child[_resolvePrototypesHelper](ids,ancestors)}[_resolvePrototypesHelper](ids,ancestors){var proto=this[_getPrototype](ids,ancestors);proto?this[_applyPrototype](proto,ids,ancestors):this[$resolvePrototypes](ids,ancestors)}[_getPrototype](ids,ancestors){var{use,usehref}=this;if(!use&&!usehref)return null;let proto=null,somExpression=null,id=null,ref=use;if(usehref?(ref=usehref).startsWith("#som(")&&usehref.endsWith(")")?somExpression=usehref.slice("#som(".length,-1):usehref.startsWith(".#som(")&&usehref.endsWith(")")?somExpression=usehref.slice(".#som(".length,-1):usehref.startsWith("#")?id=usehref.slice(1):usehref.startsWith(".#")&&(id=usehref.slice(2)):use.startsWith("#")?id=use.slice(1):somExpression=use,this.use=this.usehref="",!(proto=id?ids.get(id):(proto=searchNode(ids.get($root),this,somExpression,!0,!1))&&proto[0]))return warn(`XFA - Invalid prototype reference: ${ref}.`),null;if(proto[$nodeName]!==this[$nodeName])return warn(`XFA - Incompatible prototype: ${proto[$nodeName]} !== ${this[$nodeName]}.`),null;if(ancestors.has(proto))return warn("XFA - Cycle detected in prototypes use."),null;ancestors.add(proto);usehref=proto[_getPrototype](ids,ancestors);return usehref&&proto[_applyPrototype](usehref,ids,ancestors),proto[$resolvePrototypes](ids,ancestors),ancestors.delete(proto),proto}[_applyPrototype](proto,ids,ancestors){if(ancestors.has(proto))warn("XFA - Cycle detected in prototypes use.");else{!this[$content]&&proto[$content]&&(this[$content]=proto[$content]),new Set(ancestors).add(proto);for(const unsetAttrName of this[_getUnsetAttributes](proto[_setAttributes]))this[unsetAttrName]=proto[unsetAttrName],this[_setAttributes]&&this[_setAttributes].add(unsetAttrName);for(const name of Object.getOwnPropertyNames(this))if(!this[_attributeNames].has(name)){var value=this[name],protoValue=proto[name];if(value instanceof XFAObjectArray){for(const child of value[_children])child[_resolvePrototypesHelper](ids,ancestors);for(let i=value[_children].length,ii=protoValue[_children].length;iXFAObject[_cloneAttribute](x)):"object"==typeof obj&&null!==obj?Object.assign({},obj):obj}[$clone](){var value,clone=Object.create(Object.getPrototypeOf(this));for(const $symbol of Object.getOwnPropertySymbols(this))try{clone[$symbol]=this[$symbol]}catch{shadow(clone,$symbol,this[$symbol])}clone[$uid]=""+clone[$nodeName]+uid++,clone[_children]=[];for(const name of Object.getOwnPropertyNames(this))this[_attributeNames].has(name)?clone[name]=XFAObject[_cloneAttribute](this[name]):(value=this[name],clone[name]=value instanceof XFAObjectArray?new XFAObjectArray(value[_max]):null);for(const child of this[_children]){var name=child[$nodeName],clonedChild=child[$clone]();clone[_children].push(clonedChild),null===(clonedChild[_parent]=clone)[name]?clone[name]=clonedChild:clone[name][_children].push(clonedChild)}return clone}[$getChildren](name=null){return name?this[_children].filter(c=>c[$nodeName]===name):this[_children]}[$getChildrenByClass](name){return this[name]}[$getChildrenByName](name,allTransparent,first=!0){return Array.from(this[$getChildrenByNameIt](name,allTransparent,first))}*[$getChildrenByNameIt](name,allTransparent,first=!0){if("parent"===name)yield this[_parent];else{for(const child of this[_children])child[$nodeName]===name&&(yield child),child.name===name&&(yield child),(allTransparent||child[$isTransparent]())&&(yield*child[$getChildrenByNameIt](name,allTransparent,!1));first&&this[_attributeNames].has(name)&&(yield new XFAAttribute(this,name,this[name]))}}}class XFAObjectArray{constructor(max=1/0){this[_max]=max,this[_children]=[]}get isXFAObject(){return!1}get isXFAObjectArray(){return!0}push(child){return this[_children].length<=this[_max]?(this[_children].push(child),!0):(warn(`XFA - node "${child[$nodeName]}" accepts no more than ${this[_max]} children`),!1)}isEmpty(){return 0===this[_children].length}dump(){return 1===this[_children].length?this[_children][0][$dump]():this[_children].map(x=>x[$dump]())}[$clone](){var clone=new XFAObjectArray(this[_max]);return clone[_children]=this[_children].map(c=>c[$clone]()),clone}get children(){return this[_children]}clear(){this[_children].length=0}}class XFAAttribute{constructor(node,name,value){this[_parent]=node,this[$nodeName]=name,this[$content]=value,this[$consumed]=!1,this[$uid]="attribute"+uid++}[$getParent](){return this[_parent]}[$isDataValue](){return!0}[$getDataValue](){return this[$content].trim()}[$setValue](value){value=value.value||"",this[$content]=value.toString()}[$text](){return this[$content]}[$isDescendent](parent){return this[_parent]===parent||this[_parent][$isDescendent](parent)}}class XmlObject extends XFAObject{constructor(nsId,name,attributes={}){if(super(nsId,name),this[$content]="",this[_dataValue]=null,"#text"!==name){var attrName,value,map=new Map;this[_attributes]=map;for([attrName,value]of Object.entries(attributes))map.set(attrName,new XFAAttribute(this,attrName,value));attributes.hasOwnProperty($nsAttributes)&&void 0!==(nsId=attributes[$nsAttributes].xfa.dataNode)&&("dataGroup"===nsId?this[_dataValue]=!1:"dataValue"===nsId&&(this[_dataValue]=!0))}this[$consumed]=!1}[$toString](buf){var tagName=this[$nodeName];if("#text"===tagName)buf.push(encodeToXmlString(this[$content]));else{var name,value,tagName=utf8StringToString(tagName),prefix=this[$namespaceId]===NS_DATASETS?"xfa:":"";buf.push("<"+prefix+tagName);for([name,value]of this[_attributes].entries()){var utf8Name=utf8StringToString(name);buf.push(` ${utf8Name}="${encodeToXmlString(value[$content])}"`)}if(null!==this[_dataValue]&&(this[_dataValue]?buf.push(' xfa:dataNode="dataValue"'):buf.push(' xfa:dataNode="dataGroup"')),this[$content]||0!==this[_children].length){if(buf.push(">"),this[$content])"string"==typeof this[$content]?buf.push(encodeToXmlString(this[$content])):this[$content][$toString](buf);else for(const child of this[_children])child[$toString](buf);buf.push(``)}else buf.push("/>")}}[$onChild](child){var node;return this[$content]&&(node=new XmlObject(this[$namespaceId],"#text"),this[$appendChild](node),node[$content]=this[$content],this[$content]=""),this[$appendChild](child),!0}[$onText](str){this[$content]+=str}[$finalize](){var node;this[$content]&&0c[$nodeName]===name):this[_children]}[$getAttributes](){return this[_attributes]}[$getChildrenByClass](name){var value=this[_attributes].get(name);return void 0!==value?value:this[$getChildren](name)}*[$getChildrenByNameIt](name,allTransparent){var value=this[_attributes].get(name);value&&(yield value);for(const child of this[_children])child[$nodeName]===name&&(yield child),allTransparent&&(yield*child[$getChildrenByNameIt](name,allTransparent))}*[$getAttributeIt](name,skipConsumed){var value=this[_attributes].get(name);!value||skipConsumed&&value[$consumed]||(yield value);for(const child of this[_children])yield*child[$getAttributeIt](name,skipConsumed)}*[$getRealChildrenByNameIt](name,allTransparent,skipConsumed){for(const child of this[_children])child[$nodeName]!==name||skipConsumed&&child[$consumed]||(yield child),allTransparent&&(yield*child[$getRealChildrenByNameIt](name,allTransparent,skipConsumed))}[$isDataValue](){return null===this[_dataValue]?0===this[_children].length||this[_children][0][$namespaceId]===NamespaceIds.xhtml.id:this[_dataValue]}[$getDataValue](){return null!==this[_dataValue]||0===this[_children].length?this[$content].trim():this[_children][0][$namespaceId]===NamespaceIds.xhtml.id?this[_children][0][$text]().trim():null}[$setValue](value){value=value.value||"",this[$content]=value.toString()}[$dump](hasNS=!1){var name,value,dumped=Object.create(null);hasNS&&(dumped.$ns=this[$namespaceId]),this[$content]&&(dumped.$content=this[$content]),dumped.$name=this[$nodeName],dumped.children=[];for(const child of this[_children])dumped.children.push(child[$dump](hasNS));dumped.attributes=Object.create(null);for([name,value]of this[_attributes])dumped.attributes[name]=value[$content];return dumped}}class ContentObject extends XFAObject{constructor(nsId,name){super(nsId,name),this[$content]=""}[$onText](text){this[$content]+=text}[$finalize](){}}class OptionObject extends ContentObject{constructor(nsId,name,options){super(nsId,name),this[_options]=options}[$finalize](){this[$content]=getKeyword({data:this[$content],defaultValue:this[_options][0],validate:k=>this[_options].includes(k)})}[$clean](builder){super[$clean](builder),delete this[_options]}}class StringObject extends ContentObject{[$finalize](){this[$content]=this[$content].trim()}}class IntegerObject extends ContentObject{constructor(nsId,name,defaultValue,validator){super(nsId,name),this[_defaultValue]=defaultValue,this[_validator]=validator}[$finalize](){this[$content]=getInteger({data:this[$content],defaultValue:this[_defaultValue],validate:this[_validator]})}[$clean](builder){super[$clean](builder),delete this[_defaultValue],delete this[_validator]}}class Option01 extends IntegerObject{constructor(nsId,name){super(nsId,name,0,n=>1===n)}}class Option10 extends IntegerObject{constructor(nsId,name){super(nsId,name,1,n=>0===n)}}function measureToString(m){return"string"==typeof m?"0px":Number.isInteger(m)?m+"px":m.toFixed(2)+"px"}const converters={anchorType(node,style){var parent=node[$getSubformParent]();if(parent&&(!parent.layout||"position"===parent.layout))switch("transform"in style||(style.transform=""),node.anchorType){case"bottomCenter":style.transform+="translate(-50%, -100%)";break;case"bottomLeft":style.transform+="translate(0,-100%)";break;case"bottomRight":style.transform+="translate(-100%,-100%)";break;case"middleCenter":style.transform+="translate(-50%,-50%)";break;case"middleLeft":style.transform+="translate(0,-50%)";break;case"middleRight":style.transform+="translate(-100%,-50%)";break;case"topCenter":style.transform+="translate(-50%,0)";break;case"topRight":style.transform+="translate(-100%,0)"}},dimensions(node,style){var parent=node[$getSubformParent]();let width=node.w;var height=node.h;if(parent.layout?.includes("row")){var parent=parent[$extra],colSpan=node.colSpan;let w;-1===colSpan?(w=parent.columnWidths.slice(parent.currentColumn).reduce((a,x)=>a+x,0),parent.currentColumn=0):(w=parent.columnWidths.slice(parent.currentColumn,parent.currentColumn+colSpan).reduce((a,x)=>a+x,0),parent.currentColumn=(parent.currentColumn+node.colSpan)%parent.columnWidths.length),isNaN(w)||(width=node.w=w)}style.width=""!==width?measureToString(width):"auto",style.height=""!==height?measureToString(height):"auto"},position(node,style){var parent=node[$getSubformParent]();parent?.layout&&"position"!==parent.layout||(style.position="absolute",style.left=measureToString(node.x),style.top=measureToString(node.y))},rotate(node,style){node.rotate&&("transform"in style||(style.transform=""),style.transform+=`rotate(-${node.rotate}deg)`,style.transformOrigin="top left")},presence(node,style){switch(node.presence){case"invisible":style.visibility="hidden";break;case"hidden":case"inactive":style.display="none"}},hAlign(node,style){if("para"===node[$nodeName])switch(node.hAlign){case"justifyAll":style.textAlign="justify-all";break;case"radix":style.textAlign="left";break;default:style.textAlign=node.hAlign}else switch(node.hAlign){case"left":style.alignSelf="start";break;case"center":style.alignSelf="center";break;case"right":style.alignSelf="end"}},margin(node,style){node.margin&&(style.margin=node.margin[$toStyle]().margin)}};function setMinMaxDimensions(node,style){"position"===node[$getSubformParent]().layout&&(0a+w,0):extra.columnWidths.slice(extra.currentColumn,extra.currentColumn+colSpan).reduce((a,w)=>a+w,0),isNaN(width)||(node.w=width)}parent.layout&&"position"!==parent.layout&&(node.x=node.y=0),"table"===node.layout&&""===node.w&&Array.isArray(node.columnWidths)&&(node.w=node.columnWidths.reduce((a,x)=>a+x,0))}function layoutClass(node){switch(node.layout){case"position":return"xfaPosition";case"lr-tb":return"xfaLrTb";case"rl-row":return"xfaRlRow";case"rl-tb":return"xfaRlTb";case"row":return"xfaRow";case"table":return"xfaTable";case"tb":return"xfaTb";default:return"xfaPosition"}}function toStyle(node,...names){var style=Object.create(null);for(const name of names){var value=node[name];null!==value&&(converters.hasOwnProperty(name)?converters[name](node,style):value instanceof XFAObject&&((value=value[$toStyle]())?Object.assign(style,value):warn(`(DEBUG) - XFA - style for ${name} not implemented yet`)))}return style}function createWrapper(node,html){var attributes=html["attributes"],style=attributes["style"],wrapper={name:"div",attributes:{class:["xfaWrapper"],style:Object.create(null)},children:[]};if(attributes.class.push("xfaWrapped"),node.border){var{widths,insets:attributes}=node.border[$extra];let width,height,top=attributes[0],left=attributes[3];var insetsH=attributes[0]+attributes[2],insetsW=attributes[1]+attributes[3];switch(node.border.hand){case"even":top-=widths[0]/2,left-=widths[3]/2,width=`calc(100% + ${(widths[1]+widths[3])/2-insetsW}px)`,height=`calc(100% + ${(widths[0]+widths[2])/2-insetsH}px)`;break;case"left":top-=widths[0],left-=widths[3],width=`calc(100% + ${widths[1]+widths[3]-insetsW}px)`,height=`calc(100% + ${widths[0]+widths[2]-insetsH}px)`;break;case"right":width=insetsW?`calc(100% - ${insetsW}px)`:"100%",height=insetsH?`calc(100% - ${insetsH}px)`:"100%"}var attributes=["xfaBorder"],border=(isPrintOnly(node.border)&&attributes.push("xfaPrintOnly"),{name:"div",attributes:{class:attributes,style:{top:top+"px",left:left+"px",width:width,height:height}},children:[]});for(const key of["border","borderWidth","borderColor","borderRadius","borderStyle"])void 0!==style[key]&&(border.attributes.style[key]=style[key],delete style[key]);wrapper.children.push(border,html)}else wrapper.children.push(html);for(const key of["background","backgroundClip","top","left","width","height","minWidth","minHeight","maxWidth","maxHeight","transform","transformOrigin","visibility"])void 0!==style[key]&&(wrapper.attributes.style[key]=style[key],delete style[key]);return wrapper.attributes.style.position="absolute"===style.position?"absolute":"relative",delete style.position,style.alignSelf&&(wrapper.attributes.style.alignSelf=style.alignSelf,delete style.alignSelf),wrapper}function fixTextIndent(styles){var name,padding,indent=getMeasurement(styles.textIndent,"0px");0<=indent||(padding=getMeasurement(styles[name="padding"+("left"==("right"===styles.textAlign?"right":"left")?"Left":"Right")],"0px"),styles[name]=padding-indent+"px")}function setAccess(node,classNames){switch(node.access){case"nonInteractive":classNames.push("xfaNonInteractive");break;case"readOnly":classNames.push("xfaReadOnly");break;case"protected":classNames.push("xfaDisabled")}}function isPrintOnly(node){return 0a+x),height:availableSpace.height-marginH};case"table":case"tb":return{width:availableSpace.width-marginH,height:availableSpace.height-marginV-node[$extra].height};default:return availableSpace}}function getTransformedBBox(node){let w=""===node.w?NaN:node.w,h=""===node.h?NaN:node.h,[centerX,centerY]=[0,0];switch(node.anchorType||""){case"bottomCenter":[centerX,centerY]=[w/2,h];break;case"bottomLeft":[centerX,centerY]=[0,h];break;case"bottomRight":[centerX,centerY]=[w,h];break;case"middleCenter":[centerX,centerY]=[w/2,h/2];break;case"middleLeft":[centerX,centerY]=[0,h/2];break;case"middleRight":[centerX,centerY]=[w,h/2];break;case"topCenter":[centerX,centerY]=[w/2,0];break;case"topRight":[centerX,centerY]=[w,0]}let x,y;switch(node.rotate||0){case 0:[x,y]=[-centerX,-centerY];break;case 90:[x,y]=[-centerY,centerX],[w,h]=[h,-w];break;case 180:[x,y]=[centerX,centerY],[w,h]=[-w,-h];break;case 270:[x,y]=[centerY,-centerX],[w,h]=[-h,w]}return[node.x+x+Math.min(0,w),node.y+y+Math.min(0,h),Math.abs(w),Math.abs(h)]}function checkDimensions(node,space){if(null===node[$getTemplateRoot]()[$extra].firstUnsplittable)return!0;if(0===node.w||0===node.h)return!0;var parent=node[$getSubformParent](),attempt=parent[$extra]?.attempt||0,[,y,w,h]=getTransformedBBox(node);switch(parent.layout){case"lr-tb":case"rl-tb":return 0===attempt?node[$getTemplateRoot]()[$extra].noLayoutFailure?""!==node.w?Math.round(w-space.width)<=2:2node[$getTemplateRoot]()[$extra].currentContentArea.h;case"rl-row":case"row":return node[$getTemplateRoot]()[$extra].noLayoutFailure?!0:""===node.h||Math.round(h-space.height)<=2;default:return!0}}const TEMPLATE_NS_ID=NamespaceIds.template.id,SVG_NS="http://www.w3.org/2000/svg",MAX_ATTEMPTS_FOR_LRTB_LAYOUT=2,MAX_EMPTY_PAGES=3,DEFAULT_TAB_INDEX=5e3,HEADING_PATTERN=/^H(\d+)$/,MIMES=new Set(["image/gif","image/jpeg","image/jpg","image/pjpeg","image/png","image/apng","image/x-png","image/bmp","image/x-ms-bmp","image/tiff","image/tif","application/octet-stream"]),IMAGES_HEADERS=[[[66,77],"image/bmp"],[[255,216,255],"image/jpeg"],[[73,73,42,0],"image/tiff"],[[77,77,0,42],"image/tiff"],[[71,73,70,56,57,97],"image/gif"],[[137,80,78,71,13,10,26,10],"image/png"]];function getBorderDims(node){return node&&node.border&&(node=node.border[$getExtra]())?{w:node.widths[0]+node.widths[2]+node.insets[0]+node.insets[2],h:node.widths[1]+node.widths[3]+node.insets[1]+node.insets[3]}:{w:0,h:0}}function hasMargin(node){return node.margin&&(node.margin.topInset||node.margin.rightInset||node.margin.bottomInset||node.margin.leftInset)}function _setValue(templateNode,value){var nodeValue;templateNode.value||(nodeValue=new Value({}),templateNode[$appendChild](nodeValue),templateNode.value=nodeValue),templateNode.value[$setValue](value)}function*getContainedChildren(node){for(const child of node[$getChildren]())child instanceof SubformSet?yield*child[$getContainedChildren]():yield child}function isRequired(node){return"error"===node.validate?.nullTest}function setTabIndex(node){for(;node;){if(!node.traversal)return void(node[$tabIndex]=node[$getParent]()[$tabIndex]);if(node[$tabIndex])return;let next=null;for(const child of node.traversal[$getChildren]())if("next"===child.operation){next=child;break}if(!next||!next.ref)return void(node[$tabIndex]=node[$getParent]()[$tabIndex]);var root=node[$getTemplateRoot](),root=(node[$tabIndex]=++root[$tabIndex],root[$searchNode](next.ref,node));if(!root)return;node=root[0]}}function applyAssist(obj,attributes){var assistTitle,assist=obj.assist;assist&&((assistTitle=assist[$toHTML]())&&(attributes.title=assistTitle),assistTitle=assist.role.match(HEADING_PATTERN))&&(assist=assistTitle[1],attributes.role="heading",attributes["aria-level"]=assist),"table"===obj.layout?attributes.role="table":"row"===obj.layout?attributes.role="row":"row"===(assistTitle=obj[$getParent]()).layout&&(attributes.role="TH"===assistTitle.assist?.role?"columnheader":"cell")}function ariaLabel(obj){return obj.assist?(obj=obj.assist).speak&&""!==obj.speak[$content]?obj.speak[$content]:obj.toolTip?obj.toolTip[$content]:null:null}function valueToHtml(value){return HTMLResult.success({name:"div",attributes:{class:["xfaRich"],style:Object.create(null)},children:[{name:"span",attributes:{style:Object.create(null)},value:value}]})}function setFirstUnsplittable(node){var root=node[$getTemplateRoot]();null===root[$extra].firstUnsplittable&&(root[$extra].firstUnsplittable=node,root[$extra].noLayoutFailure=!0)}function unsetFirstUnsplittable(node){var root=node[$getTemplateRoot]();root[$extra].firstUnsplittable===node&&(root[$extra].noLayoutFailure=!1)}function handleBreak(node){if(node[$extra])return!1;if(node[$extra]=Object.create(null),"auto"===node.targetType)return!1;var root=node[$getTemplateRoot]();let target=null;if(node.target){if(!(target=root[$searchNode](node.target,node[$getParent]())))return!1;target=target[0]}var{currentPageArea:root,currentContentArea}=root[$extra];if("pageArea"===node.targetType)return target instanceof PageArea||(target=null),node.startNew?(node[$extra].target=target||root,!0):!(!target||target===root||(node[$extra].target=target,0));var indexForCurrent,contentAreas,pageArea=(target=target instanceof ContentArea?target:null)&&target[$getParent]();let index,nextPageArea=pageArea;if(node.startNew)index=target?(indexForCurrent=(contentAreas=pageArea.contentArea.children).indexOf(currentContentArea),contentAreas=contentAreas.indexOf(target),-1!==indexForCurrent&&indexForCurrentnode,root[$extra].noLayoutFailure=!0,extraNode[$toHTML](space));node[$addHTML](space.html,space.bbox),root[$extra].noLayoutFailure=saved,extraNode[$getSubformParent]=savedMethod}class AppearanceFilter extends StringObject{constructor(attributes){super(TEMPLATE_NS_ID,"appearanceFilter"),this.id=attributes.id||"",this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class Arc extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"arc",!0),this.circular=getInteger({data:attributes.circular,defaultValue:0,validate:x=>1===x}),this.hand=getStringOption(attributes.hand,["even","left","right"]),this.id=attributes.id||"",this.startAngle=getFloat({data:attributes.startAngle,defaultValue:0,validate:x=>!0}),this.sweepAngle=getFloat({data:attributes.sweepAngle,defaultValue:360,validate:x=>!0}),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.edge=null,this.fill=null}[$toHTML](){var edge=this.edge||new Edge({}),edgeStyle=edge[$toStyle](),style=Object.create(null);"visible"===this.fill?.presence?Object.assign(style,this.fill[$toStyle]()):style.fill="transparent",style.strokeWidth=measureToString("visible"===edge.presence?edge.thickness:0),style.stroke=edgeStyle.color;let arc;var largeArc,sweepAngle,x2,y2,edge={xmlns:SVG_NS,style:{width:"100%",height:"100%",overflow:"visible"}},edgeStyle=(360===this.sweepAngle?arc={name:"ellipse",attributes:{xmlns:SVG_NS,cx:"50%",cy:"50%",rx:"50%",ry:"50%",style:style}}:(edgeStyle=this.startAngle*Math.PI/180,sweepAngle=this.sweepAngle*Math.PI/180,largeArc=1801<=n||-1===n}),this.id=attributes.id||"",this.name=attributes.name||"",this.relevant=getRelevant(attributes.relevant),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.x=getMeasurement(attributes.x,"0pt"),this.y=getMeasurement(attributes.y,"0pt"),this.desc=null,this.extras=null,this.area=new XFAObjectArray,this.draw=new XFAObjectArray,this.exObject=new XFAObjectArray,this.exclGroup=new XFAObjectArray,this.field=new XFAObjectArray,this.subform=new XFAObjectArray,this.subformSet=new XFAObjectArray}*[$getContainedChildren](){yield*getContainedChildren(this)}[$isTransparent](){return!0}[$isBindable](){return!0}[$addHTML](html,bbox){var[bbox,y,w,h]=bbox;this[$extra].width=Math.max(this[$extra].width,bbox+w),this[$extra].height=Math.max(this[$extra].height,y+h),this[$extra].children.push(html)}[$getAvailableSpace](){return this[$extra].availableSpace}[$toHTML](availableSpace){var style=toStyle(this,"position"),attributes={style:style,id:this[$uid],class:["xfaArea"]},children=(isPrintOnly(this)&&attributes.class.push("xfaPrintOnly"),this.name&&(attributes.xfaName=this.name),[]),availableSpace=(this[$extra]={children:children,width:0,height:0,availableSpace:availableSpace},this[$childrenToHTML]({filter:new Set(["area","draw","field","exclGroup","subform","subformSet"]),include:!0}));if(!availableSpace.success)return availableSpace.isBreak()?availableSpace:(delete this[$extra],HTMLResult.FAILURE);style.width=measureToString(this[$extra].width),style.height=measureToString(this[$extra].height);availableSpace={name:"div",attributes:attributes,children:children},style=[this.x,this.y,this[$extra].width,this[$extra].height];return delete this[$extra],HTMLResult.success(availableSpace,style)}}class Assist extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"assist",!0),this.id=attributes.id||"",this.role=attributes.role||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.speak=null,this.toolTip=null}[$toHTML](){return this.toolTip?.[$content]||null}}class Barcode extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"barcode",!0),this.charEncoding=getKeyword({data:attributes.charEncoding?attributes.charEncoding.toLowerCase():"",defaultValue:"",validate:k=>["utf-8","big-five","fontspecific","gbk","gb-18030","gb-2312","ksc-5601","none","shift-jis","ucs-2","utf-16"].includes(k)||k.match(/iso-8859-\d{2}/)}),this.checksum=getStringOption(attributes.checksum,["none","1mod10","1mod10_1mod11","2mod10","auto"]),this.dataColumnCount=getInteger({data:attributes.dataColumnCount,defaultValue:-1,validate:x=>0<=x}),this.dataLength=getInteger({data:attributes.dataLength,defaultValue:-1,validate:x=>0<=x}),this.dataPrep=getStringOption(attributes.dataPrep,["none","flateCompress"]),this.dataRowCount=getInteger({data:attributes.dataRowCount,defaultValue:-1,validate:x=>0<=x}),this.endChar=attributes.endChar||"",this.errorCorrectionLevel=getInteger({data:attributes.errorCorrectionLevel,defaultValue:-1,validate:x=>0<=x&&x<=8}),this.id=attributes.id||"",this.moduleHeight=getMeasurement(attributes.moduleHeight,"5mm"),this.moduleWidth=getMeasurement(attributes.moduleWidth,"0.25mm"),this.printCheckDigit=getInteger({data:attributes.printCheckDigit,defaultValue:0,validate:x=>1===x}),this.rowColumnRatio=getRatio(attributes.rowColumnRatio),this.startChar=attributes.startChar||"",this.textLocation=getStringOption(attributes.textLocation,["below","above","aboveEmbedded","belowEmbedded","none"]),this.truncate=getInteger({data:attributes.truncate,defaultValue:0,validate:x=>1===x}),this.type=getStringOption(attributes.type?attributes.type.toLowerCase():"",["aztec","codabar","code2of5industrial","code2of5interleaved","code2of5matrix","code2of5standard","code3of9","code3of9extended","code11","code49","code93","code128","code128a","code128b","code128c","code128sscc","datamatrix","ean8","ean8add2","ean8add5","ean13","ean13add2","ean13add5","ean13pwcd","fim","logmars","maxicode","msi","pdf417","pdf417macro","plessey","postauscust2","postauscust3","postausreplypaid","postausstandard","postukrm4scc","postusdpbc","postusimb","postusstandard","postus5zip","qrcode","rfid","rss14","rss14expanded","rss14limited","rss14stacked","rss14stackedomni","rss14truncated","telepen","ucc128","ucc128random","ucc128sscc","upca","upcaadd2","upcaadd5","upcapwcd","upce","upceadd2","upceadd5","upcean2","upcean5","upsmaxicode"]),this.upsMode=getStringOption(attributes.upsMode,["usCarrier","internationalCarrier","secureSymbol","standardSymbol"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.wideNarrowRatio=getRatio(attributes.wideNarrowRatio),this.encrypt=null,this.extras=null}}class Bind extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"bind",!0),this.match=getStringOption(attributes.match,["once","dataRef","global","none"]),this.ref=attributes.ref||"",this.picture=null}}class BindItems extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"bindItems"),this.connection=attributes.connection||"",this.labelRef=attributes.labelRef||"",this.ref=attributes.ref||"",this.valueRef=attributes.valueRef||""}}class Bookend extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"bookend"),this.id=attributes.id||"",this.leader=attributes.leader||"",this.trailer=attributes.trailer||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class BooleanElement extends Option01{constructor(attributes){super(TEMPLATE_NS_ID,"boolean"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$toHTML](availableSpace){return valueToHtml(1===this[$content]?"1":"0")}}class Border extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"border",!0),this.break=getStringOption(attributes.break,["close","open"]),this.hand=getStringOption(attributes.hand,["even","left","right"]),this.id=attributes.id||"",this.presence=getStringOption(attributes.presence,["visible","hidden","inactive","invisible"]),this.relevant=getRelevant(attributes.relevant),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.corner=new XFAObjectArray(4),this.edge=new XFAObjectArray(4),this.extras=null,this.fill=null,this.margin=null}[$getExtra](){if(!this[$extra]){var edges=this.edge.children.slice();if(edges.length<4){var defaultEdge=edges.at(-1)||new Edge({});for(let i=edges.length;i<4;i++)edges.push(defaultEdge)}var widths=edges.map(edge=>edge.thickness),insets=[0,0,0,0];this.margin&&(insets[0]=this.margin.topInset,insets[1]=this.margin.rightInset,insets[2]=this.margin.bottomInset,insets[3]=this.margin.leftInset),this[$extra]={widths:widths,insets:insets,edges:edges}}return this[$extra]}[$toStyle](){var edges=this[$getExtra]()["edges"],edgeStyles=edges.map(node=>{node=node[$toStyle]();return node.color||="#000000",node}),style=Object.create(null);if(this.margin&&Object.assign(style,this.margin[$toStyle]()),"visible"===this.fill?.presence&&Object.assign(style,this.fill[$toStyle]()),this.corner.children.some(node=>0!==node.radius)){var cornerStyles=this.corner.children.map(node=>node[$toStyle]());if(2===cornerStyles.length||3===cornerStyles.length){var last=cornerStyles.at(-1);for(let i=cornerStyles.length;i<4;i++)cornerStyles.push(last)}style.borderRadius=cornerStyles.map(s=>s.radius).join(" ")}switch(this.presence){case"invisible":case"hidden":style.borderStyle="";break;case"inactive":style.borderStyle="none";break;default:style.borderStyle=edgeStyles.map(s=>s.style).join(" ")}return style.borderWidth=edgeStyles.map(s=>s.width).join(" "),style.borderColor=edgeStyles.map(s=>s.color).join(" "),style}}class Break extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"break",!0),this.after=getStringOption(attributes.after,["auto","contentArea","pageArea","pageEven","pageOdd"]),this.afterTarget=attributes.afterTarget||"",this.before=getStringOption(attributes.before,["auto","contentArea","pageArea","pageEven","pageOdd"]),this.beforeTarget=attributes.beforeTarget||"",this.bookendLeader=attributes.bookendLeader||"",this.bookendTrailer=attributes.bookendTrailer||"",this.id=attributes.id||"",this.overflowLeader=attributes.overflowLeader||"",this.overflowTarget=attributes.overflowTarget||"",this.overflowTrailer=attributes.overflowTrailer||"",this.startNew=getInteger({data:attributes.startNew,defaultValue:0,validate:x=>1===x}),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null}}class BreakAfter extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"breakAfter",!0),this.id=attributes.id||"",this.leader=attributes.leader||"",this.startNew=getInteger({data:attributes.startNew,defaultValue:0,validate:x=>1===x}),this.target=attributes.target||"",this.targetType=getStringOption(attributes.targetType,["auto","contentArea","pageArea"]),this.trailer=attributes.trailer||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.script=null}}class BreakBefore extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"breakBefore",!0),this.id=attributes.id||"",this.leader=attributes.leader||"",this.startNew=getInteger({data:attributes.startNew,defaultValue:0,validate:x=>1===x}),this.target=attributes.target||"",this.targetType=getStringOption(attributes.targetType,["auto","contentArea","pageArea"]),this.trailer=attributes.trailer||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.script=null}[$toHTML](availableSpace){return this[$extra]={},HTMLResult.FAILURE}}class Button extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"button",!0),this.highlight=getStringOption(attributes.highlight,["inverted","none","outline","push"]),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null}[$toHTML](availableSpace){var jsURL,href,grandpa=this[$getParent]()[$getParent](),htmlButton={name:"button",attributes:{id:this[$uid],class:["xfaButton"],style:{}},children:[]};for(const event of grandpa.event.children)"click"===event.activity&&event.script&&(jsURL=recoverJsURL(event.script[$content]))&&(href=fixURL(jsURL.url))&&htmlButton.children.push({name:"a",attributes:{id:"link"+this[$uid],href:href,newWindow:jsURL.newWindow,class:["xfaLink"],style:{}},children:[]});return HTMLResult.success(htmlButton)}}class Calculate extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"calculate",!0),this.id=attributes.id||"",this.override=getStringOption(attributes.override,["disabled","error","ignore","warning"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null,this.message=null,this.script=null}}class Caption extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"caption",!0),this.id=attributes.id||"",this.placement=getStringOption(attributes.placement,["left","bottom","inline","right","top"]),this.presence=getStringOption(attributes.presence,["visible","hidden","inactive","invisible"]),this.reserve=Math.ceil(getMeasurement(attributes.reserve)),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null,this.font=null,this.margin=null,this.para=null,this.value=null}[$setValue](value){_setValue(this,value)}[$getExtra](availableSpace){if(!this[$extra]){let{width,height}=availableSpace;switch(this.placement){case"left":case"right":case"inline":width=this.reserve<=0?width:this.reserve;break;case"top":case"bottom":height=this.reserve<=0?height:this.reserve}this[$extra]=layoutNode(this,{width:width,height:height})}return this[$extra]}[$toHTML](availableSpace){if(!this.value)return HTMLResult.EMPTY;this[$pushPara]();var value=this.value[$toHTML](availableSpace).html;if(!value)return this[$popPara](),HTMLResult.EMPTY;var savedReserve=this.reserve;if(this.reserve<=0){var{w,h}=this[$getExtra](availableSpace);switch(this.placement){case"left":case"right":case"inline":this.reserve=w;break;case"top":case"bottom":this.reserve=h}}var availableSpace=[],style=(availableSpace.push("string"==typeof value?{name:"#text",value:value}:value),toStyle(this,"font","margin","visibility"));switch(this.placement){case"left":case"right":01===x}),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.border=null,this.extras=null,this.margin=null}[$toHTML](availableSpace){var style=toStyle(this,"border","margin"),field=this[$getParent]()[$getParent](),optionStyle={fontSize:`calc(${field.font?.size||10}px * var(--scale-factor))`},children=[];if(00<=x}),this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class Connect extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"connect",!0),this.connection=attributes.connection||"",this.id=attributes.id||"",this.ref=attributes.ref||"",this.usage=getStringOption(attributes.usage,["exportAndImport","exportOnly","importOnly"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.picture=null}}class ContentArea extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"contentArea",!0),this.h=getMeasurement(attributes.h),this.id=attributes.id||"",this.name=attributes.name||"",this.relevant=getRelevant(attributes.relevant),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.w=getMeasurement(attributes.w),this.x=getMeasurement(attributes.x,"0pt"),this.y=getMeasurement(attributes.y,"0pt"),this.desc=null,this.extras=null}[$toHTML](availableSpace){var style={left:measureToString(this.x),top:measureToString(this.y),width:measureToString(this.w),height:measureToString(this.h)},classNames=["xfaContentarea"];return isPrintOnly(this)&&classNames.push("xfaPrintOnly"),HTMLResult.success({name:"div",children:[],attributes:{style:style,class:classNames,id:this[$uid]}})}}class Corner extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"corner",!0),this.id=attributes.id||"",this.inverted=getInteger({data:attributes.inverted,defaultValue:0,validate:x=>1===x}),this.join=getStringOption(attributes.join,["square","round"]),this.presence=getStringOption(attributes.presence,["visible","hidden","inactive","invisible"]),this.radius=getMeasurement(attributes.radius),this.stroke=getStringOption(attributes.stroke,["solid","dashDot","dashDotDot","dashed","dotted","embossed","etched","lowered","raised"]),this.thickness=getMeasurement(attributes.thickness,"0.5pt"),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.color=null,this.extras=null}[$toStyle](){var style=toStyle(this,"visibility");return style.radius=measureToString("square"===this.join?0:this.radius),style}}class DateElement extends ContentObject{constructor(attributes){super(TEMPLATE_NS_ID,"date"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$finalize](){var date=this[$content].trim();this[$content]=date?new Date(date):null}[$toHTML](availableSpace){return valueToHtml(this[$content]?this[$content].toString():"")}}class DateTime extends ContentObject{constructor(attributes){super(TEMPLATE_NS_ID,"dateTime"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$finalize](){var date=this[$content].trim();this[$content]=date?new Date(date):null}[$toHTML](availableSpace){return valueToHtml(this[$content]?this[$content].toString():"")}}class DateTimeEdit extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"dateTimeEdit",!0),this.hScrollPolicy=getStringOption(attributes.hScrollPolicy,["auto","off","on"]),this.id=attributes.id||"",this.picker=getStringOption(attributes.picker,["host","none"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.border=null,this.comb=null,this.extras=null,this.margin=null}[$toHTML](availableSpace){var style=toStyle(this,"border","font","margin"),field=this[$getParent]()[$getParent](),style={name:"input",attributes:{type:"text",fieldId:field[$uid],dataId:field[$data]?.[$uid]||field[$uid],class:["xfaTextfield"],style:style,"aria-label":ariaLabel(field),"aria-required":!1}};return isRequired(field)&&(style.attributes["aria-required"]=!0,style.attributes.required=!0),HTMLResult.success({name:"label",attributes:{class:["xfaLabel"]},children:[style]})}}class Decimal extends ContentObject{constructor(attributes){super(TEMPLATE_NS_ID,"decimal"),this.fracDigits=getInteger({data:attributes.fracDigits,defaultValue:2,validate:x=>!0}),this.id=attributes.id||"",this.leadDigits=getInteger({data:attributes.leadDigits,defaultValue:-1,validate:x=>!0}),this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$finalize](){var number=parseFloat(this[$content].trim());this[$content]=isNaN(number)?null:number}[$toHTML](availableSpace){return valueToHtml(null!==this[$content]?this[$content].toString():"")}}class DefaultUi extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"defaultUi",!0),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null}}class Desc extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"desc",!0),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.boolean=new XFAObjectArray,this.date=new XFAObjectArray,this.dateTime=new XFAObjectArray,this.decimal=new XFAObjectArray,this.exData=new XFAObjectArray,this.float=new XFAObjectArray,this.image=new XFAObjectArray,this.integer=new XFAObjectArray,this.text=new XFAObjectArray,this.time=new XFAObjectArray}}class DigestMethod extends OptionObject{constructor(attributes){super(TEMPLATE_NS_ID,"digestMethod",["","SHA1","SHA256","SHA512","RIPEMD160"]),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class DigestMethods extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"digestMethods",!0),this.id=attributes.id||"",this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.digestMethod=new XFAObjectArray}}class Draw extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"draw",!0),this.anchorType=getStringOption(attributes.anchorType,["topLeft","bottomCenter","bottomLeft","bottomRight","middleCenter","middleLeft","middleRight","topCenter","topRight"]),this.colSpan=getInteger({data:attributes.colSpan,defaultValue:1,validate:n=>1<=n||-1===n}),this.h=attributes.h?getMeasurement(attributes.h):"",this.hAlign=getStringOption(attributes.hAlign,["left","center","justify","justifyAll","radix","right"]),this.id=attributes.id||"",this.locale=attributes.locale||"",this.maxH=getMeasurement(attributes.maxH,"0pt"),this.maxW=getMeasurement(attributes.maxW,"0pt"),this.minH=getMeasurement(attributes.minH,"0pt"),this.minW=getMeasurement(attributes.minW,"0pt"),this.name=attributes.name||"",this.presence=getStringOption(attributes.presence,["visible","hidden","inactive","invisible"]),this.relevant=getRelevant(attributes.relevant),this.rotate=getInteger({data:attributes.rotate,defaultValue:0,validate:x=>x%90==0}),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.w=attributes.w?getMeasurement(attributes.w):"",this.x=getMeasurement(attributes.x,"0pt"),this.y=getMeasurement(attributes.y,"0pt"),this.assist=null,this.border=null,this.caption=null,this.desc=null,this.extras=null,this.font=null,this.keep=null,this.margin=null,this.para=null,this.traversal=null,this.ui=null,this.value=null,this.setProperty=new XFAObjectArray}[$setValue](value){_setValue(this,value)}[$toHTML](availableSpace){if(setTabIndex(this),"hidden"===this.presence||"inactive"===this.presence)return HTMLResult.EMPTY;fixDimensions(this),this[$pushPara]();var savedW=this.w,savedH=this.h,{w,h,isBroken}=layoutNode(this,availableSpace);if(w&&""===this.w){if(isBroken&&this[$getSubformParent]()[$isThereMoreWidth]())return this[$popPara](),HTMLResult.FAILURE;this.w=w}if(h&&""===this.h&&(this.h=h),setFirstUnsplittable(this),!checkDimensions(this,availableSpace))return this.w=savedW,this.h=savedH,this[$popPara](),HTMLResult.FAILURE;unsetFirstUnsplittable(this);isBroken=toStyle(this,"font","hAlign","dimensions","position","presence","rotate","anchorType","border","margin"),setMinMaxDimensions(this,isBroken),isBroken.margin&&(isBroken.padding=isBroken.margin,delete isBroken.margin),w=["xfaDraw"],this.font&&w.push("xfaFont"),isPrintOnly(this)&&w.push("xfaPrintOnly"),h={style:isBroken,id:this[$uid],class:w},this.name&&(h.xfaName=this.name),w={name:"div",attributes:h,children:[]},applyAssist(this,h),h=computeBbox(this,w,availableSpace),availableSpace=this.value?this.value[$toHTML](availableSpace).html:null;return null===availableSpace?(this.w=savedW,this.h=savedH,this[$popPara]()):(w.children.push(availableSpace),setPara(this,isBroken,availableSpace),this.w=savedW,this.h=savedH,this[$popPara]()),HTMLResult.success(createWrapper(this,w),h)}}class Edge extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"edge",!0),this.cap=getStringOption(attributes.cap,["square","butt","round"]),this.id=attributes.id||"",this.presence=getStringOption(attributes.presence,["visible","hidden","inactive","invisible"]),this.stroke=getStringOption(attributes.stroke,["solid","dashDot","dashDotDot","dashed","dotted","embossed","etched","lowered","raised"]),this.thickness=getMeasurement(attributes.thickness,"0.5pt"),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.color=null,this.extras=null}[$toStyle](){var style=toStyle(this,"visibility");if(Object.assign(style,{linecap:this.cap,width:measureToString(this.thickness),color:this.color?this.color[$toStyle]():"#000000",style:""}),"visible"!==this.presence)style.style="none";else switch(this.stroke){case"solid":style.style="solid";break;case"dashDot":case"dashDotDot":case"dashed":style.style="dashed";break;case"dotted":style.style="dotted";break;case"embossed":style.style="ridge";break;case"etched":style.style="groove";break;case"lowered":style.style="inset";break;case"raised":style.style="outset"}return style}}class Encoding extends OptionObject{constructor(attributes){super(TEMPLATE_NS_ID,"encoding",["adbe.x509.rsa_sha1","adbe.pkcs7.detached","adbe.pkcs7.sha1"]),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class Encodings extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"encodings",!0),this.id=attributes.id||"",this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.encoding=new XFAObjectArray}}class Encrypt extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"encrypt",!0),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.certificate=null}}class EncryptData extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"encryptData",!0),this.id=attributes.id||"",this.operation=getStringOption(attributes.operation,["encrypt","decrypt"]),this.target=attributes.target||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.filter=null,this.manifest=null}}class Encryption extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"encryption",!0),this.id=attributes.id||"",this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.certificate=new XFAObjectArray}}class EncryptionMethod extends OptionObject{constructor(attributes){super(TEMPLATE_NS_ID,"encryptionMethod",["","AES256-CBC","TRIPLEDES-CBC","AES128-CBC","AES192-CBC"]),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class EncryptionMethods extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"encryptionMethods",!0),this.id=attributes.id||"",this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.encryptionMethod=new XFAObjectArray}}class Event extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"event",!0),this.activity=getStringOption(attributes.activity,["click","change","docClose","docReady","enter","exit","full","indexChange","initialize","mouseDown","mouseEnter","mouseExit","mouseUp","postExecute","postOpen","postPrint","postSave","postSign","postSubmit","preExecute","preOpen","prePrint","preSave","preSign","preSubmit","ready","validationState"]),this.id=attributes.id||"",this.listen=getStringOption(attributes.listen,["refOnly","refAndDescendents"]),this.name=attributes.name||"",this.ref=attributes.ref||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null,this.encryptData=null,this.execute=null,this.script=null,this.signData=null,this.submit=null}}class ExData extends ContentObject{constructor(attributes){super(TEMPLATE_NS_ID,"exData"),this.contentType=attributes.contentType||"",this.href=attributes.href||"",this.id=attributes.id||"",this.maxLength=getInteger({data:attributes.maxLength,defaultValue:-1,validate:x=>-1<=x}),this.name=attributes.name||"",this.rid=attributes.rid||"",this.transferEncoding=getStringOption(attributes.transferEncoding,["none","base64","package"]),this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$isCDATAXml](){return"text/html"===this.contentType}[$onChild](child){return("text/html"===this.contentType&&child[$namespaceId]===NamespaceIds.xhtml.id||"text/xml"===this.contentType)&&(this[$content]=child,!0)}[$toHTML](availableSpace){return"text/html"===this.contentType&&this[$content]?this[$content][$toHTML](availableSpace):HTMLResult.EMPTY}}class ExObject extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"exObject",!0),this.archive=attributes.archive||"",this.classId=attributes.classId||"",this.codeBase=attributes.codeBase||"",this.codeType=attributes.codeType||"",this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null,this.boolean=new XFAObjectArray,this.date=new XFAObjectArray,this.dateTime=new XFAObjectArray,this.decimal=new XFAObjectArray,this.exData=new XFAObjectArray,this.exObject=new XFAObjectArray,this.float=new XFAObjectArray,this.image=new XFAObjectArray,this.integer=new XFAObjectArray,this.text=new XFAObjectArray,this.time=new XFAObjectArray}}class ExclGroup extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"exclGroup",!0),this.access=getStringOption(attributes.access,["open","nonInteractive","protected","readOnly"]),this.accessKey=attributes.accessKey||"",this.anchorType=getStringOption(attributes.anchorType,["topLeft","bottomCenter","bottomLeft","bottomRight","middleCenter","middleLeft","middleRight","topCenter","topRight"]),this.colSpan=getInteger({data:attributes.colSpan,defaultValue:1,validate:n=>1<=n||-1===n}),this.h=attributes.h?getMeasurement(attributes.h):"",this.hAlign=getStringOption(attributes.hAlign,["left","center","justify","justifyAll","radix","right"]),this.id=attributes.id||"",this.layout=getStringOption(attributes.layout,["position","lr-tb","rl-row","rl-tb","row","table","tb"]),this.maxH=getMeasurement(attributes.maxH,"0pt"),this.maxW=getMeasurement(attributes.maxW,"0pt"),this.minH=getMeasurement(attributes.minH,"0pt"),this.minW=getMeasurement(attributes.minW,"0pt"),this.name=attributes.name||"",this.presence=getStringOption(attributes.presence,["visible","hidden","inactive","invisible"]),this.relevant=getRelevant(attributes.relevant),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.w=attributes.w?getMeasurement(attributes.w):"",this.x=getMeasurement(attributes.x,"0pt"),this.y=getMeasurement(attributes.y,"0pt"),this.assist=null,this.bind=null,this.border=null,this.calculate=null,this.caption=null,this.desc=null,this.extras=null,this.margin=null,this.para=null,this.traversal=null,this.validate=null,this.connect=new XFAObjectArray,this.event=new XFAObjectArray,this.field=new XFAObjectArray,this.setProperty=new XFAObjectArray}[$isBindable](){return!0}[$hasSettableValue](){return!0}[$setValue](value){for(const field of this.field.children){var nodeValue;field.value||(nodeValue=new Value({}),field[$appendChild](nodeValue),field.value=nodeValue),field.value[$setValue](value)}}[$isThereMoreWidth](){return this.layout.endsWith("-tb")&&0===this[$extra].attempt&&01<=n||-1===n}),this.h=attributes.h?getMeasurement(attributes.h):"",this.hAlign=getStringOption(attributes.hAlign,["left","center","justify","justifyAll","radix","right"]),this.id=attributes.id||"",this.locale=attributes.locale||"",this.maxH=getMeasurement(attributes.maxH,"0pt"),this.maxW=getMeasurement(attributes.maxW,"0pt"),this.minH=getMeasurement(attributes.minH,"0pt"),this.minW=getMeasurement(attributes.minW,"0pt"),this.name=attributes.name||"",this.presence=getStringOption(attributes.presence,["visible","hidden","inactive","invisible"]),this.relevant=getRelevant(attributes.relevant),this.rotate=getInteger({data:attributes.rotate,defaultValue:0,validate:x=>x%90==0}),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.w=attributes.w?getMeasurement(attributes.w):"",this.x=getMeasurement(attributes.x,"0pt"),this.y=getMeasurement(attributes.y,"0pt"),this.assist=null,this.bind=null,this.border=null,this.calculate=null,this.caption=null,this.desc=null,this.extras=null,this.font=null,this.format=null,this.items=new XFAObjectArray(2),this.keep=null,this.margin=null,this.para=null,this.traversal=null,this.ui=null,this.validate=null,this.value=null,this.bindItems=new XFAObjectArray,this.connect=new XFAObjectArray,this.event=new XFAObjectArray,this.setProperty=new XFAObjectArray}[$isBindable](){return!0}[$setValue](value){_setValue(this,value)}[$toHTML](availableSpace){if(setTabIndex(this),!this.ui){this.ui=new Ui({}),this.ui[$globalData]=this[$globalData],this[$appendChild](this.ui);let node;switch(this.items.children.length){case 0:node=new TextEdit({}),this.ui.textEdit=node;break;case 1:node=new CheckButton({}),this.ui.checkButton=node;break;case 2:node=new ChoiceList({}),this.ui.choiceList=node}this.ui[$appendChild](node)}if(!this.ui||"hidden"===this.presence||"inactive"===this.presence||0===this.h||0===this.w)return HTMLResult.EMPTY;this.caption&&delete this.caption[$extra],this[$pushPara]();var caption=this.caption?this.caption[$toHTML](availableSpace).html:null,savedW=this.w,savedH=this.h;let marginH=0,marginV=0,borderDims=(this.margin&&(marginH=this.margin.leftInset+this.margin.rightInset,marginV=this.margin.topInset+this.margin.bottomInset),null);if(""===this.w||""===this.h){let width=null,height=null,uiW=0,uiH=0;if(this.ui.checkButton?uiW=uiH=this.ui.checkButton.size:({w,h}=layoutNode(this,availableSpace),uiH=null!==w?(uiW=w,h):fonts_getMetrics(this.font,!0).lineNoGap),borderDims=getBorderDims(this.ui[$getExtra]()),uiW+=borderDims.w,uiH+=borderDims.h,this.caption){const{w,h,isBroken}=this.caption[$getExtra](availableSpace);if(isBroken&&this[$getSubformParent]()[$isThereMoreWidth]())return this[$popPara](),HTMLResult.FAILURE;switch(width=w,height=h,this.caption.placement){case"left":case"right":case"inline":width+=uiW;break;case"top":case"bottom":height+=uiH}}else width=uiW,height=uiH;width&&""===this.w&&(width+=marginH,this.w=Math.min(this.maxW<=0?1/0:this.maxW,this.minW+11<=x&&x<=5}),this.appearanceFilter=null,this.certificates=null,this.digestMethods=null,this.encodings=null,this.encryptionMethods=null,this.handler=null,this.lockDocument=null,this.mdp=null,this.reasons=null,this.timeStamp=null}}class Float extends ContentObject{constructor(attributes){super(TEMPLATE_NS_ID,"float"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$finalize](){var number=parseFloat(this[$content].trim());this[$content]=isNaN(number)?null:number}[$toHTML](availableSpace){return valueToHtml(null!==this[$content]?this[$content].toString():"")}}class template_Font extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"font",!0),this.baselineShift=getMeasurement(attributes.baselineShift),this.fontHorizontalScale=getFloat({data:attributes.fontHorizontalScale,defaultValue:100,validate:x=>0<=x}),this.fontVerticalScale=getFloat({data:attributes.fontVerticalScale,defaultValue:100,validate:x=>0<=x}),this.id=attributes.id||"",this.kerningMode=getStringOption(attributes.kerningMode,["none","pair"]),this.letterSpacing=getMeasurement(attributes.letterSpacing,"0"),this.lineThrough=getInteger({data:attributes.lineThrough,defaultValue:0,validate:x=>1===x||2===x}),this.lineThroughPeriod=getStringOption(attributes.lineThroughPeriod,["all","word"]),this.overline=getInteger({data:attributes.overline,defaultValue:0,validate:x=>1===x||2===x}),this.overlinePeriod=getStringOption(attributes.overlinePeriod,["all","word"]),this.posture=getStringOption(attributes.posture,["normal","italic"]),this.size=getMeasurement(attributes.size,"10pt"),this.typeface=attributes.typeface||"Courier",this.underline=getInteger({data:attributes.underline,defaultValue:0,validate:x=>1===x||2===x}),this.underlinePeriod=getStringOption(attributes.underlinePeriod,["all","word"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.weight=getStringOption(attributes.weight,["normal","bold"]),this.extras=null,this.fill=null}[$clean](builder){super[$clean](builder),this[$globalData].usedTypefaces.add(this.typeface)}[$toStyle](){var style=toStyle(this,"fill"),color=style.color;return color&&("#000000"===color?delete style.color:color.startsWith("#")||(style.background=color,style.backgroundClip="text",style.color="transparent")),this.baselineShift&&(style.verticalAlign=measureToString(this.baselineShift)),style.fontKerning="none"===this.kerningMode?"none":"normal",style.letterSpacing=measureToString(this.letterSpacing),0!==this.lineThrough&&(style.textDecoration="line-through",2===this.lineThrough)&&(style.textDecorationStyle="double"),0!==this.overline&&(style.textDecoration="overline",2===this.overline)&&(style.textDecorationStyle="double"),style.fontStyle=this.posture,style.fontSize=measureToString(.99*this.size),setFontFamily(this,this,this[$globalData].fontFinder,style),0!==this.underline&&(style.textDecoration="underline",2===this.underline)&&(style.textDecorationStyle="double"),style.fontWeight=this.weight,style}}class Format extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"format",!0),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null,this.picture=null}}class Handler extends StringObject{constructor(attributes){super(TEMPLATE_NS_ID,"handler"),this.id=attributes.id||"",this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class Hyphenation extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"hyphenation"),this.excludeAllCaps=getInteger({data:attributes.excludeAllCaps,defaultValue:0,validate:x=>1===x}),this.excludeInitialCap=getInteger({data:attributes.excludeInitialCap,defaultValue:0,validate:x=>1===x}),this.hyphenate=getInteger({data:attributes.hyphenate,defaultValue:0,validate:x=>1===x}),this.id=attributes.id||"",this.pushCharacterCount=getInteger({data:attributes.pushCharacterCount,defaultValue:3,validate:x=>0<=x}),this.remainCharacterCount=getInteger({data:attributes.remainCharacterCount,defaultValue:3,validate:x=>0<=x}),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.wordCharacterCount=getInteger({data:attributes.wordCharacterCount,defaultValue:7,validate:x=>0<=x})}}class Image extends StringObject{constructor(attributes){super(TEMPLATE_NS_ID,"image"),this.aspect=getStringOption(attributes.aspect,["fit","actual","height","none","width"]),this.contentType=attributes.contentType||"",this.href=attributes.href||"",this.id=attributes.id||"",this.name=attributes.name||"",this.transferEncoding=getStringOption(attributes.transferEncoding,["base64","none","package"]),this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$toHTML](){if(this.contentType&&!MIMES.has(this.contentType.toLowerCase()))return HTMLResult.EMPTY;let buffer=this[$globalData].images&&this[$globalData].images.get(this.href);if(!buffer&&(this.href||!this[$content]))return HTMLResult.EMPTY;if(!(buffer=buffer||"base64"!==this.transferEncoding?buffer:stringToBytes(atob(this[$content]))))return HTMLResult.EMPTY;if(!this.contentType){for(var[header,type]of IMAGES_HEADERS)if(buffer.length>header.length&&header.every((x,i)=>x===buffer[i])){this.contentType=type;break}if(!this.contentType)return HTMLResult.EMPTY}var blob=new Blob([buffer],{type:this.contentType});let style;switch(this.aspect){case"fit":case"actual":break;case"height":style={height:"100%",objectFit:"fill"};break;case"none":style={width:"100%",height:"100%",objectFit:"fill"};break;case"width":style={width:"100%",objectFit:"fill"}}var parent=this[$getParent]();return HTMLResult.success({name:"img",attributes:{class:["xfaImage"],style:style,src:URL.createObjectURL(blob),alt:parent?ariaLabel(parent[$getParent]()):null}})}}class ImageEdit extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"imageEdit",!0),this.data=getStringOption(attributes.data,["link","embed"]),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.border=null,this.extras=null,this.margin=null}[$toHTML](availableSpace){return"embed"===this.data?HTMLResult.success({name:"div",children:[],attributes:{}}):HTMLResult.EMPTY}}class Integer extends ContentObject{constructor(attributes){super(TEMPLATE_NS_ID,"integer"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$finalize](){var number=parseInt(this[$content].trim(),10);this[$content]=isNaN(number)?null:number}[$toHTML](availableSpace){return valueToHtml(null!==this[$content]?this[$content].toString():"")}}class Issuers extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"issuers",!0),this.id=attributes.id||"",this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.certificate=new XFAObjectArray}}class Items extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"items",!0),this.id=attributes.id||"",this.name=attributes.name||"",this.presence=getStringOption(attributes.presence,["visible","hidden","inactive","invisible"]),this.ref=attributes.ref||"",this.save=getInteger({data:attributes.save,defaultValue:0,validate:x=>1===x}),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.boolean=new XFAObjectArray,this.date=new XFAObjectArray,this.dateTime=new XFAObjectArray,this.decimal=new XFAObjectArray,this.exData=new XFAObjectArray,this.float=new XFAObjectArray,this.image=new XFAObjectArray,this.integer=new XFAObjectArray,this.text=new XFAObjectArray,this.time=new XFAObjectArray}[$toHTML](){var output=[];for(const child of this[$getChildren]())output.push(child[$text]());return HTMLResult.success(output)}}class Keep extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"keep",!0),this.id=attributes.id||"";var options=["none","contentArea","pageArea"];this.intact=getStringOption(attributes.intact,options),this.next=getStringOption(attributes.next,options),this.previous=getStringOption(attributes.previous,options),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null}}class KeyUsage extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"keyUsage");var options=["","yes","no"];this.crlSign=getStringOption(attributes.crlSign,options),this.dataEncipherment=getStringOption(attributes.dataEncipherment,options),this.decipherOnly=getStringOption(attributes.decipherOnly,options),this.digitalSignature=getStringOption(attributes.digitalSignature,options),this.encipherOnly=getStringOption(attributes.encipherOnly,options),this.id=attributes.id||"",this.keyAgreement=getStringOption(attributes.keyAgreement,options),this.keyCertSign=getStringOption(attributes.keyCertSign,options),this.keyEncipherment=getStringOption(attributes.keyEncipherment,options),this.nonRepudiation=getStringOption(attributes.nonRepudiation,options),this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class Line extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"line",!0),this.hand=getStringOption(attributes.hand,["even","left","right"]),this.id=attributes.id||"",this.slope=getStringOption(attributes.slope,["\\","/"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.edge=null}[$toHTML](){var parent=this[$getParent]()[$getParent](),edge=this.edge||new Edge({}),edgeStyle=edge[$toStyle](),style=Object.create(null),edge="visible"===edge.presence?edge.thickness:0;style.strokeWidth=measureToString(edge),style.stroke=edgeStyle.color;let x1,y1,x2,y2,width="100%",height="100%";parent.w<=edge?([x1,y1,x2,y2]=["50%",0,"50%","100%"],width=style.strokeWidth):parent.h<=edge?([x1,y1,x2,y2]=[0,"50%","100%","50%"],height=style.strokeWidth):"\\"===this.slope?[x1,y1,x2,y2]=[0,0,"100%","100%"]:[x1,y1,x2,y2]=[0,"100%","100%",0];edgeStyle={name:"svg",children:[{name:"line",attributes:{xmlns:SVG_NS,x1:x1,y1:y1,x2:x2,y2:y2,style:style}}],attributes:{xmlns:SVG_NS,width:width,height:height,style:{overflow:"visible"}}};return hasMargin(parent)?HTMLResult.success({name:"div",attributes:{style:{display:"inline",width:"100%",height:"100%"}},children:[edgeStyle]}):(edgeStyle.attributes.style.position="absolute",HTMLResult.success(edgeStyle))}}class Linear extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"linear",!0),this.id=attributes.id||"",this.type=getStringOption(attributes.type,["toRight","toBottom","toLeft","toTop"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.color=null,this.extras=null}[$toStyle](startColor){return startColor=startColor?startColor[$toStyle]():"#FFFFFF",`linear-gradient(${this.type.replace(/([RBLT])/," $1").toLowerCase()}, ${startColor}, ${this.color?this.color[$toStyle]():"#000000"})`}}class LockDocument extends ContentObject{constructor(attributes){super(TEMPLATE_NS_ID,"lockDocument"),this.id=attributes.id||"",this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$finalize](){this[$content]=getStringOption(this[$content],["auto","0","1"])}}class Manifest extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"manifest",!0),this.action=getStringOption(attributes.action,["include","all","exclude"]),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null,this.ref=new XFAObjectArray}}class Margin extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"margin",!0),this.bottomInset=getMeasurement(attributes.bottomInset,"0"),this.id=attributes.id||"",this.leftInset=getMeasurement(attributes.leftInset,"0"),this.rightInset=getMeasurement(attributes.rightInset,"0"),this.topInset=getMeasurement(attributes.topInset,"0"),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null}[$toStyle](){return{margin:measureToString(this.topInset)+" "+measureToString(this.rightInset)+" "+measureToString(this.bottomInset)+" "+measureToString(this.leftInset)}}}class Mdp extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"mdp"),this.id=attributes.id||"",this.permissions=getInteger({data:attributes.permissions,defaultValue:2,validate:x=>1===x||3===x}),this.signatureType=getStringOption(attributes.signatureType,["filler","author"]),this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class Medium extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"medium"),this.id=attributes.id||"",this.imagingBBox=getBBox(attributes.imagingBBox),this.long=getMeasurement(attributes.long),this.orientation=getStringOption(attributes.orientation,["portrait","landscape"]),this.short=getMeasurement(attributes.short),this.stock=attributes.stock||"",this.trayIn=getStringOption(attributes.trayIn,["auto","delegate","pageFront"]),this.trayOut=getStringOption(attributes.trayOut,["auto","delegate"]),this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class Message extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"message",!0),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.text=new XFAObjectArray}}class NumericEdit extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"numericEdit",!0),this.hScrollPolicy=getStringOption(attributes.hScrollPolicy,["auto","off","on"]),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.border=null,this.comb=null,this.extras=null,this.margin=null}[$toHTML](availableSpace){var style=toStyle(this,"border","font","margin"),field=this[$getParent]()[$getParent](),style={name:"input",attributes:{type:"text",fieldId:field[$uid],dataId:field[$data]?.[$uid]||field[$uid],class:["xfaTextfield"],style:style,"aria-label":ariaLabel(field),"aria-required":!1}};return isRequired(field)&&(style.attributes["aria-required"]=!0,style.attributes.required=!0),HTMLResult.success({name:"label",attributes:{class:["xfaLabel"]},children:[style]})}}class Occur extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"occur",!0),this.id=attributes.id||"",this.initial=""!==attributes.initial?getInteger({data:attributes.initial,defaultValue:"",validate:x=>!0}):"",this.max=""!==attributes.max?getInteger({data:attributes.max,defaultValue:1,validate:x=>!0}):"",this.min=""!==attributes.min?getInteger({data:attributes.min,defaultValue:1,validate:x=>!0}):"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null}[$clean](){var parent=this[$getParent](),originalMin=this.min;""===this.min&&(this.min=parent instanceof PageArea||parent instanceof PageSet?0:1),""===this.max&&(this.max=""===originalMin?parent instanceof PageArea||parent instanceof PageSet?-1:1:this.min),-1!==this.max&&this.max!0}),this.name=attributes.name||"",this.numbered=getInteger({data:attributes.numbered,defaultValue:1,validate:x=>!0}),this.oddOrEven=getStringOption(attributes.oddOrEven,["any","even","odd"]),this.pagePosition=getStringOption(attributes.pagePosition,["any","first","last","only","rest"]),this.relevant=getRelevant(attributes.relevant),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.desc=null,this.extras=null,this.medium=null,this.occur=null,this.area=new XFAObjectArray,this.contentArea=new XFAObjectArray,this.draw=new XFAObjectArray,this.exclGroup=new XFAObjectArray,this.field=new XFAObjectArray,this.subform=new XFAObjectArray}[$isUsable](){return this[$extra]?!this.occur||-1===this.occur.max||this[$extra].numberOfUsep.oddOrEven===parity&&p.pagePosition===position);return parent||this.pageArea.children.find(p=>"any"===p.oddOrEven&&p.pagePosition===position)||this.pageArea.children.find(p=>"any"===p.oddOrEven&&"any"===p.pagePosition)||this.pageArea.children[0]}}class Para extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"para",!0),this.hAlign=getStringOption(attributes.hAlign,["left","center","justify","justifyAll","radix","right"]),this.id=attributes.id||"",this.lineHeight=attributes.lineHeight?getMeasurement(attributes.lineHeight,"0pt"):"",this.marginLeft=attributes.marginLeft?getMeasurement(attributes.marginLeft,"0pt"):"",this.marginRight=attributes.marginRight?getMeasurement(attributes.marginRight,"0pt"):"",this.orphans=getInteger({data:attributes.orphans,defaultValue:0,validate:x=>0<=x}),this.preserve=attributes.preserve||"",this.radixOffset=attributes.radixOffset?getMeasurement(attributes.radixOffset,"0pt"):"",this.spaceAbove=attributes.spaceAbove?getMeasurement(attributes.spaceAbove,"0pt"):"",this.spaceBelow=attributes.spaceBelow?getMeasurement(attributes.spaceBelow,"0pt"):"",this.tabDefault=attributes.tabDefault?getMeasurement(this.tabDefault):"",this.tabStops=(attributes.tabStops||"").trim().split(/\s+/).map((x,i)=>i%2==1?getMeasurement(x):x),this.textIndent=attributes.textIndent?getMeasurement(attributes.textIndent,"0pt"):"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.vAlign=getStringOption(attributes.vAlign,["top","bottom","middle"]),this.widows=getInteger({data:attributes.widows,defaultValue:0,validate:x=>0<=x}),this.hyphenation=null}[$toStyle](){var style=toStyle(this,"hAlign");return""!==this.marginLeft&&(style.paddingLeft=measureToString(this.marginLeft)),""!==this.marginRight&&(style.paddingight=measureToString(this.marginRight)),""!==this.spaceAbove&&(style.paddingTop=measureToString(this.spaceAbove)),""!==this.spaceBelow&&(style.paddingBottom=measureToString(this.spaceBelow)),""!==this.textIndent&&(style.textIndent=measureToString(this.textIndent),fixTextIndent(style)),01===x}),this.id=attributes.id||"",this.priority=getStringOption(attributes.priority,["custom","caption","name","toolTip"]),this.rid=attributes.rid||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class Stipple extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"stipple",!0),this.id=attributes.id||"",this.rate=getInteger({data:attributes.rate,defaultValue:50,validate:x=>0<=x&&x<=100}),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.color=null,this.extras=null}[$toStyle](bgColor){var alpha=this.rate/100;return Util.makeHexColor(Math.round(bgColor.value.r*(1-alpha)+this.value.r*alpha),Math.round(bgColor.value.g*(1-alpha)+this.value.g*alpha),Math.round(bgColor.value.b*(1-alpha)+this.value.b*alpha))}}class Subform extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"subform",!0),this.access=getStringOption(attributes.access,["open","nonInteractive","protected","readOnly"]),this.allowMacro=getInteger({data:attributes.allowMacro,defaultValue:0,validate:x=>1===x}),this.anchorType=getStringOption(attributes.anchorType,["topLeft","bottomCenter","bottomLeft","bottomRight","middleCenter","middleLeft","middleRight","topCenter","topRight"]),this.colSpan=getInteger({data:attributes.colSpan,defaultValue:1,validate:n=>1<=n||-1===n}),this.columnWidths=(attributes.columnWidths||"").trim().split(/\s+/).map(x=>"-1"===x?-1:getMeasurement(x)),this.h=attributes.h?getMeasurement(attributes.h):"",this.hAlign=getStringOption(attributes.hAlign,["left","center","justify","justifyAll","radix","right"]),this.id=attributes.id||"",this.layout=getStringOption(attributes.layout,["position","lr-tb","rl-row","rl-tb","row","table","tb"]),this.locale=attributes.locale||"",this.maxH=getMeasurement(attributes.maxH,"0pt"),this.maxW=getMeasurement(attributes.maxW,"0pt"),this.mergeMode=getStringOption(attributes.mergeMode,["consumeData","matchTemplate"]),this.minH=getMeasurement(attributes.minH,"0pt"),this.minW=getMeasurement(attributes.minW,"0pt"),this.name=attributes.name||"",this.presence=getStringOption(attributes.presence,["visible","hidden","inactive","invisible"]),this.relevant=getRelevant(attributes.relevant),this.restoreState=getStringOption(attributes.restoreState,["manual","auto"]),this.scope=getStringOption(attributes.scope,["name","none"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.w=attributes.w?getMeasurement(attributes.w):"",this.x=getMeasurement(attributes.x,"0pt"),this.y=getMeasurement(attributes.y,"0pt"),this.assist=null,this.bind=null,this.bookend=null,this.border=null,this.break=null,this.calculate=null,this.desc=null,this.extras=null,this.keep=null,this.margin=null,this.occur=null,this.overflow=null,this.pageSet=null,this.para=null,this.traversal=null,this.validate=null,this.variables=null,this.area=new XFAObjectArray,this.breakAfter=new XFAObjectArray,this.breakBefore=new XFAObjectArray,this.connect=new XFAObjectArray,this.draw=new XFAObjectArray,this.event=new XFAObjectArray,this.exObject=new XFAObjectArray,this.exclGroup=new XFAObjectArray,this.field=new XFAObjectArray,this.proto=new XFAObjectArray,this.setProperty=new XFAObjectArray,this.subform=new XFAObjectArray,this.subformSet=new XFAObjectArray}[$getSubformParent](){var parent=this[$getParent]();return parent instanceof SubformSet?parent[$getSubformParent]():parent}[$isBindable](){return!0}[$isThereMoreWidth](){return this.layout.endsWith("-tb")&&0===this[$extra].attempt&&0((kv=kv.split("=",2))[0]=kv[0].trim(),kv)))}}class SubjectDNs extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"subjectDNs",!0),this.id=attributes.id||"",this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.subjectDN=new XFAObjectArray}}class Submit extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"submit",!0),this.embedPDF=getInteger({data:attributes.embedPDF,defaultValue:0,validate:x=>1===x}),this.format=getStringOption(attributes.format,["xdp","formdata","pdf","urlencoded","xfd","xml"]),this.id=attributes.id||"",this.target=attributes.target||"",this.textEncoding=getKeyword({data:attributes.textEncoding?attributes.textEncoding.toLowerCase():"",defaultValue:"",validate:k=>["utf-8","big-five","fontspecific","gbk","gb-18030","gb-2312","ksc-5601","none","shift-jis","ucs-2","utf-16"].includes(k)||k.match(/iso-8859-\d{2}/)}),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.xdpContent=attributes.xdpContent||"",this.encrypt=null,this.encryptData=new XFAObjectArray,this.signData=new XFAObjectArray}}class Template extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"template",!0),this.baseProfile=getStringOption(attributes.baseProfile,["full","interactiveForms"]),this.extras=null,this.subform=new XFAObjectArray}[$finalize](){0===this.subform.children.length&&warn("XFA - No subforms in template node."),2<=this.subform.children.length&&warn("XFA - Several subforms in template node: please file a bug."),this[$tabIndex]=DEFAULT_TAB_INDEX}[$isSplittable](){return!0}[$searchNode](expr,container){return expr.startsWith("#")?[this[$ids].get(expr.slice(1))]:searchNode(this,container,expr,!0,!0)}*[$toPages](){if(!this.subform.children.length)return HTMLResult.success({name:"div",children:[]});this[$extra]={overflowNode:null,firstUnsplittable:null,currentContentArea:null,currentPageArea:null,noLayoutFailure:!1,pageNumber:1,pagePosition:"first",oddOrEven:"odd",blankOrNotBlank:"nonBlank",paraStack:[]};const root=this.subform.children[0];root.pageSet[$cleanPage]();var pageAreas=root.pageSet.pageArea.children,mainHtml={name:"div",children:[]};let pageArea=null,breakBefore=null,breakBeforeTarget=null;1<=root.breakBefore.children.length?(breakBefore=root.breakBefore.children[0],breakBeforeTarget=breakBefore.target):1<=root.subform.children.length&&1<=root.subform.children[0].breakBefore.children.length?(breakBefore=root.subform.children[0].breakBefore.children[0],breakBeforeTarget=breakBefore.target):root.break?.beforeTarget?(breakBefore=root.break,breakBeforeTarget=breakBefore.beforeTarget):1<=root.subform.children.length&&root.subform.children[0].break?.beforeTarget&&(breakBefore=root.subform.children[0].break,breakBeforeTarget=breakBefore.beforeTarget),breakBefore&&(target=this[$searchNode](breakBeforeTarget,breakBefore[$getParent]()))instanceof PageArea&&(pageArea=target,breakBefore[$extra]={}),(pageArea=pageArea||pageAreas[0])[$extra]={numberOfUse:1};var target=pageArea[$getParent]();target[$extra]={numberOfUse:1,pageIndex:target.pageArea.children.indexOf(pageArea),pageSetIndex:0};let targetPageArea,leader=null,trailer=null,hasSomething=!0,hasSomethingCounter=0,startIndex=0;for(;;){if(hasSomething)hasSomethingCounter=0;else if(mainHtml.children.pop(),++hasSomethingCounter===MAX_EMPTY_PAGES)return warn("XFA - Something goes wrong: please file a bug."),mainHtml;targetPageArea=null;var page=(this[$extra].currentPageArea=pageArea)[$toHTML]().html,contentAreas=(mainHtml.children.push(page),leader&&(this[$extra].noLayoutFailure=!0,page.children.push(leader[$toHTML](pageArea[$extra].space).html),leader=null),trailer&&(this[$extra].noLayoutFailure=!0,page.children.push(trailer[$toHTML](pageArea[$extra].space).html),trailer=null),pageArea.contentArea.children);const htmlContentAreas=page.children.filter(node=>node.attributes.class.includes("xfaContentarea"));hasSomething=!1,this[$extra].firstUnsplittable=null,this[$extra].noLayoutFailure=!1;var flush=index=>{var html=root[$flushHTML]();html&&(hasSomething||=00<=x}),this.name=attributes.name||"",this.rid=attributes.rid||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$acceptWhitespace](){return!0}[$onChild](child){return child[$namespaceId]===NamespaceIds.xhtml.id?(this[$content]=child,!0):(warn(`XFA - Invalid content in Text: ${child[$nodeName]}.`),!1)}[$onText](str){this[$content]instanceof XFAObject||super[$onText](str)}[$finalize](){"string"==typeof this[$content]&&(this[$content]=this[$content].replaceAll("\r\n","\n"))}[$getExtra](){return"string"==typeof this[$content]?this[$content].split(/[\u2029\u2028\n]/).reduce((acc,line)=>(line&&acc.push(line),acc),[]).join("\n"):this[$content][$text]()}[$toHTML](availableSpace){if("string"!=typeof this[$content])return this[$content][$toHTML](availableSpace);{const html=valueToHtml(this[$content]).html;return this[$content].includes("\u2029")?(html.name="div",html.children=[],this[$content].split("\u2029").map(para=>para.split(/[\u2028\n]/).reduce((acc,line)=>(acc.push({name:"span",value:line},{name:"br"}),acc),[])).forEach(lines=>{html.children.push({name:"p",children:lines})})):/[\u2028\n]/.test(this[$content])&&(html.name="div",html.children=[],this[$content].split(/[\u2028\n]/).forEach(line=>{html.children.push({name:"span",value:line},{name:"br"})})),HTMLResult.success(html)}}}class TextEdit extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"textEdit",!0),this.allowRichText=getInteger({data:attributes.allowRichText,defaultValue:0,validate:x=>1===x}),this.hScrollPolicy=getStringOption(attributes.hScrollPolicy,["auto","off","on"]),this.id=attributes.id||"",this.multiLine=getInteger({data:attributes.multiLine,defaultValue:"",validate:x=>0===x||1===x}),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.vScrollPolicy=getStringOption(attributes.vScrollPolicy,["auto","off","on"]),this.border=null,this.comb=null,this.extras=null,this.margin=null}[$toHTML](availableSpace){var style=toStyle(this,"border","font","margin");let html;var field=this[$getParent]()[$getParent]();return""===this.multiLine&&(this.multiLine=field instanceof Draw?1:0),html=1===this.multiLine?{name:"textarea",attributes:{dataId:field[$data]?.[$uid]||field[$uid],fieldId:field[$uid],class:["xfaTextfield"],style:style,"aria-label":ariaLabel(field),"aria-required":!1}}:{name:"input",attributes:{type:"text",dataId:field[$data]?.[$uid]||field[$uid],fieldId:field[$uid],class:["xfaTextfield"],style:style,"aria-label":ariaLabel(field),"aria-required":!1}},isRequired(field)&&(html.attributes["aria-required"]=!0,html.attributes.required=!0),HTMLResult.success({name:"label",attributes:{class:["xfaLabel"]},children:[html]})}}class Time extends StringObject{constructor(attributes){super(TEMPLATE_NS_ID,"time"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}[$finalize](){var date=this[$content].trim();this[$content]=date?new Date(date):null}[$toHTML](availableSpace){return valueToHtml(this[$content]?this[$content].toString():"")}}class TimeStamp extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"timeStamp"),this.id=attributes.id||"",this.server=attributes.server||"",this.type=getStringOption(attributes.type,["optional","required"]),this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class ToolTip extends StringObject{constructor(attributes){super(TEMPLATE_NS_ID,"toolTip"),this.id=attributes.id||"",this.rid=attributes.rid||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class Traversal extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"traversal",!0),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null,this.traverse=new XFAObjectArray}}class Traverse extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"traverse",!0),this.id=attributes.id||"",this.operation=getStringOption(attributes.operation,["next","back","down","first","left","right","up"]),this.ref=attributes.ref||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null,this.script=null}get name(){return this.operation}[$isTransparent](){return!1}}class Ui extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"ui",!0),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null,this.picture=null,this.barcode=null,this.button=null,this.checkButton=null,this.choiceList=null,this.dateTimeEdit=null,this.defaultUi=null,this.imageEdit=null,this.numericEdit=null,this.passwordEdit=null,this.signature=null,this.textEdit=null}[$getExtra](){if(void 0===this[$extra]){for(const name of Object.getOwnPropertyNames(this))if("extras"!==name&&"picture"!==name){var obj=this[name];if(obj instanceof XFAObject)return this[$extra]=obj}this[$extra]=null}return this[$extra]}[$toHTML](availableSpace){var obj=this[$getExtra]();return obj?obj[$toHTML](availableSpace):HTMLResult.EMPTY}}class Validate extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"validate",!0),this.formatTest=getStringOption(attributes.formatTest,["warning","disabled","error"]),this.id=attributes.id||"",this.nullTest=getStringOption(attributes.nullTest,["disabled","error","warning"]),this.scriptTest=getStringOption(attributes.scriptTest,["error","disabled","warning"]),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.extras=null,this.message=null,this.picture=null,this.script=null}}class Value extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"value",!0),this.id=attributes.id||"",this.override=getInteger({data:attributes.override,defaultValue:0,validate:x=>1===x}),this.relevant=getRelevant(attributes.relevant),this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.arc=null,this.boolean=null,this.date=null,this.dateTime=null,this.decimal=null,this.exData=null,this.float=null,this.image=null,this.integer=null,this.line=null,this.rectangle=null,this.text=null,this.time=null}[$setValue](value){var parent=this[$getParent]();if(parent instanceof Field&&parent.ui?.imageEdit)this.image||(this.image=new Image({}),this[$appendChild](this.image)),this.image[$content]=value[$content];else{parent=value[$nodeName];if(null!==this[parent])this[parent][$content]=value[$content];else{for(const name of Object.getOwnPropertyNames(this)){var obj=this[name];obj instanceof XFAObject&&(this[name]=null,this[$removeChild](obj))}this[value[$nodeName]]=value,this[$appendChild](value)}}}[$text](){if(this.exData)return("string"==typeof this.exData[$content]?this.exData[$content]:this.exData[$content][$text]()).trim();for(const name of Object.getOwnPropertyNames(this))if("image"!==name){var obj=this[name];if(obj instanceof XFAObject)return(obj[$content]||"").toString().trim()}return null}[$toHTML](availableSpace){for(const name of Object.getOwnPropertyNames(this)){var obj=this[name];if(obj instanceof XFAObject)return obj[$toHTML](availableSpace)}return HTMLResult.EMPTY}}class Variables extends XFAObject{constructor(attributes){super(TEMPLATE_NS_ID,"variables",!0),this.id=attributes.id||"",this.use=attributes.use||"",this.usehref=attributes.usehref||"",this.boolean=new XFAObjectArray,this.date=new XFAObjectArray,this.dateTime=new XFAObjectArray,this.decimal=new XFAObjectArray,this.exData=new XFAObjectArray,this.float=new XFAObjectArray,this.image=new XFAObjectArray,this.integer=new XFAObjectArray,this.manifest=new XFAObjectArray,this.script=new XFAObjectArray,this.text=new XFAObjectArray,this.time=new XFAObjectArray}[$isTransparent](){return!0}}class TemplateNamespace{static[$buildXFAObject](name,attributes){if(TemplateNamespace.hasOwnProperty(name))return(name=TemplateNamespace[name](attributes))[$setSetAttributes](attributes),name}static appearanceFilter(attrs){return new AppearanceFilter(attrs)}static arc(attrs){return new Arc(attrs)}static area(attrs){return new Area(attrs)}static assist(attrs){return new Assist(attrs)}static barcode(attrs){return new Barcode(attrs)}static bind(attrs){return new Bind(attrs)}static bindItems(attrs){return new BindItems(attrs)}static bookend(attrs){return new Bookend(attrs)}static boolean(attrs){return new BooleanElement(attrs)}static border(attrs){return new Border(attrs)}static break(attrs){return new Break(attrs)}static breakAfter(attrs){return new BreakAfter(attrs)}static breakBefore(attrs){return new BreakBefore(attrs)}static button(attrs){return new Button(attrs)}static calculate(attrs){return new Calculate(attrs)}static caption(attrs){return new Caption(attrs)}static certificate(attrs){return new Certificate(attrs)}static certificates(attrs){return new Certificates(attrs)}static checkButton(attrs){return new CheckButton(attrs)}static choiceList(attrs){return new ChoiceList(attrs)}static color(attrs){return new Color(attrs)}static comb(attrs){return new Comb(attrs)}static connect(attrs){return new Connect(attrs)}static contentArea(attrs){return new ContentArea(attrs)}static corner(attrs){return new Corner(attrs)}static date(attrs){return new DateElement(attrs)}static dateTime(attrs){return new DateTime(attrs)}static dateTimeEdit(attrs){return new DateTimeEdit(attrs)}static decimal(attrs){return new Decimal(attrs)}static defaultUi(attrs){return new DefaultUi(attrs)}static desc(attrs){return new Desc(attrs)}static digestMethod(attrs){return new DigestMethod(attrs)}static digestMethods(attrs){return new DigestMethods(attrs)}static draw(attrs){return new Draw(attrs)}static edge(attrs){return new Edge(attrs)}static encoding(attrs){return new Encoding(attrs)}static encodings(attrs){return new Encodings(attrs)}static encrypt(attrs){return new Encrypt(attrs)}static encryptData(attrs){return new EncryptData(attrs)}static encryption(attrs){return new Encryption(attrs)}static encryptionMethod(attrs){return new EncryptionMethod(attrs)}static encryptionMethods(attrs){return new EncryptionMethods(attrs)}static event(attrs){return new Event(attrs)}static exData(attrs){return new ExData(attrs)}static exObject(attrs){return new ExObject(attrs)}static exclGroup(attrs){return new ExclGroup(attrs)}static execute(attrs){return new Execute(attrs)}static extras(attrs){return new Extras(attrs)}static field(attrs){return new Field(attrs)}static fill(attrs){return new Fill(attrs)}static filter(attrs){return new Filter(attrs)}static float(attrs){return new Float(attrs)}static font(attrs){return new template_Font(attrs)}static format(attrs){return new Format(attrs)}static handler(attrs){return new Handler(attrs)}static hyphenation(attrs){return new Hyphenation(attrs)}static image(attrs){return new Image(attrs)}static imageEdit(attrs){return new ImageEdit(attrs)}static integer(attrs){return new Integer(attrs)}static issuers(attrs){return new Issuers(attrs)}static items(attrs){return new Items(attrs)}static keep(attrs){return new Keep(attrs)}static keyUsage(attrs){return new KeyUsage(attrs)}static line(attrs){return new Line(attrs)}static linear(attrs){return new Linear(attrs)}static lockDocument(attrs){return new LockDocument(attrs)}static manifest(attrs){return new Manifest(attrs)}static margin(attrs){return new Margin(attrs)}static mdp(attrs){return new Mdp(attrs)}static medium(attrs){return new Medium(attrs)}static message(attrs){return new Message(attrs)}static numericEdit(attrs){return new NumericEdit(attrs)}static occur(attrs){return new Occur(attrs)}static oid(attrs){return new Oid(attrs)}static oids(attrs){return new Oids(attrs)}static overflow(attrs){return new Overflow(attrs)}static pageArea(attrs){return new PageArea(attrs)}static pageSet(attrs){return new PageSet(attrs)}static para(attrs){return new Para(attrs)}static passwordEdit(attrs){return new PasswordEdit(attrs)}static pattern(attrs){return new template_Pattern(attrs)}static picture(attrs){return new Picture(attrs)}static proto(attrs){return new Proto(attrs)}static radial(attrs){return new Radial(attrs)}static reason(attrs){return new Reason(attrs)}static reasons(attrs){return new Reasons(attrs)}static rectangle(attrs){return new Rectangle(attrs)}static ref(attrs){return new RefElement(attrs)}static script(attrs){return new Script(attrs)}static setProperty(attrs){return new SetProperty(attrs)}static signData(attrs){return new SignData(attrs)}static signature(attrs){return new Signature(attrs)}static signing(attrs){return new Signing(attrs)}static solid(attrs){return new Solid(attrs)}static speak(attrs){return new Speak(attrs)}static stipple(attrs){return new Stipple(attrs)}static subform(attrs){return new Subform(attrs)}static subformSet(attrs){return new SubformSet(attrs)}static subjectDN(attrs){return new SubjectDN(attrs)}static subjectDNs(attrs){return new SubjectDNs(attrs)}static submit(attrs){return new Submit(attrs)}static template(attrs){return new Template(attrs)}static text(attrs){return new Text(attrs)}static textEdit(attrs){return new TextEdit(attrs)}static time(attrs){return new Time(attrs)}static timeStamp(attrs){return new TimeStamp(attrs)}static toolTip(attrs){return new ToolTip(attrs)}static traversal(attrs){return new Traversal(attrs)}static traverse(attrs){return new Traverse(attrs)}static ui(attrs){return new Ui(attrs)}static validate(attrs){return new Validate(attrs)}static value(attrs){return new Value(attrs)}static variables(attrs){return new Variables(attrs)}}const bind_NS_DATASETS=NamespaceIds.datasets.id;function createText(content){var node=new Text({});return node[$content]=content,node}class Binder{constructor(root){this.root=root,this.datasets=root.datasets,this.data=root.datasets?.data||new XmlObject(NamespaceIds.datasets.id,"data"),this.emptyMerge=0===this.data[$getChildren]().length,this.root.form=this.form=root.template[$clone]()}_isConsumeData(){return!this.emptyMerge&&this._mergeMode}_isMatchTemplate(){return!this._isConsumeData()}bind(){return this._bindElement(this.form,this.data),this.form}getData(){return this.data}_bindValue(formNode,data,picture){if(formNode[$data]=data,formNode[$hasSettableValue]())if(data[$isDataValue]()){var value=data[$getDataValue]();formNode[$setValue](createText(value))}else if(formNode instanceof Field&&"multiSelect"===formNode.ui?.choiceList?.open){const value=data[$getChildren]().map(child=>child[$content].trim()).join("\n");formNode[$setValue](createText(value))}else this._isConsumeData()&&warn("XFA - Nodes haven't the same type.");else!data[$isDataValue]()||this._isMatchTemplate()?this._bindElement(formNode,data):warn("XFA - Nodes haven't the same type.")}_findDataByNameToConsume(name,isValue,dataNode,global){if(!name)return null;let generator,match;for(let i=0;i<3;i++){for(generator=dataNode[$getRealChildrenByNameIt](name,!1,!0);;){if(!(match=generator.next().value))break;if(isValue===match[$isDataValue]())return match}if(dataNode[$namespaceId]===NamespaceIds.datasets.id&&"data"===dataNode[$nodeName])break;dataNode=dataNode[$getParent]()}return global?(generator=this.data[$getRealChildrenByNameIt](name,!0,!1),(match=generator.next().value)||(generator=this.data[$getAttributeIt](name,!0),(match=generator.next().value)?.[$isDataValue]()?match:null)):null}_setProperties(formNode,dataNode){if(formNode.hasOwnProperty("setProperty"))for(var{ref,target,connection}of formNode.setProperty.children){var targetNodes,targetParent,content,name,attrs;connection||ref&&((connection=searchNode(this.root,dataNode,ref,!1,!1))?([connection]=connection,connection[$isDescendent](this.data)?(targetNodes=searchNode(this.root,formNode,target,!1,!1))?([targetNodes]=targetNodes,targetNodes[$isDescendent](formNode)?(targetParent=targetNodes[$getParent](),targetNodes instanceof SetProperty||targetParent instanceof SetProperty?warn("XFA - Invalid target: cannot be a setProperty or one of its properties."):targetNodes instanceof BindItems||targetParent instanceof BindItems?warn("XFA - Invalid target: cannot be a bindItems or one of its properties."):(content=connection[$text](),name=targetNodes[$nodeName],targetNodes instanceof XFAAttribute?((attrs=Object.create(null))[name]=content,attrs=Reflect.construct(Object.getPrototypeOf(targetParent).constructor,[attrs]),targetParent[name]=attrs[name]):targetNodes.hasOwnProperty($content)?(targetNodes[$data]=connection,targetNodes[$content]=content,targetNodes[$finalize]()):warn("XFA - Invalid node to use in setProperty"))):warn("XFA - Invalid target: must be a property or subproperty.")):warn(`XFA - Invalid target: ${target}.`):warn("XFA - Invalid node: must be a data node.")):warn(`XFA - Invalid reference: ${ref}.`))}}_bindItems(formNode,dataNode){if(formNode.hasOwnProperty("items")&&formNode.hasOwnProperty("bindItems")&&!formNode.bindItems.isEmpty()){for(const item of formNode.items.children)formNode[$removeChild](item);formNode.items.clear();var ref,labelRef,valueRef,connection,labels=new Items({}),values=new Items({});formNode[$appendChild](labels),formNode.items.push(labels),formNode[$appendChild](values),formNode.items.push(values);for({ref,labelRef,valueRef,connection}of formNode.bindItems.children)if(!connection&&ref){var labelNodes,valueNodes,nodes=searchNode(this.root,dataNode,ref,!1,!1);if(nodes)for(const node of nodes)node[$isDescendent](this.datasets)?(labelNodes=searchNode(this.root,node,labelRef,!0,!1))?([labelNodes]=labelNodes,labelNodes[$isDescendent](this.datasets)?(valueNodes=searchNode(this.root,node,valueRef,!0,!1))?([valueNodes]=valueNodes,valueNodes[$isDescendent](this.datasets)?(labelNodes=createText(labelNodes[$text]()),valueNodes=createText(valueNodes[$text]()),labels[$appendChild](labelNodes),labels.text.push(labelNodes),values[$appendChild](valueNodes),values.text.push(valueNodes)):warn("XFA - Invalid value: must be a datasets child.")):warn(`XFA - Invalid value: ${valueRef}.`):warn("XFA - Invalid label: must be a datasets child.")):warn(`XFA - Invalid label: ${labelRef}.`):warn(`XFA - Invalid ref (${ref}): must be a datasets child.`);else warn(`XFA - Invalid reference: ${ref}.`)}}}_bindOccurrences(formNode,matches,picture){let baseClone;if(1e.name===formNode.name):parent[name].children).length;var pos=parent[$indexOf](formNode)+1,ii=occur.initial-currentNumber;if(ii){var nodeClone=formNode[$clone]();nodeClone[$removeChild](nodeClone.occur),nodeClone.occur=null,parent[name].push(nodeClone),parent[$insertAt](pos,nodeClone);for(let i=1;i!node[$consumed]):match).length>max?match=match.slice(0,max):0===match.length&&(match=null),match&&this._isConsumeData()&&match.forEach(node=>{node[$consumed]=!0})}else{if(!child.name){this._setAndBind(child,dataNode);continue}if(this._isConsumeData()){for(var matches=[];matches.lengthnode[$getParent]()[$removeChild](node))}}class DataHandler{constructor(root,data){this.data=data,this.dataset=root.datasets||null}serialize(storage){for(var stack=[[-1,this.data[$getChildren]()]];0'];if(this.dataset)for(const child of this.dataset[$getChildren]())"data"!==child[$nodeName]&&child[$toString](buf);return this.data[$toString](buf),buf.push(""),buf.join("")}}const CONFIG_NS_ID=NamespaceIds.config.id;class Acrobat extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"acrobat",!0),this.acrobat7=null,this.autoSave=null,this.common=null,this.validate=null,this.validateApprovalSignatures=null,this.submitUrl=new XFAObjectArray}}class Acrobat7 extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"acrobat7",!0),this.dynamicRender=null}}class ADBE_JSConsole extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"ADBE_JSConsole",["delegate","Enable","Disable"])}}class ADBE_JSDebugger extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"ADBE_JSDebugger",["delegate","Enable","Disable"])}}class AddSilentPrint extends Option01{constructor(attributes){super(CONFIG_NS_ID,"addSilentPrint")}}class AddViewerPreferences extends Option01{constructor(attributes){super(CONFIG_NS_ID,"addViewerPreferences")}}class AdjustData extends Option10{constructor(attributes){super(CONFIG_NS_ID,"adjustData")}}class AdobeExtensionLevel extends IntegerObject{constructor(attributes){super(CONFIG_NS_ID,"adobeExtensionLevel",0,n=>1<=n&&n<=8)}}class Agent extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"agent",!0),this.name=attributes.name?attributes.name.trim():"",this.common=new XFAObjectArray}}class AlwaysEmbed extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"alwaysEmbed")}}class Amd extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"amd")}}class config_Area extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"area"),this.level=getInteger({data:attributes.level,defaultValue:0,validate:n=>1<=n&&n<=3}),this.name=getStringOption(attributes.name,["","barcode","coreinit","deviceDriver","font","general","layout","merge","script","signature","sourceSet","templateCache"])}}class Attributes extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"attributes",["preserve","delegate","ignore"])}}class AutoSave extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"autoSave",["disabled","enabled"])}}class Base extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"base")}}class BatchOutput extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"batchOutput"),this.format=getStringOption(attributes.format,["none","concat","zip","zipCompress"])}}class BehaviorOverride extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"behaviorOverride")}[$finalize](){this[$content]=new Map(this[$content].trim().split(/\s+/).filter(x=>x.includes(":")).map(x=>x.split(":",2)))}}class Cache extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"cache",!0),this.templateCache=null}}class Change extends Option01{constructor(attributes){super(CONFIG_NS_ID,"change")}}class Common extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"common",!0),this.data=null,this.locale=null,this.localeSet=null,this.messaging=null,this.suppressBanner=null,this.template=null,this.validationMessaging=null,this.versionControl=null,this.log=new XFAObjectArray}}class Compress extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"compress"),this.scope=getStringOption(attributes.scope,["imageOnly","document"])}}class CompressLogicalStructure extends Option01{constructor(attributes){super(CONFIG_NS_ID,"compressLogicalStructure")}}class CompressObjectStream extends Option10{constructor(attributes){super(CONFIG_NS_ID,"compressObjectStream")}}class Compression extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"compression",!0),this.compressLogicalStructure=null,this.compressObjectStream=null,this.level=null,this.type=null}}class Config extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"config",!0),this.acrobat=null,this.present=null,this.trace=null,this.agent=new XFAObjectArray}}class Conformance extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"conformance",["A","B"])}}class ContentCopy extends Option01{constructor(attributes){super(CONFIG_NS_ID,"contentCopy")}}class Copies extends IntegerObject{constructor(attributes){super(CONFIG_NS_ID,"copies",1,n=>1<=n)}}class Creator extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"creator")}}class CurrentPage extends IntegerObject{constructor(attributes){super(CONFIG_NS_ID,"currentPage",0,n=>0<=n)}}class Data extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"data",!0),this.adjustData=null,this.attributes=null,this.incrementalLoad=null,this.outputXSL=null,this.range=null,this.record=null,this.startNode=null,this.uri=null,this.window=null,this.xsl=null,this.excludeNS=new XFAObjectArray,this.transform=new XFAObjectArray}}class Debug extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"debug",!0),this.uri=null}}class DefaultTypeface extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"defaultTypeface"),this.writingScript=getStringOption(attributes.writingScript,["*","Arabic","Cyrillic","EastEuropeanRoman","Greek","Hebrew","Japanese","Korean","Roman","SimplifiedChinese","Thai","TraditionalChinese","Vietnamese"])}}class Destination extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"destination",["pdf","pcl","ps","webClient","zpl"])}}class DocumentAssembly extends Option01{constructor(attributes){super(CONFIG_NS_ID,"documentAssembly")}}class Driver extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"driver",!0),this.name=attributes.name?attributes.name.trim():"",this.fontInfo=null,this.xdc=null}}class DuplexOption extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"duplexOption",["simplex","duplexFlipLongEdge","duplexFlipShortEdge"])}}class DynamicRender extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"dynamicRender",["forbidden","required"])}}class Embed extends Option01{constructor(attributes){super(CONFIG_NS_ID,"embed")}}class config_Encrypt extends Option01{constructor(attributes){super(CONFIG_NS_ID,"encrypt")}}class config_Encryption extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"encryption",!0),this.encrypt=null,this.encryptionLevel=null,this.permissions=null}}class EncryptionLevel extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"encryptionLevel",["40bit","128bit"])}}class Enforce extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"enforce")}}class Equate extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"equate"),this.force=getInteger({data:attributes.force,defaultValue:1,validate:n=>0===n}),this.from=attributes.from||"",this.to=attributes.to||""}}class EquateRange extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"equateRange"),this.from=attributes.from||"",this.to=attributes.to||"",this._unicodeRange=attributes.unicodeRange||""}get unicodeRange(){var range,ranges=[];const unicodeRegex=/U\+([0-9a-fA-F]+)/;for(range of this._unicodeRange.split(",").map(x=>x.trim()).filter(x=>!!x))1===(range=range.split("-",2).map(x=>{x=x.match(unicodeRegex);return x?parseInt(x[1],16):0})).length&&range.push(range[0]),ranges.push(range);return shadow(this,"unicodeRange",ranges)}}class Exclude extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"exclude")}[$finalize](){this[$content]=this[$content].trim().split(/\s+/).filter(x=>x&&["calculate","close","enter","exit","initialize","ready","validate"].includes(x))}}class ExcludeNS extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"excludeNS")}}class FlipLabel extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"flipLabel",["usePrinterSetting","on","off"])}}class config_FontInfo extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"fontInfo",!0),this.embed=null,this.map=null,this.subsetBelow=null,this.alwaysEmbed=new XFAObjectArray,this.defaultTypeface=new XFAObjectArray,this.neverEmbed=new XFAObjectArray}}class FormFieldFilling extends Option01{constructor(attributes){super(CONFIG_NS_ID,"formFieldFilling")}}class GroupParent extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"groupParent")}}class IfEmpty extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"ifEmpty",["dataValue","dataGroup","ignore","remove"])}}class IncludeXDPContent extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"includeXDPContent")}}class IncrementalLoad extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"incrementalLoad",["none","forwardOnly"])}}class IncrementalMerge extends Option01{constructor(attributes){super(CONFIG_NS_ID,"incrementalMerge")}}class Interactive extends Option01{constructor(attributes){super(CONFIG_NS_ID,"interactive")}}class Jog extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"jog",["usePrinterSetting","none","pageSet"])}}class LabelPrinter extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"labelPrinter",!0),this.name=getStringOption(attributes.name,["zpl","dpl","ipl","tcpl"]),this.batchOutput=null,this.flipLabel=null,this.fontInfo=null,this.xdc=null}}class Layout extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"layout",["paginate","panel"])}}class Level extends IntegerObject{constructor(attributes){super(CONFIG_NS_ID,"level",0,n=>01<=n)}}class NameAttr extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"nameAttr")}}class NeverEmbed extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"neverEmbed")}}class NumberOfCopies extends IntegerObject{constructor(attributes){super(CONFIG_NS_ID,"numberOfCopies",null,n=>2<=n&&n<=5)}}class OpenAction extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"openAction",!0),this.destination=null}}class Output extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"output",!0),this.to=null,this.type=null,this.uri=null}}class OutputBin extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"outputBin")}}class OutputXSL extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"outputXSL",!0),this.uri=null}}class Overprint extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"overprint",["none","both","draw","field"])}}class Packets extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"packets")}[$finalize](){"*"!==this[$content]&&(this[$content]=this[$content].trim().split(/\s+/).filter(x=>["config","datasets","template","xfdf","xslt"].includes(x)))}}class PageOffset extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"pageOffset"),this.x=getInteger({data:attributes.x,defaultValue:"useXDCSetting",validate:n=>!0}),this.y=getInteger({data:attributes.y,defaultValue:"useXDCSetting",validate:n=>!0})}}class PageRange extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"pageRange")}[$finalize](){var numbers=this[$content].trim().split(/\s+/).map(x=>parseInt(x,10)),ranges=[];for(let i=0,ii=numbers.length;i!1)}}class Pcl extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"pcl",!0),this.name=attributes.name||"",this.batchOutput=null,this.fontInfo=null,this.jog=null,this.mediumInfo=null,this.outputBin=null,this.pageOffset=null,this.staple=null,this.xdc=null}}class Pdf extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"pdf",!0),this.name=attributes.name||"",this.adobeExtensionLevel=null,this.batchOutput=null,this.compression=null,this.creator=null,this.encryption=null,this.fontInfo=null,this.interactive=null,this.linearized=null,this.openAction=null,this.pdfa=null,this.producer=null,this.renderPolicy=null,this.scriptModel=null,this.silentPrint=null,this.submitFormat=null,this.tagged=null,this.version=null,this.viewerPreferences=null,this.xdc=null}}class Pdfa extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"pdfa",!0),this.amd=null,this.conformance=null,this.includeXDPContent=null,this.part=null}}class Permissions extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"permissions",!0),this.accessibleContent=null,this.change=null,this.contentCopy=null,this.documentAssembly=null,this.formFieldFilling=null,this.modifyAnnots=null,this.plaintextMetadata=null,this.print=null,this.printHighQuality=null}}class PickTrayByPDFSize extends Option01{constructor(attributes){super(CONFIG_NS_ID,"pickTrayByPDFSize")}}class config_Picture extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"picture")}}class PlaintextMetadata extends Option01{constructor(attributes){super(CONFIG_NS_ID,"plaintextMetadata")}}class Presence extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"presence",["preserve","dissolve","dissolveStructure","ignore","remove"])}}class Present extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"present",!0),this.behaviorOverride=null,this.cache=null,this.common=null,this.copies=null,this.destination=null,this.incrementalMerge=null,this.layout=null,this.output=null,this.overprint=null,this.pagination=null,this.paginationOverride=null,this.script=null,this.validate=null,this.xdp=null,this.driver=new XFAObjectArray,this.labelPrinter=new XFAObjectArray,this.pcl=new XFAObjectArray,this.pdf=new XFAObjectArray,this.ps=new XFAObjectArray,this.submitUrl=new XFAObjectArray,this.webClient=new XFAObjectArray,this.zpl=new XFAObjectArray}}class Print extends Option01{constructor(attributes){super(CONFIG_NS_ID,"print")}}class PrintHighQuality extends Option01{constructor(attributes){super(CONFIG_NS_ID,"printHighQuality")}}class PrintScaling extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"printScaling",["appdefault","noScaling"])}}class PrinterName extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"printerName")}}class Producer extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"producer")}}class Ps extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"ps",!0),this.name=attributes.name||"",this.batchOutput=null,this.fontInfo=null,this.jog=null,this.mediumInfo=null,this.outputBin=null,this.staple=null,this.xdc=null}}class Range extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"range")}[$finalize](){this[$content]=this[$content].trim().split(/\s*,\s*/,2).map(range=>range.split("-").map(x=>parseInt(x.trim(),10))).filter(range=>range.every(x=>!isNaN(x))).map(range=>(1===range.length&&range.push(range[0]),range))}}class Record extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"record")}[$finalize](){this[$content]=this[$content].trim();var n=parseInt(this[$content],10);!isNaN(n)&&0<=n&&(this[$content]=n)}}class Relevant extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"relevant")}[$finalize](){this[$content]=this[$content].trim().split(/\s+/)}}class Rename extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"rename")}[$finalize](){this[$content]=this[$content].trim(),(this[$content].toLowerCase().startsWith("xml")||new RegExp("[\\p{L}_][\\p{L}\\d._\\p{M}-]*","u").test(this[$content]))&&warn("XFA - Rename: invalid XFA name")}}class RenderPolicy extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"renderPolicy",["server","client"])}}class RunScripts extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"runScripts",["both","client","none","server"])}}class config_Script extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"script",!0),this.currentPage=null,this.exclude=null,this.runScripts=null}}class ScriptModel extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"scriptModel",["XFA","none"])}}class Severity extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"severity",["ignore","error","information","trace","warning"])}}class SilentPrint extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"silentPrint",!0),this.addSilentPrint=null,this.printerName=null}}class Staple extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"staple"),this.mode=getStringOption(attributes.mode,["usePrinterSetting","on","off"])}}class StartNode extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"startNode")}}class StartPage extends IntegerObject{constructor(attributes){super(CONFIG_NS_ID,"startPage",0,n=>!0)}}class SubmitFormat extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"submitFormat",["html","delegate","fdf","xml","pdf"])}}class SubmitUrl extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"submitUrl")}}class SubsetBelow extends IntegerObject{constructor(attributes){super(CONFIG_NS_ID,"subsetBelow",100,n=>0<=n&&n<=100)}}class SuppressBanner extends Option01{constructor(attributes){super(CONFIG_NS_ID,"suppressBanner")}}class Tagged extends Option01{constructor(attributes){super(CONFIG_NS_ID,"tagged")}}class config_Template extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"template",!0),this.base=null,this.relevant=null,this.startPage=null,this.uri=null,this.xsl=null}}class Threshold extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"threshold",["trace","error","information","warning"])}}class To extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"to",["null","memory","stderr","stdout","system","uri"])}}class TemplateCache extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"templateCache"),this.maxEntries=getInteger({data:attributes.maxEntries,defaultValue:5,validate:n=>0<=n})}}class Trace extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"trace",!0),this.area=new XFAObjectArray}}class Transform extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"transform",!0),this.groupParent=null,this.ifEmpty=null,this.nameAttr=null,this.picture=null,this.presence=null,this.rename=null,this.whitespace=null}}class Type extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"type",["none","ascii85","asciiHex","ccittfax","flate","lzw","runLength","native","xdp","mergedXDP"])}}class Uri extends StringObject{constructor(attributes){super(CONFIG_NS_ID,"uri")}}class config_Validate extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"validate",["preSubmit","prePrint","preExecute","preSave"])}}class ValidateApprovalSignatures extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"validateApprovalSignatures")}[$finalize](){this[$content]=this[$content].trim().split(/\s+/).filter(x=>["docReady","postSign"].includes(x))}}class ValidationMessaging extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"validationMessaging",["allMessagesIndividually","allMessagesTogether","firstMessageOnly","noMessages"])}}class Version extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"version",["1.7","1.6","1.5","1.4","1.3","1.2"])}}class VersionControl extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"VersionControl"),this.outputBelow=getStringOption(attributes.outputBelow,["warn","error","update"]),this.sourceAbove=getStringOption(attributes.sourceAbove,["warn","error"]),this.sourceBelow=getStringOption(attributes.sourceBelow,["update","maintain"])}}class ViewerPreferences extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"viewerPreferences",!0),this.ADBE_JSConsole=null,this.ADBE_JSDebugger=null,this.addViewerPreferences=null,this.duplexOption=null,this.enforce=null,this.numberOfCopies=null,this.pageRange=null,this.pickTrayByPDFSize=null,this.printScaling=null}}class WebClient extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"webClient",!0),this.name=attributes.name?attributes.name.trim():"",this.fontInfo=null,this.xdc=null}}class Whitespace extends OptionObject{constructor(attributes){super(CONFIG_NS_ID,"whitespace",["preserve","ltrim","normalize","rtrim","trim"])}}class Window extends ContentObject{constructor(attributes){super(CONFIG_NS_ID,"window")}[$finalize](){var pair=this[$content].trim().split(/\s*,\s*/,2).map(x=>parseInt(x,10));pair.some(x=>isNaN(x))?this[$content]=[0,0]:(1===pair.length&&pair.push(pair[0]),this[$content]=pair)}}class Xdc extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"xdc",!0),this.uri=new XFAObjectArray,this.xsl=new XFAObjectArray}}class Xdp extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"xdp",!0),this.packets=null}}class Xsl extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"xsl",!0),this.debug=null,this.uri=null}}class Zpl extends XFAObject{constructor(attributes){super(CONFIG_NS_ID,"zpl",!0),this.name=attributes.name?attributes.name.trim():"",this.batchOutput=null,this.flipLabel=null,this.fontInfo=null,this.xdc=null}}class ConfigNamespace{static[$buildXFAObject](name,attributes){if(ConfigNamespace.hasOwnProperty(name))return ConfigNamespace[name](attributes)}static acrobat(attrs){return new Acrobat(attrs)}static acrobat7(attrs){return new Acrobat7(attrs)}static ADBE_JSConsole(attrs){return new ADBE_JSConsole(attrs)}static ADBE_JSDebugger(attrs){return new ADBE_JSDebugger(attrs)}static addSilentPrint(attrs){return new AddSilentPrint(attrs)}static addViewerPreferences(attrs){return new AddViewerPreferences(attrs)}static adjustData(attrs){return new AdjustData(attrs)}static adobeExtensionLevel(attrs){return new AdobeExtensionLevel(attrs)}static agent(attrs){return new Agent(attrs)}static alwaysEmbed(attrs){return new AlwaysEmbed(attrs)}static amd(attrs){return new Amd(attrs)}static area(attrs){return new config_Area(attrs)}static attributes(attrs){return new Attributes(attrs)}static autoSave(attrs){return new AutoSave(attrs)}static base(attrs){return new Base(attrs)}static batchOutput(attrs){return new BatchOutput(attrs)}static behaviorOverride(attrs){return new BehaviorOverride(attrs)}static cache(attrs){return new Cache(attrs)}static change(attrs){return new Change(attrs)}static common(attrs){return new Common(attrs)}static compress(attrs){return new Compress(attrs)}static compressLogicalStructure(attrs){return new CompressLogicalStructure(attrs)}static compressObjectStream(attrs){return new CompressObjectStream(attrs)}static compression(attrs){return new Compression(attrs)}static config(attrs){return new Config(attrs)}static conformance(attrs){return new Conformance(attrs)}static contentCopy(attrs){return new ContentCopy(attrs)}static copies(attrs){return new Copies(attrs)}static creator(attrs){return new Creator(attrs)}static currentPage(attrs){return new CurrentPage(attrs)}static data(attrs){return new Data(attrs)}static debug(attrs){return new Debug(attrs)}static defaultTypeface(attrs){return new DefaultTypeface(attrs)}static destination(attrs){return new Destination(attrs)}static documentAssembly(attrs){return new DocumentAssembly(attrs)}static driver(attrs){return new Driver(attrs)}static duplexOption(attrs){return new DuplexOption(attrs)}static dynamicRender(attrs){return new DynamicRender(attrs)}static embed(attrs){return new Embed(attrs)}static encrypt(attrs){return new config_Encrypt(attrs)}static encryption(attrs){return new config_Encryption(attrs)}static encryptionLevel(attrs){return new EncryptionLevel(attrs)}static enforce(attrs){return new Enforce(attrs)}static equate(attrs){return new Equate(attrs)}static equateRange(attrs){return new EquateRange(attrs)}static exclude(attrs){return new Exclude(attrs)}static excludeNS(attrs){return new ExcludeNS(attrs)}static flipLabel(attrs){return new FlipLabel(attrs)}static fontInfo(attrs){return new config_FontInfo(attrs)}static formFieldFilling(attrs){return new FormFieldFilling(attrs)}static groupParent(attrs){return new GroupParent(attrs)}static ifEmpty(attrs){return new IfEmpty(attrs)}static includeXDPContent(attrs){return new IncludeXDPContent(attrs)}static incrementalLoad(attrs){return new IncrementalLoad(attrs)}static incrementalMerge(attrs){return new IncrementalMerge(attrs)}static interactive(attrs){return new Interactive(attrs)}static jog(attrs){return new Jog(attrs)}static labelPrinter(attrs){return new LabelPrinter(attrs)}static layout(attrs){return new Layout(attrs)}static level(attrs){return new Level(attrs)}static linearized(attrs){return new Linearized(attrs)}static locale(attrs){return new Locale(attrs)}static localeSet(attrs){return new LocaleSet(attrs)}static log(attrs){return new Log(attrs)}static map(attrs){return new MapElement(attrs)}static mediumInfo(attrs){return new MediumInfo(attrs)}static message(attrs){return new config_Message(attrs)}static messaging(attrs){return new Messaging(attrs)}static mode(attrs){return new Mode(attrs)}static modifyAnnots(attrs){return new ModifyAnnots(attrs)}static msgId(attrs){return new MsgId(attrs)}static nameAttr(attrs){return new NameAttr(attrs)}static neverEmbed(attrs){return new NeverEmbed(attrs)}static numberOfCopies(attrs){return new NumberOfCopies(attrs)}static openAction(attrs){return new OpenAction(attrs)}static output(attrs){return new Output(attrs)}static outputBin(attrs){return new OutputBin(attrs)}static outputXSL(attrs){return new OutputXSL(attrs)}static overprint(attrs){return new Overprint(attrs)}static packets(attrs){return new Packets(attrs)}static pageOffset(attrs){return new PageOffset(attrs)}static pageRange(attrs){return new PageRange(attrs)}static pagination(attrs){return new Pagination(attrs)}static paginationOverride(attrs){return new PaginationOverride(attrs)}static part(attrs){return new Part(attrs)}static pcl(attrs){return new Pcl(attrs)}static pdf(attrs){return new Pdf(attrs)}static pdfa(attrs){return new Pdfa(attrs)}static permissions(attrs){return new Permissions(attrs)}static pickTrayByPDFSize(attrs){return new PickTrayByPDFSize(attrs)}static picture(attrs){return new config_Picture(attrs)}static plaintextMetadata(attrs){return new PlaintextMetadata(attrs)}static presence(attrs){return new Presence(attrs)}static present(attrs){return new Present(attrs)}static print(attrs){return new Print(attrs)}static printHighQuality(attrs){return new PrintHighQuality(attrs)}static printScaling(attrs){return new PrintScaling(attrs)}static printerName(attrs){return new PrinterName(attrs)}static producer(attrs){return new Producer(attrs)}static ps(attrs){return new Ps(attrs)}static range(attrs){return new Range(attrs)}static record(attrs){return new Record(attrs)}static relevant(attrs){return new Relevant(attrs)}static rename(attrs){return new Rename(attrs)}static renderPolicy(attrs){return new RenderPolicy(attrs)}static runScripts(attrs){return new RunScripts(attrs)}static script(attrs){return new config_Script(attrs)}static scriptModel(attrs){return new ScriptModel(attrs)}static severity(attrs){return new Severity(attrs)}static silentPrint(attrs){return new SilentPrint(attrs)}static staple(attrs){return new Staple(attrs)}static startNode(attrs){return new StartNode(attrs)}static startPage(attrs){return new StartPage(attrs)}static submitFormat(attrs){return new SubmitFormat(attrs)}static submitUrl(attrs){return new SubmitUrl(attrs)}static subsetBelow(attrs){return new SubsetBelow(attrs)}static suppressBanner(attrs){return new SuppressBanner(attrs)}static tagged(attrs){return new Tagged(attrs)}static template(attrs){return new config_Template(attrs)}static templateCache(attrs){return new TemplateCache(attrs)}static threshold(attrs){return new Threshold(attrs)}static to(attrs){return new To(attrs)}static trace(attrs){return new Trace(attrs)}static transform(attrs){return new Transform(attrs)}static type(attrs){return new Type(attrs)}static uri(attrs){return new Uri(attrs)}static validate(attrs){return new config_Validate(attrs)}static validateApprovalSignatures(attrs){return new ValidateApprovalSignatures(attrs)}static validationMessaging(attrs){return new ValidationMessaging(attrs)}static version(attrs){return new Version(attrs)}static versionControl(attrs){return new VersionControl(attrs)}static viewerPreferences(attrs){return new ViewerPreferences(attrs)}static webClient(attrs){return new WebClient(attrs)}static whitespace(attrs){return new Whitespace(attrs)}static window(attrs){return new Window(attrs)}static xdc(attrs){return new Xdc(attrs)}static xdp(attrs){return new Xdp(attrs)}static xsl(attrs){return new Xsl(attrs)}static zpl(attrs){return new Zpl(attrs)}}const CONNECTION_SET_NS_ID=NamespaceIds.connectionSet.id;class ConnectionSet extends XFAObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"connectionSet",!0),this.wsdlConnection=new XFAObjectArray,this.xmlConnection=new XFAObjectArray,this.xsdConnection=new XFAObjectArray}}class EffectiveInputPolicy extends XFAObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"effectiveInputPolicy"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class EffectiveOutputPolicy extends XFAObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"effectiveOutputPolicy"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class Operation extends StringObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"operation"),this.id=attributes.id||"",this.input=attributes.input||"",this.name=attributes.name||"",this.output=attributes.output||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class RootElement extends StringObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"rootElement"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class SoapAction extends StringObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"soapAction"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class SoapAddress extends StringObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"soapAddress"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class connection_set_Uri extends StringObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"uri"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class WsdlAddress extends StringObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"wsdlAddress"),this.id=attributes.id||"",this.name=attributes.name||"",this.use=attributes.use||"",this.usehref=attributes.usehref||""}}class WsdlConnection extends XFAObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"wsdlConnection",!0),this.dataDescription=attributes.dataDescription||"",this.name=attributes.name||"",this.effectiveInputPolicy=null,this.effectiveOutputPolicy=null,this.operation=null,this.soapAction=null,this.soapAddress=null,this.wsdlAddress=null}}class XmlConnection extends XFAObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"xmlConnection",!0),this.dataDescription=attributes.dataDescription||"",this.name=attributes.name||"",this.uri=null}}class XsdConnection extends XFAObject{constructor(attributes){super(CONNECTION_SET_NS_ID,"xsdConnection",!0),this.dataDescription=attributes.dataDescription||"",this.name=attributes.name||"",this.rootElement=null,this.uri=null}}class ConnectionSetNamespace{static[$buildXFAObject](name,attributes){if(ConnectionSetNamespace.hasOwnProperty(name))return ConnectionSetNamespace[name](attributes)}static connectionSet(attrs){return new ConnectionSet(attrs)}static effectiveInputPolicy(attrs){return new EffectiveInputPolicy(attrs)}static effectiveOutputPolicy(attrs){return new EffectiveOutputPolicy(attrs)}static operation(attrs){return new Operation(attrs)}static rootElement(attrs){return new RootElement(attrs)}static soapAction(attrs){return new SoapAction(attrs)}static soapAddress(attrs){return new SoapAddress(attrs)}static uri(attrs){return new connection_set_Uri(attrs)}static wsdlAddress(attrs){return new WsdlAddress(attrs)}static wsdlConnection(attrs){return new WsdlConnection(attrs)}static xmlConnection(attrs){return new XmlConnection(attrs)}static xsdConnection(attrs){return new XsdConnection(attrs)}}const DATASETS_NS_ID=NamespaceIds.datasets.id;class datasets_Data extends XmlObject{constructor(attributes){super(DATASETS_NS_ID,"data",attributes)}[$isNsAgnostic](){return!0}}class Datasets extends XFAObject{constructor(attributes){super(DATASETS_NS_ID,"datasets",!0),this.data=null,this.Signature=null}[$onChild](child){var name=child[$nodeName];("data"===name&&child[$namespaceId]===DATASETS_NS_ID||"Signature"===name&&child[$namespaceId]===NamespaceIds.signature.id)&&(this[name]=child),this[$appendChild](child)}}class DatasetsNamespace{static[$buildXFAObject](name,attributes){if(DatasetsNamespace.hasOwnProperty(name))return DatasetsNamespace[name](attributes)}static datasets(attributes){return new Datasets(attributes)}static data(attributes){return new datasets_Data(attributes)}}const LOCALE_SET_NS_ID=NamespaceIds.localeSet.id;class CalendarSymbols extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"calendarSymbols",!0),this.name="gregorian",this.dayNames=new XFAObjectArray(2),this.eraNames=null,this.meridiemNames=null,this.monthNames=new XFAObjectArray(2)}}class CurrencySymbol extends StringObject{constructor(attributes){super(LOCALE_SET_NS_ID,"currencySymbol"),this.name=getStringOption(attributes.name,["symbol","isoname","decimal"])}}class CurrencySymbols extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"currencySymbols",!0),this.currencySymbol=new XFAObjectArray(3)}}class DatePattern extends StringObject{constructor(attributes){super(LOCALE_SET_NS_ID,"datePattern"),this.name=getStringOption(attributes.name,["full","long","med","short"])}}class DatePatterns extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"datePatterns",!0),this.datePattern=new XFAObjectArray(4)}}class DateTimeSymbols extends ContentObject{constructor(attributes){super(LOCALE_SET_NS_ID,"dateTimeSymbols")}}class Day extends StringObject{constructor(attributes){super(LOCALE_SET_NS_ID,"day")}}class DayNames extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"dayNames",!0),this.abbr=getInteger({data:attributes.abbr,defaultValue:0,validate:x=>1===x}),this.day=new XFAObjectArray(7)}}class Era extends StringObject{constructor(attributes){super(LOCALE_SET_NS_ID,"era")}}class EraNames extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"eraNames",!0),this.era=new XFAObjectArray(2)}}class locale_set_Locale extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"locale",!0),this.desc=attributes.desc||"",this.name="isoname",this.calendarSymbols=null,this.currencySymbols=null,this.datePatterns=null,this.dateTimeSymbols=null,this.numberPatterns=null,this.numberSymbols=null,this.timePatterns=null,this.typeFaces=null}}class locale_set_LocaleSet extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"localeSet",!0),this.locale=new XFAObjectArray}}class Meridiem extends StringObject{constructor(attributes){super(LOCALE_SET_NS_ID,"meridiem")}}class MeridiemNames extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"meridiemNames",!0),this.meridiem=new XFAObjectArray(2)}}class Month extends StringObject{constructor(attributes){super(LOCALE_SET_NS_ID,"month")}}class MonthNames extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"monthNames",!0),this.abbr=getInteger({data:attributes.abbr,defaultValue:0,validate:x=>1===x}),this.month=new XFAObjectArray(12)}}class NumberPattern extends StringObject{constructor(attributes){super(LOCALE_SET_NS_ID,"numberPattern"),this.name=getStringOption(attributes.name,["full","long","med","short"])}}class NumberPatterns extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"numberPatterns",!0),this.numberPattern=new XFAObjectArray(4)}}class NumberSymbol extends StringObject{constructor(attributes){super(LOCALE_SET_NS_ID,"numberSymbol"),this.name=getStringOption(attributes.name,["decimal","grouping","percent","minus","zero"])}}class NumberSymbols extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"numberSymbols",!0),this.numberSymbol=new XFAObjectArray(5)}}class TimePattern extends StringObject{constructor(attributes){super(LOCALE_SET_NS_ID,"timePattern"),this.name=getStringOption(attributes.name,["full","long","med","short"])}}class TimePatterns extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"timePatterns",!0),this.timePattern=new XFAObjectArray(4)}}class TypeFace extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"typeFace",!0),this.name=""|attributes.name}}class TypeFaces extends XFAObject{constructor(attributes){super(LOCALE_SET_NS_ID,"typeFaces",!0),this.typeFace=new XFAObjectArray}}class LocaleSetNamespace{static[$buildXFAObject](name,attributes){if(LocaleSetNamespace.hasOwnProperty(name))return LocaleSetNamespace[name](attributes)}static calendarSymbols(attrs){return new CalendarSymbols(attrs)}static currencySymbol(attrs){return new CurrencySymbol(attrs)}static currencySymbols(attrs){return new CurrencySymbols(attrs)}static datePattern(attrs){return new DatePattern(attrs)}static datePatterns(attrs){return new DatePatterns(attrs)}static dateTimeSymbols(attrs){return new DateTimeSymbols(attrs)}static day(attrs){return new Day(attrs)}static dayNames(attrs){return new DayNames(attrs)}static era(attrs){return new Era(attrs)}static eraNames(attrs){return new EraNames(attrs)}static locale(attrs){return new locale_set_Locale(attrs)}static localeSet(attrs){return new locale_set_LocaleSet(attrs)}static meridiem(attrs){return new Meridiem(attrs)}static meridiemNames(attrs){return new MeridiemNames(attrs)}static month(attrs){return new Month(attrs)}static monthNames(attrs){return new MonthNames(attrs)}static numberPattern(attrs){return new NumberPattern(attrs)}static numberPatterns(attrs){return new NumberPatterns(attrs)}static numberSymbol(attrs){return new NumberSymbol(attrs)}static numberSymbols(attrs){return new NumberSymbols(attrs)}static timePattern(attrs){return new TimePattern(attrs)}static timePatterns(attrs){return new TimePatterns(attrs)}static typeFace(attrs){return new TypeFace(attrs)}static typeFaces(attrs){return new TypeFaces(attrs)}}const SIGNATURE_NS_ID=NamespaceIds.signature.id;class signature_Signature extends XFAObject{constructor(attributes){super(SIGNATURE_NS_ID,"signature",!0)}}class SignatureNamespace{static[$buildXFAObject](name,attributes){if(SignatureNamespace.hasOwnProperty(name))return SignatureNamespace[name](attributes)}static signature(attributes){return new signature_Signature(attributes)}}const STYLESHEET_NS_ID=NamespaceIds.stylesheet.id;class Stylesheet extends XFAObject{constructor(attributes){super(STYLESHEET_NS_ID,"stylesheet",!0)}}class StylesheetNamespace{static[$buildXFAObject](name,attributes){if(StylesheetNamespace.hasOwnProperty(name))return StylesheetNamespace[name](attributes)}static stylesheet(attributes){return new Stylesheet(attributes)}}const XDP_NS_ID=NamespaceIds.xdp.id;class xdp_Xdp extends XFAObject{constructor(attributes){super(XDP_NS_ID,"xdp",!0),this.uuid=attributes.uuid||"",this.timeStamp=attributes.timeStamp||"",this.config=null,this.connectionSet=null,this.datasets=null,this.localeSet=null,this.stylesheet=new XFAObjectArray,this.template=null}[$onChildCheck](child){var ns=NamespaceIds[child[$nodeName]];return ns&&child[$namespaceId]===ns.id}}class XdpNamespace{static[$buildXFAObject](name,attributes){if(XdpNamespace.hasOwnProperty(name))return XdpNamespace[name](attributes)}static xdp(attributes){return new xdp_Xdp(attributes)}}const XHTML_NS_ID=NamespaceIds.xhtml.id,$richText=Symbol(),VALID_STYLES=new Set(["color","font","font-family","font-size","font-stretch","font-style","font-weight","margin","margin-bottom","margin-left","margin-right","margin-top","letter-spacing","line-height","orphans","page-break-after","page-break-before","page-break-inside","tab-interval","tab-stop","text-align","text-decoration","text-indent","vertical-align","widows","kerning-mode","xfa-font-horizontal-scale","xfa-font-vertical-scale","xfa-spacerun","xfa-tab-stops"]),StyleMapping=new Map([["page-break-after","breakAfter"],["page-break-before","breakBefore"],["page-break-inside","breakInside"],["kerning-mode",value=>"none"===value?"none":"normal"],["xfa-font-horizontal-scale",value=>`scaleX(${Math.max(0,Math.min(parseInt(value)/100)).toFixed(2)})`],["xfa-font-vertical-scale",value=>`scaleY(${Math.max(0,Math.min(parseInt(value)/100)).toFixed(2)})`],["xfa-spacerun",""],["xfa-tab-stops",""],["font-size",(value,original)=>measureToString(.99*(value=original.fontSize=getMeasurement(value)))],["letter-spacing",value=>measureToString(getMeasurement(value))],["line-height",value=>measureToString(getMeasurement(value))],["margin",value=>measureToString(getMeasurement(value))],["margin-bottom",value=>measureToString(getMeasurement(value))],["margin-left",value=>measureToString(getMeasurement(value))],["margin-right",value=>measureToString(getMeasurement(value))],["margin-top",value=>measureToString(getMeasurement(value))],["text-indent",value=>measureToString(getMeasurement(value))],["font-family",value=>value],["vertical-align",value=>measureToString(getMeasurement(value))]]),spacesRegExp=/\s+/g,crlfRegExp=/[\r\n]+/g,crlfForRichTextRegExp=/\r\n?/g;function mapStyle(styleStr,node,richText){var style=Object.create(null);if(styleStr){var key,value,original=Object.create(null);for([key,value]of styleStr.split(";").map(s=>s.split(":",2))){var mapping=StyleMapping.get(key);if(""!==mapping){let newValue=value;mapping&&(newValue="string"==typeof mapping?mapping:mapping(value,original)),key.endsWith("scale")?style.transform=style.transform?style[key]+" "+newValue:newValue:style[key.replaceAll(/-([a-zA-Z])/g,(_,x)=>x.toUpperCase())]=newValue}}style.fontFamily&&setFontFamily({typeface:style.fontFamily,weight:style.fontWeight||"normal",posture:style.fontStyle||"normal",size:original.fontSize||0},node,node[$globalData].fontFinder,style),richText&&style.verticalAlign&&"0px"!==style.verticalAlign&&style.fontSize&&(styleStr=getMeasurement(style.fontSize),style.fontSize=measureToString(.583*styleStr),style.verticalAlign=measureToString(Math.sign(getMeasurement(style.verticalAlign))*styleStr*.333)),richText&&style.fontSize&&(style.fontSize=`calc(${style.fontSize} * var(--scale-factor))`),fixTextIndent(style)}return style}function checkStyle(node){return node.style?node.style.trim().split(/\s*;\s*/).filter(s=>!!s).map(s=>s.split(/\s*:\s*/,2)).filter(([key,value])=>("font-family"===key&&node[$globalData].usedTypefaces.add(value),VALID_STYLES.has(key))).map(kv=>kv.join(":")).join(";"):""}const NoWhites=new Set(["body","html"]);class XhtmlObject extends XmlObject{constructor(attributes,name){super(XHTML_NS_ID,name),this[$richText]=!1,this.style=attributes.style||""}[$clean](builder){super[$clean](builder),this.style=checkStyle(this)}[$acceptWhitespace](){return!NoWhites.has(this[$nodeName])}[$onText](str,richText=!1){richText?this[$richText]=!0:(str=str.replaceAll(crlfRegExp,""),this.style.includes("xfa-spacerun:yes")||(str=str.replaceAll(spacesRegExp," "))),str&&(this[$content]+=str)}[$pushGlyphs](measure,mustPop=!0){var key,value,xfaFont=Object.create(null),margin={top:NaN,bottom:NaN,left:NaN,right:NaN};let lineHeight=null;for([key,value]of this.style.split(";").map(s=>s.split(":",2)))switch(key){case"font-family":xfaFont.typeface=stripQuotes(value);break;case"font-size":xfaFont.size=getMeasurement(value);break;case"font-weight":xfaFont.weight=value;break;case"font-style":xfaFont.posture=value;break;case"letter-spacing":xfaFont.letterSpacing=getMeasurement(value);break;case"margin":var values=value.split(/ \t/).map(x=>getMeasurement(x));switch(values.length){case 1:margin.top=margin.bottom=margin.left=margin.right=values[0];break;case 2:margin.top=margin.bottom=values[0],margin.left=margin.right=values[1];break;case 3:margin.top=values[0],margin.bottom=values[2],margin.left=margin.right=values[1];break;case 4:margin.top=values[0],margin.left=values[1],margin.bottom=values[2],margin.right=values[3]}break;case"margin-top":margin.top=getMeasurement(value);break;case"margin-bottom":margin.bottom=getMeasurement(value);break;case"margin-left":margin.left=getMeasurement(value);break;case"margin-right":margin.right=getMeasurement(value);break;case"line-height":lineHeight=getMeasurement(value)}if(measure.pushData(xfaFont,margin,lineHeight),this[$content])measure.addString(this[$content]);else for(const child of this[$getChildren]())"#text"===child[$nodeName]?measure.addString(child[$content]):child[$pushGlyphs](measure);mustPop&&measure.popFont()}[$toHTML](availableSpace){var children=[];if(this[$extra]={children:children},this[$childrenToHTML]({}),0===children.length&&!this[$content])return HTMLResult.EMPTY;let value;return value=this[$richText]?this[$content]?this[$content].replaceAll(crlfForRichTextRegExp,"\n"):void 0:this[$content]||void 0,HTMLResult.success({name:this[$nodeName],attributes:{href:this.href,style:mapStyle(this.style,this,this[$richText])},children:children,value:value})}}class A extends XhtmlObject{constructor(attributes){super(attributes,"a"),this.href=fixURL(attributes.href)||""}}class B extends XhtmlObject{constructor(attributes){super(attributes,"b")}[$pushGlyphs](measure){measure.pushFont({weight:"bold"}),super[$pushGlyphs](measure),measure.popFont()}}class Body extends XhtmlObject{constructor(attributes){super(attributes,"body")}[$toHTML](availableSpace){var availableSpace=super[$toHTML](availableSpace),html=availableSpace["html"];return html?(html.name="div",html.attributes.class=["xfaRich"],availableSpace):HTMLResult.EMPTY}}class Br extends XhtmlObject{constructor(attributes){super(attributes,"br")}[$text](){return"\n"}[$pushGlyphs](measure){measure.addString("\n")}[$toHTML](availableSpace){return HTMLResult.success({name:"br"})}}class Html extends XhtmlObject{constructor(attributes){super(attributes,"html")}[$toHTML](availableSpace){var children=[];if(this[$extra]={children:children},this[$childrenToHTML]({}),0===children.length)return HTMLResult.success({name:"div",attributes:{class:["xfaRich"],style:{}},value:this[$content]||""});if(1===children.length){var child=children[0];if(child.attributes?.class.includes("xfaRich"))return HTMLResult.success(child)}return HTMLResult.success({name:"div",attributes:{class:["xfaRich"],style:{}},children:children})}}class I extends XhtmlObject{constructor(attributes){super(attributes,"i")}[$pushGlyphs](measure){measure.pushFont({posture:"italic"}),super[$pushGlyphs](measure),measure.popFont()}}class Li extends XhtmlObject{constructor(attributes){super(attributes,"li")}}class Ol extends XhtmlObject{constructor(attributes){super(attributes,"ol")}}class P extends XhtmlObject{constructor(attributes){super(attributes,"p")}[$pushGlyphs](measure){super[$pushGlyphs](measure,!1),measure.addString("\n"),measure.addPara(),measure.popFont()}[$text](){return this[$getParent]()[$getChildren]().at(-1)===this?super[$text]():super[$text]()+"\n"}}class Span extends XhtmlObject{constructor(attributes){super(attributes,"span")}}class Sub extends XhtmlObject{constructor(attributes){super(attributes,"sub")}}class Sup extends XhtmlObject{constructor(attributes){super(attributes,"sup")}}class Ul extends XhtmlObject{constructor(attributes){super(attributes,"ul")}}class XhtmlNamespace{static[$buildXFAObject](name,attributes){if(XhtmlNamespace.hasOwnProperty(name))return XhtmlNamespace[name](attributes)}static a(attributes){return new A(attributes)}static b(attributes){return new B(attributes)}static body(attributes){return new Body(attributes)}static br(attributes){return new Br(attributes)}static html(attributes){return new Html(attributes)}static i(attributes){return new I(attributes)}static li(attributes){return new Li(attributes)}static ol(attributes){return new Ol(attributes)}static p(attributes){return new P(attributes)}static span(attributes){return new Span(attributes)}static sub(attributes){return new Sub(attributes)}static sup(attributes){return new Sup(attributes)}static ul(attributes){return new Ul(attributes)}}const NamespaceSetUp={config:ConfigNamespace,connection:ConnectionSetNamespace,datasets:DatasetsNamespace,localeSet:LocaleSetNamespace,signature:SignatureNamespace,stylesheet:StylesheetNamespace,template:TemplateNamespace,xdp:XdpNamespace,xhtml:XhtmlNamespace};class UnknownNamespace{constructor(nsId){this.namespaceId=nsId}[$buildXFAObject](name,attributes){return new XmlObject(this.namespaceId,name,attributes)}}class Root extends XFAObject{constructor(ids){super(-1,"root",Object.create(null)),this.element=null,this[$ids]=ids}[$onChild](child){return this.element=child,!0}[$finalize](){super[$finalize](),this.element.template instanceof Template&&(this[$ids].set($root,this.element),this.element.template[$resolvePrototypes](this[$ids]),this.element.template[$ids]=this[$ids])}}class Empty extends XFAObject{constructor(){super(-1,"",Object.create(null))}[$onChild](_){return!1}}class Builder{constructor(rootNameSpace=null){this._namespaceStack=[],this._nsAgnosticLevel=0,this._namespacePrefixes=new Map,this._namespaces=new Map,this._nextNsId=Math.max(...Object.values(NamespaceIds).map(({id})=>id)),this._currentNamespace=rootNameSpace||new UnknownNamespace(++this._nextNsId)}buildRoot(ids){return new Root(ids)}build({nsPrefix,name,attributes,namespace,prefixes}){var hasNamespaceDef=null!==namespace;if(hasNamespaceDef&&(this._namespaceStack.push(this._currentNamespace),this._currentNamespace=this._searchNamespace(namespace)),prefixes&&this._addNamespacePrefix(prefixes),attributes.hasOwnProperty($nsAttributes)){var ns,attrs,dataTemplate=NamespaceSetUp.datasets,namespace=attributes[$nsAttributes];let xfaAttrs=null;for([ns,attrs]of Object.entries(namespace))if(this._getNamespaceToUse(ns)===dataTemplate){xfaAttrs={xfa:attrs};break}xfaAttrs?attributes[$nsAttributes]=xfaAttrs:delete attributes[$nsAttributes]}namespace=this._getNamespaceToUse(nsPrefix)?.[$buildXFAObject](name,attributes)||new Empty;return namespace[$isNsAgnostic]()&&this._nsAgnosticLevel++,(hasNamespaceDef||prefixes||namespace[$isNsAgnostic]())&&(namespace[$cleanup]={hasNamespace:hasNamespaceDef,prefixes:prefixes,nsAgnostic:namespace[$isNsAgnostic]()}),namespace}isNsAgnostic(){return 0{this._namespacePrefixes.get(prefix).pop()}),nsAgnostic&&this._nsAgnosticLevel--}}class XFAParser extends XMLParserBase{constructor(rootNameSpace=null,richText=!1){super(),this._builder=new Builder(rootNameSpace),this._stack=[],this._globalData={usedTypefaces:new Set},this._ids=new Map,this._current=this._builder.buildRoot(this._ids),this._errorCode=XMLParserErrorCode.NoError,this._whiteRegex=/^\s+$/,this._nbsps=/\xa0+/g,this._richText=richText}parse(data){if(this.parseXml(data),this._errorCode===XMLParserErrorCode.NoError)return this._current[$finalize](),this._current.element}onText(text){text=text.replace(this._nbsps,match=>match.slice(1)+" "),this._richText||this._current[$acceptWhitespace]()?this._current[$onText](text,this._richText):this._whiteRegex.test(text)||this._current[$onText](text.trim())}onCdata(text){this._current[$onText](text)}_mkAttributes(attributes,tagName){let namespace=null,prefixes=null;var name,value,attributeObj=Object.create({});for({name,value}of attributes)if("xmlns"===name)namespace?warn(`XFA - multiple namespace definition in <${tagName}>`):namespace=value;else if(name.startsWith("xmlns:")){var prefix=name.substring("xmlns:".length);(prefixes=prefixes||[]).push({prefix:prefix,value:value})}else{prefix=name.indexOf(":");if(-1===prefix)attributeObj[name]=value;else{let nsAttrs=attributeObj[$nsAttributes];nsAttrs=nsAttrs||(attributeObj[$nsAttributes]=Object.create(null));var[ns,attrName]=[name.slice(0,prefix),name.slice(prefix+1)];(nsAttrs[ns]||=Object.create(null))[attrName]=value}}return[namespace,prefixes,attributeObj]}_getNameAndPrefix(name,nsAgnostic){var i=name.indexOf(":");return-1===i?[name,null]:[name.substring(i+1),nsAgnostic?"":name.substring(0,i)]}onBeginElement(tagName,attributes,isEmpty){var[attributes,prefixes,attributesObj]=this._mkAttributes(attributes,tagName),[tagName,nsPrefix]=this._getNameAndPrefix(tagName,this._builder.isNsAgnostic()),nsPrefix=this._builder.build({nsPrefix:nsPrefix,name:tagName,attributes:attributesObj,namespace:attributes,prefixes:prefixes});nsPrefix[$globalData]=this._globalData,isEmpty?(nsPrefix[$finalize](),this._current[$onChild](nsPrefix)&&nsPrefix[$setId](this._ids),nsPrefix[$clean](this._builder)):(this._stack.push(this._current),this._current=nsPrefix)}onEndElement(name){var parser,node=this._current;node[$isCDATAXml]()&&"string"==typeof node[$content]&&((parser=new XFAParser)._globalData=this._globalData,parser=parser.parse(node[$content]),node[$content]=null,node[$onChild](parser)),node[$finalize](),this._current=this._stack.pop(),this._current[$onChild](node)&&node[$setId](this._ids),node[$clean](this._builder)}onError(code){this._errorCode=code}}class XFAFactory{constructor(data){try{this.root=(new XFAParser).parse(XFAFactory._createDocument(data));var binder=new Binder(this.root);this.form=binder.bind(),this.dataHandler=new DataHandler(this.root,binder.getData()),this.form[$globalData].template=this.form}catch(e){warn("XFA - an error occurred during parsing and binding: "+e)}}isValid(){return this.root&&this.form}_createPagesHelper(){const iterator=this.form[$toPages]();return new Promise((resolve,reject)=>{const nextIteration=()=>{try{var value=iterator.next();value.done?resolve(value.value):setTimeout(nextIteration,0)}catch(e){reject(e)}};setTimeout(nextIteration,0)})}async _createPages(){try{this.pages=await this._createPagesHelper(),this.dims=this.pages.children.map(c=>{var{width:c,height}=c.attributes.style;return[0,0,parseInt(c),parseInt(height)]})}catch(e){warn("XFA - an error occurred during layout: "+e)}}getBoundingBox(pageIndex){return this.dims[pageIndex]}async getNumPages(){return this.pages||await this._createPages(),this.dims.length}setImages(images){this.form[$globalData].images=images}setFonts(fonts){this.form[$globalData].fontFinder=new FontFinder(fonts);var typeface,missingFonts=[];for(typeface of this.form[$globalData].usedTypefaces)typeface=stripQuotes(typeface),this.form[$globalData].fontFinder.find(typeface)||missingFonts.push(typeface);return 0!attr.startsWith("xfa"))),attributes.dir="auto"),{html:html,str:root[$text]()}):null}catch(e){warn("XFA - an error occurred during parsing of rich text: "+e)}return null}}class AnnotationFactory{static createGlobals(pdfManager){return Promise.all([pdfManager.ensureCatalog("acroForm"),pdfManager.ensureDoc("xfaDatasets"),pdfManager.ensureCatalog("structTreeRoot"),pdfManager.ensureCatalog("baseUrl"),pdfManager.ensureCatalog("attachments")]).then(([acroForm,xfaDatasets,structTreeRoot,baseUrl,attachments])=>({pdfManager:pdfManager,acroForm:acroForm instanceof Dict?acroForm:Dict.empty,xfaDatasets:xfaDatasets,structTreeRoot:structTreeRoot,baseUrl:baseUrl,attachments:attachments}),reason=>(warn(`createGlobals: "${reason}".`),null))}static async create(xref,ref,annotationGlobals,idFactory,collectFields,pageRef){var pageIndex=collectFields?await this._getPageIndex(xref,ref,annotationGlobals.pdfManager):null;return annotationGlobals.pdfManager.ensure(this,"_create",[xref,ref,annotationGlobals,idFactory,collectFields,pageIndex,pageRef])}static _create(xref,ref,annotationGlobals,idFactory,collectFields=!1,pageIndex=null,pageRef=null){var dict=xref.fetchIfRef(ref);if(dict instanceof Dict){var{acroForm,pdfManager}=annotationGlobals,idFactory=ref instanceof Ref?ref.toString():"annot_"+idFactory.createObjId(),subtype=dict.get("Subtype"),parameters={xref:xref,ref:ref,dict:dict,subtype:subtype=subtype instanceof Name?subtype.name:null,id:idFactory,annotationGlobals:annotationGlobals,collectFields:collectFields,needAppearances:!collectFields&&!0===acroForm.get("NeedAppearances"),pageIndex:pageIndex,evaluatorOptions:pdfManager.evaluatorOptions,pageRef:pageRef};switch(subtype){case"Link":return new LinkAnnotation(parameters);case"Text":return new TextAnnotation(parameters);case"Widget":var fieldType=getInheritableProperty({dict:dict,key:"FT"});switch(fieldType=fieldType instanceof Name?fieldType.name:null){case"Tx":return new TextWidgetAnnotation(parameters);case"Btn":return new ButtonWidgetAnnotation(parameters);case"Ch":return new ChoiceWidgetAnnotation(parameters);case"Sig":return new SignatureWidgetAnnotation(parameters)}return warn(`Unimplemented widget field type "${fieldType}", `+"falling back to base field type."),new WidgetAnnotation(parameters);case"Popup":return new PopupAnnotation(parameters);case"FreeText":return new FreeTextAnnotation(parameters);case"Line":return new LineAnnotation(parameters);case"Square":return new SquareAnnotation(parameters);case"Circle":return new CircleAnnotation(parameters);case"PolyLine":return new PolylineAnnotation(parameters);case"Polygon":return new PolygonAnnotation(parameters);case"Caret":return new CaretAnnotation(parameters);case"Ink":return new InkAnnotation(parameters);case"Highlight":return new HighlightAnnotation(parameters);case"Underline":return new UnderlineAnnotation(parameters);case"Squiggly":return new SquigglyAnnotation(parameters);case"StrikeOut":return new StrikeOutAnnotation(parameters);case"Stamp":return new StampAnnotation(parameters);case"FileAttachment":return new FileAttachmentAnnotation(parameters);default:return collectFields||warn(subtype?`Unimplemented annotation type "${subtype}", `+"falling back to base annotation.":"Annotation is missing the required /Subtype."),new Annotation(parameters)}}}static async _getPageIndex(xref,ref,pdfManager){try{var annotDict=await xref.fetchIfRefAsync(ref);if(!(annotDict instanceof Dict))return-1;var pageRef=annotDict.getRaw("P");if(pageRef instanceof Ref)try{return await pdfManager.ensureCatalog("getPageIndex",[pageRef])}catch(ex){info(`_getPageIndex -- not a valid page reference: "${ex}".`)}if(annotDict.has("Kids"))return-1;var numPages=await pdfManager.ensureDoc("numPages");for(let pageIndex=0;pageIndexc/255)}function getQuadPoints(dict,rect){var quadPoints=dict.getArray("QuadPoints");if(!Array.isArray(quadPoints)||0===quadPoints.length||0rect[2]||minYrect[3]))return null;quadPointsLists.push([{x:minX,y:maxY},{x:maxX,y:maxY},{x:minX,y:minY},{x:maxX,y:minY}])}return quadPointsLists}function getTransformMatrix(rect,bbox,matrix){var[bbox,matrix,maxX,maxY]=Util.getAxialAlignedBoundingBox(bbox,matrix);return bbox===maxX||matrix===maxY?[1,0,0,1,rect[0],rect[1]]:[maxX=(rect[2]-rect[0])/(maxX-bbox),0,0,maxY=(rect[3]-rect[1])/(maxY-matrix),rect[0]-bbox*maxX,rect[1]-matrix*maxY]}class Annotation{constructor(params){var structParent,{dict,xref,annotationGlobals}=params,MK=(this.setTitle(dict.get("T")),this.setContents(dict.get("Contents")),this.setModificationDate(dict.get("M")),this.setFlags(dict.get("F")),this.setRectangle(dict.getArray("Rect")),this.setColor(dict.getArray("C")),this.setBorderStyle(dict),this.setAppearance(dict),this.setOptionalContent(dict),dict.get("MK")),MK=(this.setBorderAndBackgroundColors(MK),this.setRotation(MK,dict),this.ref=params.ref instanceof Ref?params.ref:null,this._streams=[],this.appearance&&this._streams.push(this.appearance),!!(this.flags&AnnotationFlag.LOCKED)),isContentLocked=!!(this.flags&AnnotationFlag.LOCKEDCONTENTS);if(annotationGlobals.structTreeRoot&&(structParent=dict.get("StructParent"),structParent=Number.isInteger(structParent)&&0<=structParent?structParent:-1,annotationGlobals.structTreeRoot.addAnnotationIdToPage(params.pageRef,structParent)),this.data={annotationFlags:this.flags,borderStyle:this.borderStyle,color:this.color,backgroundColor:this.backgroundColor,borderColor:this.borderColor,rotation:this.rotation,contentsObj:this._contents,hasAppearance:!!this.appearance,id:params.id,modificationDate:this.modificationDate,rect:this.rectangle,subtype:params.subtype,hasOwnCanvas:!1,noRotate:!!(this.flags&AnnotationFlag.NOROTATE),noHTML:MK&&isContentLocked},params.collectFields){annotationGlobals=dict.get("Kids");if(Array.isArray(annotationGlobals)){var kidIds=[];for(const kid of annotationGlobals)kid instanceof Ref&&kidIds.push(kid.toString());0!==kidIds.length&&(this.data.kidIds=kidIds)}this.data.actions=collectActions(xref,dict,AnnotationActionEventType),this.data.fieldName=this._constructFieldName(dict),this.data.pageIndex=params.pageIndex}this._isOffscreenCanvasSupported=params.evaluatorOptions.isOffscreenCanvasSupported,this._fallbackFontDict=null,this._needAppearances=!1}_hasFlag(flags,flag){return!!(flags&flag)}_isViewable(flags){return!this._hasFlag(flags,AnnotationFlag.INVISIBLE)&&!this._hasFlag(flags,AnnotationFlag.NOVIEW)}_isPrintable(flags){return this._hasFlag(flags,AnnotationFlag.PRINT)&&!this._hasFlag(flags,AnnotationFlag.HIDDEN)&&!this._hasFlag(flags,AnnotationFlag.INVISIBLE)}mustBeViewed(annotationStorage,_renderForms){annotationStorage=annotationStorage?.get(this.data.id)?.noView;return void 0!==annotationStorage?!annotationStorage:this.viewable&&!this._hasFlag(this.flags,AnnotationFlag.HIDDEN)}mustBePrinted(annotationStorage){annotationStorage=annotationStorage?.get(this.data.id)?.noPrint;return void 0!==annotationStorage?!annotationStorage:this.printable}get viewable(){return null!==this.data.quadPoints&&(0===this.flags||this._isViewable(this.flags))}get printable(){return null!==this.data.quadPoints&&0!==this.flags&&this._isPrintable(this.flags)}_parseStringHelper(data){data="string"==typeof data?stringToPDFString(data):"";return{str:data,dir:data&&"rtl"===bidi(data).dir?"rtl":"ltr"}}setDefaultAppearance(params){var{dict:params,annotationGlobals}=params,params=getInheritableProperty({dict:params,key:"DA"})||annotationGlobals.acroForm.get("DA");this._defaultAppearance="string"==typeof params?params:"",this.data.defaultAppearanceData=parseDefaultAppearance(this._defaultAppearance)}setTitle(title){this._title=this._parseStringHelper(title)}setContents(contents){this._contents=this._parseStringHelper(contents)}setModificationDate(modificationDate){this.modificationDate="string"==typeof modificationDate?modificationDate:null}setFlags(flags){this.flags=Number.isInteger(flags)&&0{if(resources)return new ObjectLoader(resources,keys,resources.xref).load().then(function(){return resources})})}async getOperatorList(evaluator,task,intent,renderForms,annotationStorage){var{hasOwnCanvas,id,rect}=this.data;let appearance=this.appearance;hasOwnCanvas=!!(hasOwnCanvas&&intent&RenderingIntentFlag.DISPLAY);if(hasOwnCanvas&&(rect[0]===rect[2]||rect[1]===rect[3]))return this.data.hasOwnCanvas=!1,{opList:new OperatorList,separateForm:!1,separateCanvas:!1};if(!appearance){if(!hasOwnCanvas)return{opList:new OperatorList,separateForm:!1,separateCanvas:!1};(appearance=new StringStream("")).dict=new Dict}var intent=appearance.dict,resources=await this.loadResources(["ExtGState","ColorSpace","Pattern","Shading","XObject","Font"],appearance),bbox=intent.getArray("BBox")||[0,0,1,1],intent=intent.getArray("Matrix")||[1,0,0,1,0,0],bbox=getTransformMatrix(rect,bbox,intent),opList=new OperatorList;let optionalContent;return void 0!==(optionalContent=this.oc?await evaluator.parseMarkedContentProps(this.oc,null):optionalContent)&&opList.addOp(OPS.beginMarkedContentProps,["OC",optionalContent]),opList.addOp(OPS.beginAnnotation,[id,rect,bbox,intent,hasOwnCanvas]),await evaluator.getOperatorList({stream:appearance,task:task,resources:resources,operatorList:opList,fallbackFontDict:this._fallbackFontDict}),opList.addOp(OPS.endAnnotation,[]),void 0!==optionalContent&&opList.addOp(OPS.endMarkedContent,[]),this.reset(),{opList:opList,separateForm:!1,separateCanvas:hasOwnCanvas}}async save(evaluator,task,annotationStorage){return null}get hasTextContent(){return!1}async extractTextContent(evaluator,task,viewBox){if(this.appearance){var resources=await this.loadResources(["ExtGState","Font","Properties","XObject"],this.appearance);const text=[],buffer=[];let firstPosition=null;var sink={desiredSize:Math.Infinity,ready:!0,enqueue(chunk,size){for(const item of chunk.items)void 0!==item.str&&(firstPosition||=item.transform.slice(-2),buffer.push(item.str),item.hasEOL)&&(text.push(buffer.join("").trimEnd()),buffer.length=0)}};await evaluator.getTextContent({stream:this.appearance,task:task,resources:resources,includeMarkedContent:!0,keepWhiteSpace:!0,sink:sink,viewBox:viewBox}),this.reset(),buffer.length&&text.push(buffer.join("").trimEnd()),(1"string"==typeof item).map(item=>stringToPDFString(item)):formValue instanceof Name?stringToPDFString(formValue.name):"string"==typeof formValue?stringToPDFString(formValue):null}hasFieldFlag(flag){return!!(this.data.fieldFlags&flag)}_isViewable(flags){return!0}mustBeViewed(annotationStorage,renderForms){return renderForms?this.viewable:super.mustBeViewed(annotationStorage,renderForms)&&!this._hasFlag(this.flags,AnnotationFlag.NOVIEW)}getRotationMatrix(annotationStorage){let rotation=annotationStorage?.get(this.data.id)?.rotation;var height;return 0===(rotation=void 0===rotation?this.rotation:rotation)?IDENTITY_MATRIX:(annotationStorage=this.data.rect[2]-this.data.rect[0],height=this.data.rect[3]-this.data.rect[1],getRotationMatrix(rotation,annotationStorage,height))}getBorderAndBackgroundAppearances(annotationStorage){let rotation=annotationStorage?.get(this.data.id)?.rotation;if(void 0===rotation&&(rotation=this.rotation),!this.backgroundColor&&!this.borderColor)return"";var annotationStorage=this.data.rect[2]-this.data.rect[0],height=this.data.rect[3]-this.data.rect[1],height=0===rotation||180===rotation?`0 0 ${annotationStorage} ${height} re`:`0 0 ${height} ${annotationStorage} re`;let str="";return this.backgroundColor&&(str=getPdfColor(this.backgroundColor,!0)+` ${height} f `),this.borderColor&&(annotationStorage=this.borderStyle.width||1,str+=`${annotationStorage} w ${getPdfColor(this.borderColor,!1)} ${height} S `),str}async getOperatorList(evaluator,task,intent,renderForms,annotationStorage){if(renderForms&&!(this instanceof SignatureWidgetAnnotation)&&!this.data.noHTML&&!this.data.hasOwnCanvas)return{opList:new OperatorList,separateForm:!0,separateCanvas:!1};if(!this._hasText)return super.getOperatorList(evaluator,task,intent,renderForms,annotationStorage);var content=await this._getAppearance(evaluator,task,intent,annotationStorage);if(this.appearance&&null===content)return super.getOperatorList(evaluator,task,intent,renderForms,annotationStorage);renderForms=new OperatorList;if(!this._defaultAppearance||null===content)return{opList:renderForms,separateForm:!1,separateCanvas:!1};var intent=!!(this.data.hasOwnCanvas&&intent&RenderingIntentFlag.DISPLAY),bbox=[0,0,this.data.rect[2]-this.data.rect[0],this.data.rect[3]-this.data.rect[1]],bbox=getTransformMatrix(this.data.rect,bbox,[1,0,0,1,0,0]);let optionalContent;void 0!==(optionalContent=this.oc?await evaluator.parseMarkedContentProps(this.oc,null):optionalContent)&&renderForms.addOp(OPS.beginMarkedContentProps,["OC",optionalContent]),renderForms.addOp(OPS.beginAnnotation,[this.data.id,this.data.rect,bbox,this.getRotationMatrix(annotationStorage),intent]);bbox=new StringStream(content);return await evaluator.getOperatorList({stream:bbox,task:task,resources:this._fieldResources.mergedResources,operatorList:renderForms}),renderForms.addOp(OPS.endAnnotation,[]),void 0!==optionalContent&&renderForms.addOp(OPS.endMarkedContent,[]),{opList:renderForms,separateForm:!1,separateCanvas:intent}}_getMKDict(rotation){var mk=new Dict(null);return rotation&&mk.set("R",rotation),this.borderColor&&mk.set("BC",getPdfColorArray(this.borderColor)),this.backgroundColor&&mk.set("BG",getPdfColorArray(this.backgroundColor)),0x===this.data.fieldValue[i]))return null;void 0===rotation&&(rotation=this.rotation);let appearance=null;if(!this._needAppearances&&null===(appearance=await this._getAppearance(evaluator,task,RenderingIntentFlag.SAVE,annotationStorage)))return null;let needAppearances=!1;appearance?.needAppearances&&(needAppearances=!0,appearance=null);var storageEntry=evaluator["xref"],originalDict=storageEntry.fetchIfRef(this.ref);if(!(originalDict instanceof Dict))return null;var dict=new Dict(storageEntry);for(const key of originalDict.getKeys())"AP"!==key&&dict.set(key,originalDict.getRaw(key));var newRef,appearanceStream,appearanceDict,AP,task={path:this.data.fieldName,value:value},evaluator=val=>isAscii(val)?val:stringToUTF16String(val,!0),evaluator=(dict.set("V",Array.isArray(value)?value.map(evaluator):evaluator(value)),this.amendSavedDict(annotationStorage,dict),this._getMKDict(rotation)),evaluator=(evaluator&&dict.set("MK",evaluator),[]),task=[{ref:this.ref,data:"",xfa:task,needAppearances:needAppearances}];return null!==appearance&&(newRef=storageEntry.getNewTemporaryRef(),AP=new Dict(storageEntry),dict.set("AP",AP),AP.set("N",newRef),AP=this._getSaveFieldResources(storageEntry),(appearanceDict=(appearanceStream=new StringStream(appearance)).dict=new Dict(storageEntry)).set("Subtype",Name.get("Form")),appearanceDict.set("Resources",AP),appearanceDict.set("BBox",[0,0,this.data.rect[2]-this.data.rect[0],this.data.rect[3]-this.data.rect[1]]),(AP=this.getRotationMatrix(annotationStorage))!==IDENTITY_MATRIX&&appearanceDict.set("Matrix",AP),await writeObject(newRef,appearanceStream,evaluator,storageEntry),task.push({ref:newRef,data:evaluator.join(""),xfa:null,needAppearances:!1}),evaluator.length=0),dict.set("M","D:"+getModificationDate()),await writeObject(this.ref,dict,evaluator,storageEntry),task[0].data=evaluator.join(""),task}async _getAppearance(evaluator,task,intent,annotationStorage){if(this.hasFieldFlag(AnnotationFieldFlag.PASSWORD))return null;var storageEntry=annotationStorage?.get(this.data.id);let value,rotation;if(storageEntry&&(value=storageEntry.formattedValue||storageEntry.value,rotation=storageEntry.rotation),void 0===rotation&&void 0===value&&!this._needAppearances&&(!this._hasValueFromXFA||this.appearance))return null;storageEntry=this.getBorderAndBackgroundAppearances(annotationStorage);if(void 0===value&&!(value=this.data.fieldValue))return`/Tx BMC q ${storageEntry}Q EMC`;if(assert("string"==typeof(value=Array.isArray(value)&&1===value.length?value[0]:value),"Expected `value` to be a string."),value=value.trim(),this.data.combo&&(option=this.data.options.find(({exportValue})=>value===exportValue),value=option?.displayValue||value),""===value)return`/Tx BMC q ${storageEntry}Q EMC`;void 0===rotation&&(rotation=this.rotation);let lineCount=-1,lines;this.data.multiLine?(lines=value.split(/\r\n?|\n/).map(line=>line.normalize("NFC")),lineCount=lines.length):lines=[value.replace(/\r\n?|\n/,"").normalize("NFC")];let totalHeight=this.data.rect[3]-this.data.rect[1],totalWidth=this.data.rect[2]-this.data.rect[0],font=(90!==rotation&&270!==rotation||([totalWidth,totalHeight]=[totalHeight,totalWidth]),this._defaultAppearance||(this.data.defaultAppearanceData=parseDefaultAppearance(this._defaultAppearance="/Helvetica 0 Tf 0 g")),await WidgetAnnotation._getFontData(evaluator,task,this.data.defaultAppearanceData,this._fieldResources.mergedResources)),defaultAppearance,fontSize,lineHeight;var encodedLines=[];let encodingError=!1;for(const line of lines){var encodedString=font.encodeString(line);1width+glyph.width,0)/1e3}_computeFontSize(height,width,text,font,lineCount){let fontSize=this.data.defaultAppearanceData["fontSize"],lineHeight=(fontSize||12)*LINE_FACTOR,numberOfLines=Math.round(height/lineHeight);if(!fontSize){var roundWithTwoDigits=x=>Math.floor(100*x)/100;if(-1===lineCount){var textWidth=this._getTextWidth(text,font);fontSize=roundWithTwoDigits(Math.min(height/LINE_FACTOR,width{let totalHeight=0;for(const cache of cachedLines){var chunks=this._splitLine(null,font,fsize,width,cache);if((totalHeight+=chunks.length*fsize)>height)return!0}return!1};for(numberOfLines=Math.max(numberOfLines,lineCount);;){if(lineHeight=height/numberOfLines,!isTooBig(fontSize=roundWithTwoDigits(lineHeight/LINE_FACTOR)))break;numberOfLines++}}var{fontName:text,fontColor:textWidth}=this.data.defaultAppearanceData;this._defaultAppearance=createDefaultAppearance({fontSize:fontSize,fontName:text,fontColor:textWidth})}return[this._defaultAppearance,fontSize,height/numberOfLines]}_renderText(text,font,fontSize,totalWidth,alignment,prevInfo,hPadding,vPadding){let shift;if(1===alignment){var width=this._getTextWidth(text,font)*fontSize;shift=(totalWidth-width)/2}else if(2===alignment){const width=this._getTextWidth(text,font)*fontSize;shift=totalWidth-width-hPadding}else shift=hPadding;width=numberToString(shift-prevInfo.shift);return prevInfo.shift=shift,`${width} ${vPadding=numberToString(vPadding)} Td (${escapeString(text)}) Tj`}_getSaveFieldResources(xref){var{localResources,appearanceResources,acroFormResources}=this._fieldResources,fontName=this.data.defaultAppearanceData?.fontName;if(fontName){for(const resources of[localResources,appearanceResources])if(resources instanceof Dict){var localFont=resources.get("Font");if(localFont instanceof Dict&&localFont.has(fontName))return resources}if(acroFormResources instanceof Dict){var appearanceResources=acroFormResources.get("Font");if(appearanceResources instanceof Dict&&appearanceResources.has(fontName))return(acroFormResources=new Dict(xref)).set(fontName,appearanceResources.getRaw(fontName)),(appearanceResources=new Dict(xref)).set("Font",acroFormResources),Dict.merge({xref:xref,dictArray:[appearanceResources,localResources],mergeSubDicts:!0})}}return localResources||Dict.empty}getFieldObject(){return null}}class TextWidgetAnnotation extends WidgetAnnotation{constructor(params){super(params),this.data.hasOwnCanvas=this.data.readOnly&&!this.data.noHTML,this._hasText=!0;params=params.dict;"string"!=typeof this.data.fieldValue&&(this.data.fieldValue="");let alignment=getInheritableProperty({dict:params,key:"Q"}),maximumLength=((!Number.isInteger(alignment)||alignment<0||2width?(chunks.push(line.substring(startChunk,start)),startChunk=start,currentWidth=glyphWidth,lastSpacePosInStringStart=-1):(currentWidth+=glyphWidth,lastSpacePosInStringStart=start,lastSpacePosInStringEnd=end,i):currentWidth+glyphWidth>width?currentWidth=-1!==lastSpacePosInStringStart?(chunks.push(line.substring(startChunk,lastSpacePosInStringEnd)),startChunk=lastSpacePosInStringEnd,i=lastSpacePos+1,lastSpacePosInStringStart=-1,0):(chunks.push(line.substring(startChunk,start)),startChunk=start,glyphWidth):currentWidth+=glyphWidth}return startChunk"Off"!==v),exportValues.length=0,exportValues.push("Off",asValue)),exportValues.includes(this.data.fieldValue)||(this.data.fieldValue="Off"),this.data.exportValue=exportValues[1],asValue=customAppearance.get(this.data.exportValue),this.checkedAppearance=asValue instanceof BaseStream?asValue:null,exportValues=customAppearance.get("Off"),this.uncheckedAppearance=exportValues instanceof BaseStream?exportValues:null,this.checkedAppearance?this._streams.push(this.checkedAppearance):this._getDefaultCheckedAppearance(params,"check"),this.uncheckedAppearance&&this._streams.push(this.uncheckedAppearance),this._fallbackFontDict=this.fallbackFontDict,null===this.data.defaultFieldValue)&&(this.data.defaultFieldValue="Off")}_processRadioButton(params){this.data.buttonValue=null;var fieldParent=params.dict.get("Parent"),fieldParent=(fieldParent instanceof Dict&&(this.parent=params.dict.getRaw("Parent"),(fieldParent=fieldParent.get("V"))instanceof Name)&&(this.data.fieldValue=this._decodeFormValue(fieldParent)),params.dict.get("AP"));if(fieldParent instanceof Dict){fieldParent=fieldParent.get("N");if(fieldParent instanceof Dict){for(const key of fieldParent.getKeys())if("Off"!==key){this.data.buttonValue=this._decodeFormValue(key);break}var checkedAppearance=fieldParent.get(this.data.buttonValue),checkedAppearance=(this.checkedAppearance=checkedAppearance instanceof BaseStream?checkedAppearance:null,fieldParent.get("Off"));this.uncheckedAppearance=checkedAppearance instanceof BaseStream?checkedAppearance:null,this.checkedAppearance?this._streams.push(this.checkedAppearance):this._getDefaultCheckedAppearance(params,"disc"),this.uncheckedAppearance&&this._streams.push(this.uncheckedAppearance),this._fallbackFontDict=this.fallbackFontDict,null===this.data.defaultFieldValue&&(this.data.defaultFieldValue="Off")}}}_processPushButton(params){var{dict:params,annotationGlobals}=params;params.has("A")||params.has("AA")||this.data.alternativeText?(this.data.isTooltipOnly=!params.has("A")&&!params.has("AA"),Catalog.parseDestDictionary({destDict:params,resultObj:this.data,docBaseUrl:annotationGlobals.baseUrl,docAttachments:annotationGlobals.attachments})):warn("Push buttons without action dictionaries are not supported")}getFieldObject(){let type="button",exportValues;return this.data.checkBox?(type="checkbox",exportValues=this.data.exportValue):this.data.radioButton&&(type="radiobutton",exportValues=this.data.buttonValue),{id:this.data.id,value:this.data.fieldValue||"Off",defaultValue:this.data.defaultFieldValue,exportValues:exportValues,editable:!this.data.readOnly,name:this.data.fieldName,rect:this.data.rect,hidden:this.data.hidden,actions:this.data.actions,page:this.data.pageIndex,strokeColor:this.data.borderColor,fillColor:this.data.backgroundColor,rotation:this.rotation,type:type}}get fallbackFontDict(){var dict=new Dict;return dict.set("BaseFont",Name.get("ZapfDingbats")),dict.set("Type",Name.get("FallbackType")),dict.set("Subtype",Name.get("FallbackType")),dict.set("Encoding",Name.get("ZapfDingbatsEncoding")),shadow(this,"fallbackFontDict",dict)}}class ChoiceWidgetAnnotation extends WidgetAnnotation{constructor(params){super(params);var{dict:params,xref}=params,options=(this.indices=params.getArray("I"),this.hasIndices=Array.isArray(this.indices)&&0lineWidth&&(lineWidth=width,value=displayValue)}[defaultAppearance,fontSize]=this._computeFontSize(lineHeight,totalWidth-4,value,font,-1)}const lineHeight=fontSize*LINE_FACTOR;var vPadding=(lineHeight-fontSize)/2,annotationStorage=Math.floor(totalHeight/lineHeight);let firstIndex=0;0intent)&&(firstIndex=intent);var end=Math.min(firstIndex+annotationStorage+1,lineCount),buf=["/Tx BMC q",`1 1 ${totalWidth} ${totalHeight} re W n`];if(valueIndices.length){buf.push("0.600006 0.756866 0.854904 rg");for(const index of valueIndices)firstIndex<=index&&indexline.trimEnd()),{coords:evaluatorOptions,bbox,matrix}=FakeUnicodeFont.getFirstPositionInfo(this.rectangle,this.rotation,fontSize),this.data.textPosition=this._transformPoint(evaluatorOptions,bbox,matrix)),this._isOffscreenCanvasSupported?(evaluatorOptions=params.dict.get("CA"),bbox=new FakeUnicodeFont(xref,"sans-serif"),this.appearance=bbox.createAppearance(this._contents.str,this.rectangle,this.rotation,fontSize,fontColor,evaluatorOptions),this._streams.push(this.appearance)):warn("FreeTextAnnotation: OffscreenCanvas is not supported, annotation may not render correctly.")}}get hasTextContent(){return this._hasAppearance}static createNewDict(annotation,xref,{apRef,ap}){var{color:annotation,fontSize,rect,rotation,user,value}=annotation,freetext=new Dict(xref),rect=(freetext.set("Type",Name.get("Annot")),freetext.set("Subtype",Name.get("FreeText")),freetext.set("CreationDate","D:"+getModificationDate()),freetext.set("Rect",rect),`/Helv ${fontSize} Tf `+getPdfColor(annotation,!0));return freetext.set("DA",rect),freetext.set("Contents",isAscii(value)?value:stringToUTF16String(value,!0)),freetext.set("F",4),freetext.set("Border",[0,0,0]),freetext.set("Rotate",rotation),user&&freetext.set("T",isAscii(user)?user:stringToUTF16String(user,!0)),(apRef||ap)&&(fontSize=new Dict(xref),freetext.set("AP",fontSize),apRef?fontSize.set("N",apRef):fontSize.set("N",ap)),freetext}static async createNewAppearanceStream(annotation,xref,params){var{baseFontRef:params,evaluator,task}=params,{color:annotation,fontSize,rect,rotation,value}=annotation,resources=new Dict(xref),font=new Dict(xref),helv=(params?font.set("Helv",params):((params=new Dict(xref)).set("BaseFont",Name.get("Helvetica")),params.set("Type",Name.get("Font")),params.set("Subtype",Name.get("Type1")),params.set("Encoding",Name.get("WinAnsiEncoding")),font.set("Helv",params)),resources.set("Font",font),await WidgetAnnotation._getFontData(evaluator,task,{fontName:"Helv",fontSize:fontSize},resources)),[params,font,evaluator,task]=rect;let w=evaluator-params,h=task-font;rotation%180!=0&&([w,h]=[h,w]);var evaluator=value.split("\n"),scale=fontSize/1e3;let totalWidth=-1/0;var line,encodedLines=[];for(line of evaluator){var encoded=helv.encodeString(line);if(1w&&(hscale=w/totalWidth),1);var params=LINE_FACTOR*fontSize,lineAscent=(LINE_FACTOR-LINE_DESCENT_FACTOR)*fontSize,task=params*evaluator.length,font=(task>h&&(vscale=h/task),Math.min(hscale,vscale)),value=fontSize*font;let firstPoint,clipBox,matrix;switch(rotation){case 0:matrix=[1,0,0,1],clipBox=[rect[0],rect[1],w,h],firstPoint=[rect[0],rect[3]-lineAscent];break;case 90:matrix=[0,1,-1,0],clipBox=[rect[1],-rect[2],w,h],firstPoint=[rect[1],-rect[0]-lineAscent];break;case 180:matrix=[-1,0,0,-1],clipBox=[-rect[2],-rect[3],w,h],firstPoint=[-rect[2],-rect[1]-lineAscent];break;case 270:matrix=[0,-1,1,0],clipBox=[-rect[3],rect[0],w,h],firstPoint=[-rect[3],rect[2]-lineAscent]}var buffer=["q",matrix.join(" ")+" 0 0 cm",clipBox.join(" ")+" re W n","BT",""+getPdfColor(annotation,!0),`0 Tc /Helv ${numberToString(value)} Tf`],vShift=(buffer.push(`${firstPoint.join(" ")} Td (${escapeString(encodedLines[0])}) Tj`),numberToString(params));for(let i=1,ii=encodedLines.length;i(buffer.push(`${lineCoordinates[0]} ${lineCoordinates[1]} m`,`${lineCoordinates[2]} ${lineCoordinates[3]} l`,"S"),[points[0].x-borderWidth,points[1].x+borderWidth,points[3].y-borderWidth,points[1].y+borderWidth])})}}}class SquareAnnotation extends MarkupAnnotation{constructor(params){super(params);var{dict:params,xref}=params;if(this.data.annotationType=AnnotationType.SQUARE,this.data.hasOwnCanvas=this.data.noRotate,this.data.noHTML=!1,!this.appearance){var strokeColor=this.color?getPdfColorArray(this.color):[0,0,0],strokeAlpha=params.get("CA"),params=getRgbColor(params.getArray("IC"),null);const fillColor=params?getPdfColorArray(params):null;params=fillColor?strokeAlpha:null;0===this.borderStyle.width&&!fillColor||this._setDefaultAppearance({xref:xref,extra:this.borderStyle.width+" w",strokeColor:strokeColor,fillColor:fillColor,strokeAlpha:strokeAlpha,fillAlpha:params,pointsCallback:(buffer,points)=>{var x=points[2].x+this.borderStyle.width/2,y=points[2].y+this.borderStyle.width/2,width=points[3].x-points[2].x-this.borderStyle.width,height=points[1].y-points[3].y-this.borderStyle.width;return buffer.push(x+` ${y} ${width} ${height} re`),fillColor?buffer.push("B"):buffer.push("S"),[points[0].x,points[1].x,points[3].y,points[1].y]}})}}}class CircleAnnotation extends MarkupAnnotation{constructor(params){super(params);var{dict:params,xref}=params;if(this.data.annotationType=AnnotationType.CIRCLE,!this.appearance){var strokeColor=this.color?getPdfColorArray(this.color):[0,0,0],strokeAlpha=params.get("CA"),params=getRgbColor(params.getArray("IC"),null);const fillColor=params?getPdfColorArray(params):null;params=fillColor?strokeAlpha:null;if(0!==this.borderStyle.width||fillColor){const controlPointsDistance=4/3*Math.tan(Math.PI/8);this._setDefaultAppearance({xref:xref,extra:this.borderStyle.width+" w",strokeColor:strokeColor,fillColor:fillColor,strokeAlpha:strokeAlpha,fillAlpha:params,pointsCallback:(buffer,points)=>{var x0=points[0].x+this.borderStyle.width/2,y0=points[0].y-this.borderStyle.width/2,x1=points[3].x-this.borderStyle.width/2,y1=points[3].y+this.borderStyle.width/2,xMid=x0+(x1-x0)/2,yMid=y0+(y1-y0)/2,xOffset=(x1-x0)/2*controlPointsDistance,yOffset=(y1-y0)/2*controlPointsDistance;return buffer.push(xMid+` ${y1} m`,xMid+xOffset+` ${y1} ${x1} ${yMid+yOffset} ${x1} ${yMid} c`,x1+` ${yMid-yOffset} ${xMid+xOffset} ${y0} ${xMid} ${y0} c`,xMid-xOffset+` ${y0} ${x0} ${yMid-yOffset} ${x0} ${yMid} c`,x0+` ${yMid+yOffset} ${xMid-xOffset} ${y1} ${xMid} ${y1} c`,"h"),fillColor?buffer.push("B"):buffer.push("S"),[points[0].x,points[1].x,points[3].y,points[1].y]}})}}}}class PolylineAnnotation extends MarkupAnnotation{constructor(params){super(params);var{dict:params,xref}=params,rawVertices=(this.data.annotationType=AnnotationType.POLYLINE,this.data.hasOwnCanvas=this.data.noRotate,this.data.noHTML=!1,this.data.vertices=[],this instanceof PolygonAnnotation||(this.setLineEndings(params.getArray("LE")),this.data.lineEndings=this.lineEndings),params.getArray("Vertices"));if(Array.isArray(rawVertices)){for(let i=0,ii=rawVertices.length;i{var vertices=this.data.vertices;for(let i=0,ii=vertices.length;i{for(const inkList of this.data.inkLists){for(let i=0,ii=inkList.length;ip.points)),ink.set("F",4),ink.set("Rotate",rotation),outlines&&ink.set("IT",Name.get("InkHighlight")),new Dict(xref)),paths=(ink.set("BS",rect),rect.set("W",thickness),ink.set("C",Array.from(annotation,c=>c/255)),ink.set("CA",opacity),new Dict(xref));return ink.set("AP",paths),apRef?paths.set("N",apRef):paths.set("N",ap),ink}static async createNewAppearanceStream(annotation,xref,params){if(annotation.outlines)return this.createNewAppearanceStreamForHighlight(annotation,xref,params);var bezier,{color:params,rect:annotation,paths,thickness,opacity}=annotation,appearanceBuffer=[thickness+" w 1 J 1 j",""+getPdfColor(params,!1)],buffer=(1!==opacity&&appearanceBuffer.push("/R0 gs"),[]);for({bezier}of paths){if(buffer.length=0,buffer.push(`${numberToString(bezier[0])} ${numberToString(bezier[1])} m`),2===bezier.length)buffer.push(`${numberToString(bezier[0])} ${numberToString(bezier[1])} l S`);else{for(let i=2,ii=bezier.length;i(buffer.push(`${points[0].x} ${points[0].y} m`,`${points[1].x} ${points[1].y} l`,`${points[3].x} ${points[3].y} l`,`${points[2].x} ${points[2].y} l`,"f"),[points[0].x,points[1].x,points[3].y,points[1].y])}))):this.data.popupRef=null}static createNewDict(annotation,xref,{apRef,ap}){var{color:annotation,opacity,rect,rotation,user,quadPoints}=annotation,highlight=new Dict(xref);return highlight.set("Type",Name.get("Annot")),highlight.set("Subtype",Name.get("Highlight")),highlight.set("CreationDate","D:"+getModificationDate()),highlight.set("Rect",rect),highlight.set("F",4),highlight.set("Border",[0,0,0]),highlight.set("Rotate",rotation),highlight.set("QuadPoints",quadPoints),highlight.set("C",Array.from(annotation,c=>c/255)),highlight.set("CA",opacity),user&&highlight.set("T",isAscii(user)?user:stringToUTF16String(user,!0)),(apRef||ap)&&(rect=new Dict(xref),highlight.set("AP",rect),rect.set("N",apRef||ap)),highlight}static async createNewAppearanceStream(annotation,xref,params){var{color:annotation,rect,outlines,opacity}=annotation,appearanceBuffer=[""+getPdfColor(annotation,!0),"/R0 gs"],buffer=[];for(const outline of outlines){buffer.length=0,buffer.push(`${numberToString(outline[0])} ${numberToString(outline[1])} m`);for(let i=2,ii=outline.length;i(buffer.push(`${points[2].x} ${points[2].y+1.3} m`,`${points[3].x} ${points[3].y+1.3} l`,"S"),[points[0].x,points[1].x,points[3].y,points[1].y])})):this.data.popupRef=null}}class SquigglyAnnotation extends MarkupAnnotation{constructor(params){super(params);var{dict:params,xref}=params,quadPoints=(this.data.annotationType=AnnotationType.SQUIGGLY,this.data.quadPoints=getQuadPoints(params,null));quadPoints?this.appearance||(quadPoints=this.color?getPdfColorArray(this.color):[0,0,0],params=params.get("CA"),this._setDefaultAppearance({xref:xref,extra:"[] 0 d 1 w",strokeColor:quadPoints,strokeAlpha:params,pointsCallback:(buffer,points)=>{var dy=(points[0].y-points[2].y)/6;let shift=dy,x=points[2].x;var y=points[2].y,xEnd=points[3].x;for(buffer.push(`${x} ${y+shift} m`);x+=2,shift=0===shift?dy:0,buffer.push(`${x} ${y+shift} l`),x(buffer.push((points[0].x+points[2].x)/2+" "+(points[0].y+points[2].y)/2+" m",(points[1].x+points[3].x)/2+" "+(points[1].y+points[3].y)/2+" l","S"),[points[0].x,points[1].x,points[3].y,points[1].y])})):this.data.popupRef=null}}class StampAnnotation extends MarkupAnnotation{constructor(params){super(params),this.data.annotationType=AnnotationType.STAMP,this.data.hasOwnCanvas=this.data.noRotate,this.data.noHTML=!1}static async createImage(bitmap,xref){var{width,height}=bitmap,canvas=new OffscreenCanvas(width,height),ctx=canvas.getContext("2d",{alpha:!0}),data=(ctx.drawImage(bitmap,0,0),ctx.getImageData(0,0,width,height).data),buf32=new Uint32Array(data.buffer),data=buf32.some(FeatureTest.isLittleEndian?x=>x>>>24!=255:x=>255!=(255&x)),ctx=(data&&(ctx.fillStyle="white",ctx.fillRect(0,0,width,height),ctx.drawImage(bitmap,0,0)),canvas.convertToBlob({type:"image/jpeg",quality:1}).then(blob=>blob.arrayBuffer())),bitmap=Name.get("XObject"),canvas=Name.get("Image"),image=new Dict(xref);image.set("Type",bitmap),image.set("Subtype",canvas),image.set("BitsPerComponent",8),image.set("ColorSpace",Name.get("DeviceRGB")),image.set("Filter",Name.get("DCTDecode")),image.set("BBox",[0,0,width,height]),image.set("Width",width),image.set("Height",height);let smaskStream=null;if(data){var alphaBuffer=new Uint8Array(buf32.length);if(FeatureTest.isLittleEndian)for(let i=0,ii=buf32.length;i>>24;else for(let i=0,ii=buf32.length;idecodeString(child.textContent)):decodeString(path.textContent):""}}class XRef{#firstXRefStmPos=null;constructor(stream,pdfManager){this.stream=stream,this.pdfManager=pdfManager,this.entries=[],this._xrefStms=new Set,this._cacheMap=new Map,this._pendingRefs=new RefSet,this._newPersistentRefNum=null,this._newTemporaryRefNum=null,this._persistentRefsCache=null}getNewPersistentRef(obj){null===this._newPersistentRefNum&&(this._newPersistentRefNum=this.entries.length||1);var num=this._newPersistentRefNum++;return this._cacheMap.set(num,obj),Ref.get(num,0)}getNewTemporaryRef(){if(null===this._newTemporaryRefNum&&(this._newTemporaryRefNum=this.entries.length||1,this._newPersistentRefNum)){this._persistentRefsCache=new Map;for(let i=this._newTemporaryRefNum;i=length)break;offset++,skipped++}return skipped}var gEndobjRegExp=/\b(endobj|\d+\s+\d+\s+obj|xref|trailer\s*<<)\b/g,gStartxrefRegExp=/\b(startxref|\d+\s+\d+\s+obj)\b/g,objRegExp=/^(\d+)\s+(\d+)\s+obj\b/,trailerBytes=new Uint8Array([116,114,97,105,108,101,114]),startxrefBytes=new Uint8Array([115,116,97,114,116,120,114,101,102]),xrefBytes=new Uint8Array([47,88,82,101,102]),stream=(this.entries.length=0,this._cacheMap.clear(),this.stream),buffer=(stream.pos=0,stream.getBytes()),bufferStr=bytesToString(buffer),length=buffer.length;let position=stream.start;for(var trailers=[],xrefStms=[];position=length)&&(ch=buffer[position])!==LF&&ch!==CR;);else{var token=function(data,offset){let token="",ch=data[offset];for(;ch!==LF&&ch!==CR&&ch!==LT&&!(++offset>=data.length);)token+=String.fromCharCode(ch),ch=data[offset];return token}(buffer,position);if(token.startsWith("xref")&&(4===token.length||/\s/.test(token[4])))position+=skipUntil(buffer,position,trailerBytes),trailers.push(position),position+=skipUntil(buffer,position,startxrefBytes);else if(m=objRegExp.exec(token)){var num=0|m[1],m=0|m[2],startPos=position+token.length;let contentLength,updateEntries=!1;if(this.entries[num]){if(this.entries[num].gen===m)try{new Parser({lexer:new Lexer(stream.makeSubStream(startPos))}).getObj(),updateEntries=!0}catch(ex){ex instanceof ParserEOFException?warn(`indexObjects -- checking object (${token}): "${ex}".`):updateEntries=!0}}else updateEntries=!0;updateEntries&&(this.entries[num]={offset:position-stream.start,gen:m,uncompressed:!0}),gEndobjRegExp.lastIndex=startPos;num=gEndobjRegExp.exec(bufferStr),startPos=(num?(m=gEndobjRegExp.lastIndex+1,contentLength=m-position,"endobj"!==num[1]&&(warn(`indexObjects: Found "${num[1]}" inside of another "obj", `+'caused by missing "endobj" -- trying to recover.'),contentLength-=num[1].length+1)):contentLength=length-position,buffer.subarray(position,position+contentLength)),m=skipUntil(startPos,0,xrefBytes);mcontent instanceof BaseStream?content:Array.isArray(content)?new StreamsSequenceStream(content,this._onSubStreamError.bind(this)):new NullStream)}get xfaData(){return shadow(this,"xfaData",this.xfaFactory?{bbox:this.xfaFactory.getBoundingBox(this.pageIndex)}:null)}#replaceIdByRef(annotations,deletedAnnotations,existingAnnotations){for(const annotation of annotations){var ref;annotation.id&&((ref=Ref.fromString(annotation.id))?annotation.deleted?deletedAnnotations.put(ref,ref):(existingAnnotations?.put(ref),annotation.ref=ref,delete annotation.id):warn("A non-linked annotation cannot be modified: "+annotation.id))}}async saveNewAnnotations(handler,task,annotations,imagePromises){if(this.xfaFactory)throw new Error("XFA: Cannot save new annotations.");handler=new PartialEvaluator({xref:this.xref,handler:handler,pageIndex:this.pageIndex,idFactory:this._localIdFactory,fontCache:this.fontCache,builtInCMapCache:this.builtInCMapCache,standardFontDataCache:this.standardFontDataCache,globalImageCache:this.globalImageCache,systemFontCache:this.systemFontCache,options:this.evaluatorOptions});const deletedAnnotations=new RefSetCache;var ref,existingAnnotations=new RefSet,pageDict=(this.#replaceIdByRef(annotations,deletedAnnotations,existingAnnotations),this.pageDict),annotationsArray=this.annotations.filter(a=>!(a instanceof Ref&&deletedAnnotations.has(a))),handler=await AnnotationFactory.saveNewAnnotations(handler,task,annotations,imagePromises);for({ref}of handler.annotations)ref instanceof Ref&&!existingAnnotations.has(ref)&&annotationsArray.push(ref);var task=pageDict.get("Annots"),annotations=(pageDict.set("Annots",annotationsArray),[]),objects=(await writeObject(this.ref,pageDict,annotations,this.xref),task&&pageDict.set("Annots",task),handler.dependencies);objects.push({ref:this.ref,data:annotations.join("")},...handler.annotations);for(const deletedRef of deletedAnnotations)objects.push({ref:deletedRef,data:null});return objects}save(handler,task,annotationStorage){const partialEvaluator=new PartialEvaluator({xref:this.xref,handler:handler,pageIndex:this.pageIndex,idFactory:this._localIdFactory,fontCache:this.fontCache,builtInCMapCache:this.builtInCMapCache,standardFontDataCache:this.standardFontDataCache,globalImageCache:this.globalImageCache,systemFontCache:this.systemFontCache,options:this.evaluatorOptions});return this._parsedAnnotations.then(function(annotations){var newRefsPromises=[];for(const annotation of annotations)annotation.mustBePrinted(annotationStorage)&&newRefsPromises.push(annotation.save(partialEvaluator,task,annotationStorage).catch(function(reason){return warn("save - ignoring annotation data during "+`"${task.name}" task: "${reason}".`),null}));return Promise.all(newRefsPromises).then(function(newRefs){return newRefs.filter(newRef=>!!newRef)})})}loadResources(keys){return this.resourcesPromise||(this.resourcesPromise=this.pdfManager.ensure(this,"resources")),this.resourcesPromise.then(()=>{return new ObjectLoader(this.resources,keys,this.xref).load()})}getOperatorList({handler,sink,task,intent,cacheKey,annotationStorage=null}){var contentStreamPromise=this.getContentStream(),resourcesPromise=this.loadResources(["ColorSpace","ExtGState","Font","Pattern","Properties","Shading","XObject"]);const partialEvaluator=new PartialEvaluator({xref:this.xref,handler:handler,pageIndex:this.pageIndex,idFactory:this._localIdFactory,fontCache:this.fontCache,builtInCMapCache:this.builtInCMapCache,standardFontDataCache:this.standardFontDataCache,globalImageCache:this.globalImageCache,systemFontCache:this.systemFontCache,options:this.evaluatorOptions});var newAnnotationsByPage=this.xfaFactory?null:getNewAnnotationsMap(annotationStorage);let deletedAnnotations=null,newAnnotationsPromise=Promise.resolve(null);if(newAnnotationsByPage){const newAnnotations=newAnnotationsByPage.get(this.pageIndex);if(newAnnotations){newAnnotationsByPage=this.pdfManager.ensureDoc("annotationGlobals");let imagePromises;var bitmapId,bitmap,missingBitmaps=new Set;for({bitmapId,bitmap}of newAnnotations)!bitmapId||bitmap||missingBitmaps.has(bitmapId)||missingBitmaps.add(bitmapId);var isOffscreenCanvasSupported=this.evaluatorOptions["isOffscreenCanvasSupported"];if(0annotationGlobals?AnnotationFactory.printNewAnnotations(annotationGlobals,partialEvaluator,task,newAnnotations,imagePromises):null)}}isOffscreenCanvasSupported=Promise.all([contentStreamPromise,resourcesPromise]).then(([contentStream])=>{const opList=new OperatorList(intent,sink);return handler.send("StartRenderPage",{transparency:partialEvaluator.hasBlendModes(this.resources,this.nonBlendModesSet),pageIndex:this.pageIndex,cacheKey:cacheKey}),partialEvaluator.getOperatorList({stream:contentStream,task:task,resources:this.resources,operatorList:opList}).then(function(){return opList})});return Promise.all([isOffscreenCanvasSupported,this._parsedAnnotations,newAnnotationsPromise]).then(function([pageOpList,annotations,newAnnotations]){if(newAnnotations){annotations=annotations.filter(a=>!(a.ref&&deletedAnnotations.has(a.ref)));for(let i=0,ii=newAnnotations.length;ia.ref&&isRefsEqual(a.ref,newAnnotation.refToReplace)))&&(annotations.splice(j,1,newAnnotation),newAnnotations.splice(i--,1),ii--)}annotations=annotations.concat(newAnnotations)}if(0===annotations.length||intent&RenderingIntentFlag.ANNOTATIONS_DISABLE)return pageOpList.flush(!0),{length:pageOpList.totalLength};var renderForms=!!(intent&RenderingIntentFlag.ANNOTATIONS_FORMS),intentAny=!!(intent&RenderingIntentFlag.ANY),intentDisplay=!!(intent&RenderingIntentFlag.DISPLAY),intentPrint=!!(intent&RenderingIntentFlag.PRINT),opListPromises=[];for(const annotation of annotations)(intentAny||intentDisplay&&annotation.mustBeViewed(annotationStorage,renderForms)||intentPrint&&annotation.mustBePrinted(annotationStorage))&&opListPromises.push(annotation.getOperatorList(partialEvaluator,task,intent,renderForms,annotationStorage).catch(function(reason){return warn("getOperatorList - ignoring annotation data during "+`"${task.name}" task: "${reason}".`),{opList:null,separateForm:!1,separateCanvas:!1}}));return Promise.all(opListPromises).then(function(opLists){let form=!1,canvas=!1;for(var{opList,separateForm,separateCanvas}of opLists)pageOpList.addOpList(opList),form||=separateForm,canvas||=separateCanvas;return pageOpList.flush(!0,{form:form,canvas:canvas}),{length:pageOpList.totalLength}})})}extractTextContent({handler,task,includeMarkedContent,disableNormalization,sink}){var contentStreamPromise=this.getContentStream(),resourcesPromise=this.loadResources(["ExtGState","Font","Properties","XObject"]);return Promise.all([contentStreamPromise,resourcesPromise]).then(([contentStream])=>{return new PartialEvaluator({xref:this.xref,handler:handler,pageIndex:this.pageIndex,idFactory:this._localIdFactory,fontCache:this.fontCache,builtInCMapCache:this.builtInCMapCache,standardFontDataCache:this.standardFontDataCache,globalImageCache:this.globalImageCache,systemFontCache:this.systemFontCache,options:this.evaluatorOptions}).getTextContent({stream:contentStream,task:task,resources:this.resources,includeMarkedContent:includeMarkedContent,disableNormalization:disableNormalization,sink:sink,viewBox:this.view})})}async getStructTree(){var structTreeRoot=await this.pdfManager.ensureCatalog("structTreeRoot");return structTreeRoot?(await this._parsedAnnotations,(await this.pdfManager.ensure(this,"_parseStructTree",[structTreeRoot])).serializable):null}_parseStructTree(structTreeRoot){structTreeRoot=new StructTreePage(structTreeRoot,this.pageDict);return structTreeRoot.parse(this.ref),structTreeRoot}async getAnnotationsData(handler,task,intent){var annotations=await this._parsedAnnotations;if(0===annotations.length)return annotations;var annotationsData=[],textContentPromises=[];let partialEvaluator;var intentAny=!!(intent&RenderingIntentFlag.ANY),intentDisplay=!!(intent&RenderingIntentFlag.DISPLAY),intentPrint=!!(intent&RenderingIntentFlag.PRINT);for(const annotation of annotations){var isVisible=intentAny||intentDisplay&&annotation.viewable;(isVisible||intentPrint&&annotation.printable)&&annotationsData.push(annotation.data),annotation.hasTextContent&&isVisible&&(partialEvaluator||=new PartialEvaluator({xref:this.xref,handler:handler,pageIndex:this.pageIndex,idFactory:this._localIdFactory,fontCache:this.fontCache,builtInCMapCache:this.builtInCMapCache,standardFontDataCache:this.standardFontDataCache,globalImageCache:this.globalImageCache,systemFontCache:this.systemFontCache,options:this.evaluatorOptions}),textContentPromises.push(annotation.extractTextContent(partialEvaluator,task,[-1/0,-1/0,1/0,1/0]).catch(function(reason){warn(`getAnnotationsData - ignoring textContent during "${task.name}" task: "${reason}".`)})))}return await Promise.all(textContentPromises),annotationsData}get annotations(){var annots=this._getInheritableProperty("Annots");return shadow(this,"annotations",Array.isArray(annots)?annots:[])}get _parsedAnnotations(){var promise=this.pdfManager.ensure(this,"annotations").then(async annots=>{if(0===annots.length)return annots;var annotationGlobals=await this.pdfManager.ensureDoc("annotationGlobals");if(!annotationGlobals)return[];var annotationPromises=[];for(const annotationRef of annots)annotationPromises.push(AnnotationFactory.create(this.xref,annotationRef,annotationGlobals,this._localIdFactory,!1,this.ref).catch(function(reason){return warn(`_parsedAnnotations: "${reason}".`),null}));var sortedAnnotations=[];let popupAnnotations,widgetAnnotations;for(const annotation of await Promise.all(annotationPromises))annotation&&(annotation instanceof WidgetAnnotation?widgetAnnotations||=[]:annotation instanceof PopupAnnotation?popupAnnotations||=[]:sortedAnnotations).push(annotation);return widgetAnnotations&&sortedAnnotations.push(...widgetAnnotations),popupAnnotations&&sortedAnnotations.push(...popupAnnotations),sortedAnnotations});return shadow(this,"_parsedAnnotations",promise)}get jsActions(){return shadow(this,"jsActions",collectActions(this.xref,this.pageDict,PageActionEventType))}}const PDF_HEADER_SIGNATURE=new Uint8Array([37,80,68,70,45]),STARTXREF_SIGNATURE=new Uint8Array([115,116,97,114,116,120,114,101,102]),ENDOBJ_SIGNATURE=new Uint8Array([101,110,100,111,98,106]),FINGERPRINT_FIRST_BYTES=1024,EMPTY_FINGERPRINT="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";function find(stream,signature,limit=1024,backwards=!1){var signatureLength=signature.length,scanBytes=stream.peekBytes(limit),scanLength=scanBytes.length-signatureLength;if(!(scanLength<=0))if(backwards){var signatureEnd=signatureLength-1;let pos=scanBytes.length-1;for(;pos>=signatureEnd;){let j=0;for(;j=signatureLength)return stream.pos+=pos-signatureEnd,!0;pos--}}else{let pos=0;for(;pos<=scanLength;){let j=0;for(;j=signatureLength)return stream.pos+=pos,!0;pos++}}return!1}class PDFDocument{constructor(pdfManager,stream){if(stream.length<=0)throw new InvalidPDFException("The PDF file is empty, i.e. its size is zero bytes.");this.pdfManager=pdfManager,this.stream=stream,this.xref=new XRef(stream,pdfManager),this._pagePromises=new Map,this._version=null;const idCounters={font:0};this._globalIdFactory=class{static getDocId(){return"g_"+pdfManager.docId}static createFontId(){return"f"+ ++idCounters.font}static createObjId(){unreachable("Abstract method `createObjId` called.")}static getPageObjId(){unreachable("Abstract method `getPageObjId` called.")}}}parse(recoveryMode){this.xref.parse(recoveryMode),this.catalog=new Catalog(this.pdfManager,this.xref)}get linearization(){let linearization=null;try{linearization=Linearization.create(this.stream)}catch(err){if(err instanceof MissingDataException)throw err;info(err)}return shadow(this,"linearization",linearization)}get startXRef(){var stream=this.stream;let startXRef=0;if(this.linearization){if(stream.reset(),find(stream,ENDOBJ_SIGNATURE)){stream.skip(6);let ch=stream.peekByte();for(;isWhiteSpace(ch);)stream.pos++,ch=stream.peekByte();startXRef=stream.pos-stream.start}}else{var startXRefLength=STARTXREF_SIGNATURE.length;let found=!1,pos=stream.end;for(;!found&&0{var isSignature;return(field=this.xref.fetchIfRef(field))instanceof Dict&&(field.has("Kids")?10<++recursionDepth?(warn("_hasOnlyDocumentSignatures: maximum recursion depth reached"),!1):this._hasOnlyDocumentSignatures(field.get("Kids"),recursionDepth):(isSignature=isName(field.get("FT"),"Sig"),field=field.get("Rect"),field=Array.isArray(field)&&field.every(value=>0===value),isSignature&&field))})}get _xfaStreams(){var acroForm=this.catalog.acroForm;if(!acroForm)return null;var data,xfa=acroForm.get("XFA"),entries={"xdp:xdp":"",template:"",datasets:"",config:"",connectionSet:"",localeSet:"",stylesheet:"","/xdp:xdp":""};if(xfa instanceof BaseStream&&!xfa.isEmpty)entries["xdp:xdp"]=xfa;else{if(!Array.isArray(xfa)||0===xfa.length)return null;for(let i=0,ii=xfa.length;i{fonts.set(fontName,font)});var fontName,font,promises=[];for([fontName,font]of fonts){var descriptor=font.get("FontDescriptor");if(descriptor instanceof Dict){let fontFamily=descriptor.get("FontFamily");fontFamily=fontFamily.replaceAll(/[ ]+(\d)/g,"$1");var fontWeight=descriptor.get("FontWeight"),descriptor=-descriptor.get("ItalicAngle"),fontWeight={fontFamily:fontFamily,fontWeight:fontWeight,italicAngle:descriptor};validateCSSFont(fontWeight)&&promises.push(partialEvaluator.handleSetFont(resources,[Name.get(fontName),1],null,operatorList,task,initialState,null,fontWeight).catch(function(reason){return warn(`loadXfaFonts: "${reason}".`),null}))}}await Promise.all(promises);handler=this.xfaFactory.setFonts(pdfFonts);if(handler){options.ignoreErrors=!0,promises.length=0,pdfFonts.length=0;var reallyMissingFonts=new Set;for(const missing of handler)getXfaFontName(missing+"-Regular")||reallyMissingFonts.add(missing);reallyMissingFonts.size&&handler.push("PdfJS-Fallback");for(const missing of handler)if(!reallyMissingFonts.has(missing))for(const fontInfo of[{name:"Regular",fontWeight:400,italicAngle:0},{name:"Bold",fontWeight:700,italicAngle:0},{name:"Italic",fontWeight:400,italicAngle:12},{name:"BoldItalic",fontWeight:700,italicAngle:12}]){var name=missing+"-"+fontInfo.name,dict=getXfaFontDict(name);promises.push(partialEvaluator.handleSetFont(resources,[Name.get(name),1],null,operatorList,task,initialState,dict,{fontFamily:missing,fontWeight:fontInfo.fontWeight,italicAngle:fontInfo.italicAngle}).catch(function(reason){return warn(`loadXfaFonts: "${reason}".`),null}))}await Promise.all(promises),this.xfaFactory.appendFonts(pdfFonts,reallyMissingFonts)}}}}}async serializeXfaData(annotationStorage){return this.xfaFactory?this.xfaFactory.serializeData(annotationStorage):null}get version(){return this.catalog.version||this._version}get formInfo(){var formInfo={hasFields:!1,hasAcroForm:!1,hasXfa:!1,hasSignatures:!1},acroForm=this.catalog.acroForm;if(acroForm)try{var fields=acroForm.get("Fields"),hasFields=Array.isArray(fields)&&0new Page({pdfManager:this.pdfManager,xref:this.xref,pageIndex:pageIndex,pageDict:pageDict,ref:ref,globalIdFactory:this._globalIdFactory,fontCache:catalog.fontCache,builtInCMapCache:catalog.builtInCMapCache,standardFontDataCache:catalog.standardFontDataCache,globalImageCache:catalog.globalImageCache,systemFontCache:catalog.systemFontCache,nonBlendModesSet:catalog.nonBlendModesSet,xfaFactory:xfaFactory})),this._pagePromises.set(pageIndex,promise),promise}async checkFirstPage(recoveryMode=!1){if(!recoveryMode)try{await this.getPage(0)}catch(reason){if(reason instanceof XRefEntryException)throw this._pagePromises.delete(0),await this.cleanup(),new XRefParseException}}async checkLastPage(recoveryMode=!1){var{catalog,pdfManager}=this;catalog.setActualNumPages();let numPages;try{if(await Promise.all([pdfManager.ensureDoc("xfaFactory"),pdfManager.ensureDoc("linearization"),pdfManager.ensureCatalog("numPages")]),!this.xfaFactory){if(numPages=(this.linearization||catalog).numPages,!Number.isInteger(numPages))throw new FormatError("Page count is not an integer.");numPages<=1||await this.getPage(numPages-1)}}catch(reason){if(this._pagePromises.delete(numPages-1),await this.cleanup(),reason instanceof XRefEntryException&&!recoveryMode)throw new XRefParseException;warn(`checkLastPage - invalid /Pages tree /Count: ${numPages}.`);let pagesTree;try{pagesTree=await catalog.getAllPageDicts(recoveryMode)}catch(reasonAll){if(reasonAll instanceof XRefEntryException&&!recoveryMode)throw new XRefParseException;return void catalog.setActualNumPages(1)}for(var[pageIndex,[pageDict,ref]]of pagesTree){let promise;pageDict instanceof Error?(promise=Promise.reject(pageDict)).catch(()=>{}):promise=Promise.resolve(new Page({pdfManager:pdfManager,xref:this.xref,pageIndex:pageIndex,pageDict:pageDict,ref:ref,globalIdFactory:this._globalIdFactory,fontCache:catalog.fontCache,builtInCMapCache:catalog.builtInCMapCache,standardFontDataCache:catalog.standardFontDataCache,globalImageCache:catalog.globalImageCache,systemFontCache:catalog.systemFontCache,nonBlendModesSet:catalog.nonBlendModesSet,xfaFactory:null})),this._pagePromises.set(pageIndex,promise)}catalog.setActualNumPages(pagesTree.size)}}fontFallback(id,handler){return this.catalog.fontFallback(id,handler)}async cleanup(manuallyTriggered=!1){return this.catalog?this.catalog.cleanup(manuallyTriggered):clearGlobalCaches()}async#collectFieldObjects(name,fieldRef,promises,annotationGlobals,visitedRefs){var xref=this["xref"];if(fieldRef instanceof Ref&&!visitedRefs.has(fieldRef)){visitedRefs.put(fieldRef);var field=await xref.fetchAsync(fieldRef);if(field instanceof Dict){if(field.has("T")){var partName=stringToPDFString(await field.getAsync("T"));name=""===name?partName:name+"."+partName}else{let obj=field;for(;;){if((obj=obj.getRaw("Parent"))instanceof Ref){if(visitedRefs.has(obj))break;obj=await xref.fetchAsync(obj)}if(!(obj instanceof Dict))break;if(obj.has("T")){const partName=stringToPDFString(await obj.getAsync("T"));name=""===name?partName:name+"."+partName;break}}}if(promises.has(name)||promises.set(name,[]),promises.get(name).push(AnnotationFactory.create(xref,fieldRef,annotationGlobals,null,!0,null).then(annotation=>annotation?.getFieldObject()).catch(function(reason){return warn(`#collectFieldObjects: "${reason}".`),null})),field.has("Kids")){partName=await field.getAsync("Kids");if(Array.isArray(partName))for(const kid of partName)await this.#collectFieldObjects(name,kid,promises,annotationGlobals,visitedRefs)}}}}get fieldObjects(){var promise;return this.formInfo.hasFields?(promise=Promise.all([this.pdfManager.ensureDoc("annotationGlobals"),this.pdfManager.ensureCatalog("acroForm")]).then(async([annotationGlobals,acroForm])=>{if(!annotationGlobals)return null;var visitedRefs=new RefSet;const allFields=Object.create(null);var fieldPromises=new Map;for(const fieldRef of await acroForm.getAsync("Fields"))await this.#collectFieldObjects("",fieldRef,fieldPromises,annotationGlobals,visitedRefs);var allPromises=[];for(const[name,promises]of fieldPromises)allPromises.push(Promise.all(promises).then(fields=>{0<(fields=fields.filter(field=>!!field)).length&&(allFields[name]=fields)}));return await Promise.all(allPromises),allFields}),shadow(this,"fieldObjects",promise)):shadow(this,"fieldObjects",Promise.resolve(null))}get hasJSActions(){var promise=this.pdfManager.ensureDoc("_parseHasJSActions");return shadow(this,"hasJSActions",promise)}async _parseHasJSActions(){var[catalogJsActions,fieldObjects]=await Promise.all([this.pdfManager.ensureCatalog("jsActions"),this.pdfManager.ensureDoc("fieldObjects")]);return!!catalogJsActions||!!fieldObjects&&Object.values(fieldObjects).some(fieldObject=>fieldObject.some(object=>null!==object.actions))}get calculationOrderIds(){var acroForm=this.catalog.acroForm;if(!acroForm?.has("CO"))return shadow(this,"calculationOrderIds",null);acroForm=acroForm.get("CO");if(!Array.isArray(acroForm)||0===acroForm.length)return shadow(this,"calculationOrderIds",null);var ids=[];for(const id of acroForm)id instanceof Ref&&ids.push(id.toString());return shadow(this,"calculationOrderIds",0===ids.length?null:ids)}get annotationGlobals(){return shadow(this,"annotationGlobals",AnnotationFactory.createGlobals(this.pdfManager))}}function parseDocBaseUrl(url){if(url){var absoluteUrl=createValidAbsoluteUrl(url);if(absoluteUrl)return absoluteUrl.href;warn(`Invalid absolute docBaseUrl: "${url}".`)}return null}class BasePdfManager{constructor(args){this.constructor===BasePdfManager&&unreachable("Cannot initialize BasePdfManager."),this._docBaseUrl=parseDocBaseUrl(args.docBaseUrl),this._docId=args.docId,this._password=args.password,this.enableXfa=args.enableXfa,args.evaluatorOptions.isOffscreenCanvasSupported&&=FeatureTest.isOffscreenCanvasSupported,this.evaluatorOptions=args.evaluatorOptions}get docId(){return this._docId}get password(){return this._password}get docBaseUrl(){return this._docBaseUrl}get catalog(){return this.pdfDocument.catalog}ensureDoc(prop,args){return this.ensure(this.pdfDocument,prop,args)}ensureXRef(prop,args){return this.ensure(this.pdfDocument.xref,prop,args)}ensureCatalog(prop,args){return this.ensure(this.pdfDocument.catalog,prop,args)}getPage(pageIndex){return this.pdfDocument.getPage(pageIndex)}fontFallback(id,handler){return this.pdfDocument.fontFallback(id,handler)}loadXfaFonts(handler,task){return this.pdfDocument.loadXfaFonts(handler,task)}loadXfaImages(){return this.pdfDocument.loadXfaImages()}serializeXfaData(annotationStorage){return this.pdfDocument.serializeXfaData(annotationStorage)}cleanup(manuallyTriggered=!1){return this.pdfDocument.cleanup(manuallyTriggered)}async ensure(obj,prop,args){unreachable("Abstract method `ensure` called")}requestRange(begin,end){unreachable("Abstract method `requestRange` called")}requestLoadedStream(noFetch=0){unreachable("Abstract method `requestLoadedStream` called")}sendProgressiveData(chunk){unreachable("Abstract method `sendProgressiveData` called")}updatePassword(password){this._password=password}terminate(reason){unreachable("Abstract method `terminate` called")}}class LocalPdfManager extends BasePdfManager{constructor(args){super(args);args=new Stream(args.source);this.pdfDocument=new PDFDocument(this,args),this._loadedStreamPromise=Promise.resolve(args)}async ensure(obj,prop,args){prop=obj[prop];return"function"==typeof prop?prop.apply(obj,args):prop}requestRange(begin,end){return Promise.resolve()}requestLoadedStream(noFetch=0){return this._loadedStreamPromise}terminate(reason){}}class NetworkPdfManager extends BasePdfManager{constructor(args){super(args),this.streamManager=new ChunkedStreamManager(args.source,{msgHandler:args.handler,length:args.length,disableAutoFetch:args.disableAutoFetch,rangeChunkSize:args.rangeChunkSize}),this.pdfDocument=new PDFDocument(this,this.streamManager.getStream())}async ensure(obj,prop,args){try{var value=obj[prop];return"function"==typeof value?value.apply(obj,args):value}catch(ex){if(ex instanceof MissingDataException)return await this.requestRange(ex.begin,ex.end),this.ensure(obj,prop,args);throw ex}}requestRange(begin,end){return this.streamManager.requestRange(begin,end)}requestLoadedStream(noFetch=!1){return this.streamManager.requestAllChunks(noFetch)}sendProgressiveData(chunk){this.streamManager.onReceiveData({chunk:chunk})}terminate(reason){this.streamManager.abort(reason)}}const CallbackKind={UNKNOWN:0,DATA:1,ERROR:2},StreamKind={UNKNOWN:0,CANCEL:1,CANCEL_COMPLETE:2,CLOSE:3,ENQUEUE:4,ERROR:5,PULL:6,PULL_COMPLETE:7,START_COMPLETE:8};function wrapReason(reason){switch(reason instanceof Error||"object"==typeof reason&&null!==reason||unreachable('wrapReason: Expected "reason" to be a (possibly cloned) Error.'),reason.name){case"AbortException":return new AbortException(reason.message);case"MissingPDFException":return new MissingPDFException(reason.message);case"PasswordException":return new PasswordException(reason.message,reason.code);case"UnexpectedResponseException":return new UnexpectedResponseException(reason.message,reason.status);case"UnknownErrorException":return new UnknownErrorException(reason.message,reason.details);default:return new UnknownErrorException(reason.message,reason.toString())}}class MessageHandler{constructor(sourceName,targetName,comObj){this.sourceName=sourceName,this.targetName=targetName,this.comObj=comObj,this.callbackId=1,this.streamId=1,this.streamSinks=Object.create(null),this.streamControllers=Object.create(null),this.callbackCapabilities=Object.create(null),this.actionHandler=Object.create(null),this._onComObjOnMessage=event=>{const data=event.data;if(data.targetName===this.sourceName)if(data.stream)this.#processStreamMessage(data);else if(data.callback){var event=data.callbackId,capability=this.callbackCapabilities[event];if(!capability)throw new Error("Cannot resolve callback "+event);if(delete this.callbackCapabilities[event],data.callback===CallbackKind.DATA)capability.resolve(data.data);else{if(data.callback!==CallbackKind.ERROR)throw new Error("Unexpected callback case");capability.reject(wrapReason(data.reason))}}else{const action=this.actionHandler[data.action];if(!action)throw new Error("Unknown action from worker: "+data.action);if(data.callbackId){const cbSourceName=this.sourceName,cbTargetName=data.sourceName;void new Promise(function(resolve){resolve(action(data.data))}).then(function(result){comObj.postMessage({sourceName:cbSourceName,targetName:cbTargetName,callback:CallbackKind.DATA,callbackId:data.callbackId,data:result})},function(reason){comObj.postMessage({sourceName:cbSourceName,targetName:cbTargetName,callback:CallbackKind.ERROR,callbackId:data.callbackId,reason:wrapReason(reason)})})}else data.streamId?this.#createStreamSink(data):action(data.data)}},comObj.addEventListener("message",this._onComObjOnMessage)}on(actionName,handler){var ah=this.actionHandler;if(ah[actionName])throw new Error(`There is already an actionName called "${actionName}"`);ah[actionName]=handler}send(actionName,data,transfers){this.comObj.postMessage({sourceName:this.sourceName,targetName:this.targetName,action:actionName,data:data},transfers)}sendWithPromise(actionName,data,transfers){var callbackId=this.callbackId++,capability=Promise.withResolvers();this.callbackCapabilities[callbackId]=capability;try{this.comObj.postMessage({sourceName:this.sourceName,targetName:this.targetName,action:actionName,callbackId:callbackId,data:data},transfers)}catch(ex){capability.reject(ex)}return capability.promise}sendWithStream(actionName,data,queueingStrategy,transfers){const streamId=this.streamId++,sourceName=this.sourceName,targetName=this.targetName,comObj=this.comObj;return new ReadableStream({start:controller=>{var startCapability=Promise.withResolvers();return this.streamControllers[streamId]={controller:controller,startCall:startCapability,pullCall:null,cancelCall:null,isClosed:!1},comObj.postMessage({sourceName:sourceName,targetName:targetName,action:actionName,streamId:streamId,data:data,desiredSize:controller.desiredSize},transfers),startCapability.promise},pull:controller=>{var pullCapability=Promise.withResolvers();return this.streamControllers[streamId].pullCall=pullCapability,comObj.postMessage({sourceName:sourceName,targetName:targetName,stream:StreamKind.PULL,streamId:streamId,desiredSize:controller.desiredSize}),pullCapability.promise},cancel:reason=>{assert(reason instanceof Error,"cancel must have a valid reason");var cancelCapability=Promise.withResolvers();return this.streamControllers[streamId].cancelCall=cancelCapability,this.streamControllers[streamId].isClosed=!0,comObj.postMessage({sourceName:sourceName,targetName:targetName,stream:StreamKind.CANCEL,streamId:streamId,reason:wrapReason(reason)}),cancelCapability.promise}},queueingStrategy)}#createStreamSink(data){const streamId=data.streamId,sourceName=this.sourceName,targetName=data.sourceName,comObj=this.comObj,self=this,action=this.actionHandler[data.action],streamSink={enqueue(chunk,size=1,transfers){var lastDesiredSize;this.isCancelled||(lastDesiredSize=this.desiredSize,this.desiredSize-=size,0{this._isStreamingSupported=data.isStreamingSupported,this._isRangeSupported=data.isRangeSupported,this._contentLength=data.contentLength})}get headersReady(){return this._headersReady}get contentLength(){return this._contentLength}get isStreamingSupported(){return this._isStreamingSupported}get isRangeSupported(){return this._isRangeSupported}async read(){var{value,done}=await this._reader.read();return done?{value:void 0,done:!0}:{value:value.buffer,done:!1}}cancel(reason){this._reader.cancel(reason)}}class PDFWorkerStreamRangeReader{constructor(begin,end,msgHandler){this._msgHandler=msgHandler,this.onProgress=null;msgHandler=this._msgHandler.sendWithStream("GetRangeReader",{begin:begin,end:end});this._reader=msgHandler.getReader()}get isStreamingSupported(){return!1}async read(){var{value,done}=await this._reader.read();return done?{value:void 0,done:!0}:{value:value.buffer,done:!1}}cancel(reason){this._reader.cancel(reason)}}class WorkerTask{constructor(name){this.name=name,this.terminated=!1,this._capability=Promise.withResolvers()}get finished(){return this._capability.promise}finish(){this._capability.resolve()}terminate(){this.terminated=!0}ensureNotTerminated(){if(this.terminated)throw new Error("Worker task was terminated")}}class WorkerMessageHandler{static setup(handler,port){let testMessageProcessed=!1;handler.on("test",function(data){testMessageProcessed||(testMessageProcessed=!0,handler.send("test",data instanceof Uint8Array))}),handler.on("configure",function(data){setVerbosityLevel(data.verbosity)}),handler.on("GetDocRequest",function(data){return WorkerMessageHandler.createDocumentHandler(data,port)})}static createDocumentHandler(docParams,port){let pdfManager,terminated=!1,cancelXHRs=null;const WorkerTasks=new Set,verbosity=getVerbosityLevel(),{docId,apiVersion}=docParams;if("4.2.67"!==apiVersion)throw new Error(`The API version "${apiVersion}" does not match `+'the Worker version "4.2.67".');var enumerableProperties=[];for(const property in[])enumerableProperties.push(property);if(enumerableProperties.length)throw new Error("The `Array.prototype` contains unexpected enumerable properties: "+enumerableProperties.join(", ")+"; thus breaking e.g. `for...in` iteration of `Array`s.");var workerHandlerName=docId+"_worker";let handler=new MessageHandler(workerHandlerName,docId,port);function ensureNotTerminated(){if(terminated)throw new Error("Worker was terminated")}function startWorkerTask(task){WorkerTasks.add(task)}function finishWorkerTask(task){task.finish(),WorkerTasks.delete(task)}async function loadDocument(recoveryMode){await pdfManager.ensureDoc("checkHeader"),await pdfManager.ensureDoc("parseStartXRef"),await pdfManager.ensureDoc("parse",[recoveryMode]),await pdfManager.ensureDoc("checkFirstPage",[recoveryMode]),await pdfManager.ensureDoc("checkLastPage",[recoveryMode]);recoveryMode=await pdfManager.ensureDoc("isPureXfa");if(recoveryMode){const task=new WorkerTask("loadXfaFonts");startWorkerTask(task),await Promise.all([pdfManager.loadXfaFonts(handler,task).catch(reason=>{}).then(()=>finishWorkerTask(task)),pdfManager.loadXfaImages()])}var[numPages,fingerprints]=await Promise.all([pdfManager.ensureDoc("numPages"),pdfManager.ensureDoc("fingerprints")]);return{numPages:numPages,fingerprints:fingerprints,htmlForXfa:recoveryMode?await pdfManager.ensureDoc("htmlForXfa"):null}}function getPdfManager({data,password,disableAutoFetch,rangeChunkSize,length,docBaseUrl,enableXfa,evaluatorOptions}){const pdfManagerArgs={source:null,disableAutoFetch:disableAutoFetch,docBaseUrl:docBaseUrl,docId:docId,enableXfa:enableXfa,evaluatorOptions:evaluatorOptions,handler:handler,length:length,password:password,rangeChunkSize:rangeChunkSize},pdfManagerCapability=Promise.withResolvers();let newPdfManager;if(data)try{pdfManagerArgs.source=data,newPdfManager=new LocalPdfManager(pdfManagerArgs),pdfManagerCapability.resolve(newPdfManager)}catch(ex){pdfManagerCapability.reject(ex)}else{let pdfStream,cachedChunks=[];try{pdfStream=new PDFWorkerStream(handler)}catch(ex){return pdfManagerCapability.reject(ex),pdfManagerCapability.promise}const fullRequest=pdfStream.getFullReader();fullRequest.headersReady.then(function(){if(fullRequest.isRangeSupported){pdfManagerArgs.source=pdfStream,pdfManagerArgs.length=fullRequest.contentLength,pdfManagerArgs.disableAutoFetch||=fullRequest.isStreamingSupported,newPdfManager=new NetworkPdfManager(pdfManagerArgs);for(const chunk of cachedChunks)newPdfManager.sendProgressiveData(chunk);cachedChunks=[],pdfManagerCapability.resolve(newPdfManager),cancelXHRs=null}}).catch(function(reason){pdfManagerCapability.reject(reason),cancelXHRs=null});let loaded=0;new Promise(function(resolve,reject){const readChunk=function({value,done}){try{if(ensureNotTerminated(),done){if(!newPdfManager){var pdfFile=arrayBuffersToBytes(cachedChunks);length&&pdfFile.length!==length&&warn("reported HTTP length is different from actual");try{pdfManagerArgs.source=pdfFile,newPdfManager=new LocalPdfManager(pdfManagerArgs),pdfManagerCapability.resolve(newPdfManager)}catch(ex){pdfManagerCapability.reject(ex)}cachedChunks=[]}cancelXHRs=null}else loaded+=value.byteLength,fullRequest.isStreamingSupported||handler.send("DocProgress",{loaded:loaded,total:Math.max(loaded,fullRequest.contentLength||0)}),newPdfManager?newPdfManager.sendProgressiveData(value):cachedChunks.push(value),fullRequest.read().then(readChunk,reject)}catch(e){reject(e)}};fullRequest.read().then(readChunk,reject)}).catch(function(e){pdfManagerCapability.reject(e),cancelXHRs=null}),cancelXHRs=function(reason){pdfStream.cancelAllRequests(reason)}}return pdfManagerCapability.promise}return handler.on("GetPage",function(data){return pdfManager.getPage(data.pageIndex).then(function(page){return Promise.all([pdfManager.ensure(page,"rotate"),pdfManager.ensure(page,"ref"),pdfManager.ensure(page,"userUnit"),pdfManager.ensure(page,"view")]).then(function([rotate,ref,userUnit,view]){return{rotate:rotate,ref:ref,refStr:ref?.toString()??null,userUnit:userUnit,view:view}})})}),handler.on("GetPageIndex",function(data){data=Ref.get(data.num,data.gen);return pdfManager.ensureCatalog("getPageIndex",[data])}),handler.on("GetDestinations",function(data){return pdfManager.ensureCatalog("destinations")}),handler.on("GetDestination",function(data){return pdfManager.ensureCatalog("getDestination",[data.id])}),handler.on("GetPageLabels",function(data){return pdfManager.ensureCatalog("pageLabels")}),handler.on("GetPageLayout",function(data){return pdfManager.ensureCatalog("pageLayout")}),handler.on("GetPageMode",function(data){return pdfManager.ensureCatalog("pageMode")}),handler.on("GetViewerPreferences",function(data){return pdfManager.ensureCatalog("viewerPreferences")}),handler.on("GetOpenAction",function(data){return pdfManager.ensureCatalog("openAction")}),handler.on("GetAttachments",function(data){return pdfManager.ensureCatalog("attachments")}),handler.on("GetDocJSActions",function(data){return pdfManager.ensureCatalog("jsActions")}),handler.on("GetPageJSActions",function({pageIndex}){return pdfManager.getPage(pageIndex).then(function(page){return pdfManager.ensure(page,"jsActions")})}),handler.on("GetOutline",function(data){return pdfManager.ensureCatalog("documentOutline")}),handler.on("GetOptionalContentConfig",function(data){return pdfManager.ensureCatalog("optionalContentConfig")}),handler.on("GetPermissions",function(data){return pdfManager.ensureCatalog("permissions")}),handler.on("GetMetadata",function(data){return Promise.all([pdfManager.ensureDoc("documentInfo"),pdfManager.ensureCatalog("metadata")])}),handler.on("GetMarkInfo",function(data){return pdfManager.ensureCatalog("markInfo")}),handler.on("GetData",function(data){return pdfManager.requestLoadedStream().then(function(stream){return stream.bytes})}),handler.on("GetAnnotations",function({pageIndex,intent}){return pdfManager.getPage(pageIndex).then(function(page){const task=new WorkerTask("GetAnnotations: page "+pageIndex);return startWorkerTask(task),page.getAnnotationsData(handler,task,intent).then(data=>(finishWorkerTask(task),data),reason=>{throw finishWorkerTask(task),reason})})}),handler.on("GetFieldObjects",function(data){return pdfManager.ensureDoc("fieldObjects")}),handler.on("HasJSActions",function(data){return pdfManager.ensureDoc("hasJSActions")}),handler.on("GetCalculationOrderIds",function(data){return pdfManager.ensureDoc("calculationOrderIds")}),handler.on("SaveDocument",async function({isPureXfa,numPages,annotationStorage,filename}){var globalPromises=[pdfManager.requestLoadedStream(),pdfManager.ensureCatalog("acroForm"),pdfManager.ensureCatalog("acroFormRef"),pdfManager.ensureDoc("startXRef"),pdfManager.ensureDoc("xref"),pdfManager.ensureDoc("linearization"),pdfManager.ensureCatalog("structTreeRoot")],promises=[];const newAnnotationsByPage=isPureXfa?null:getNewAnnotationsMap(annotationStorage),[stream,acroForm,acroFormRef,startXRef,xref,linearization,_structTreeRoot]=await Promise.all(globalPromises),catalogRef=xref.trailer.getRaw("Root")||null;let structTreeRoot;if(newAnnotationsByPage){_structTreeRoot?await _structTreeRoot.canUpdateStructTree({pdfManager:pdfManager,xref:xref,newAnnotationsByPage:newAnnotationsByPage})&&(structTreeRoot=_structTreeRoot):await StructTreeRoot.canCreateStructureTree({catalogRef:catalogRef,pdfManager:pdfManager,newAnnotationsByPage:newAnnotationsByPage})&&(structTreeRoot=null);const imagePromises=AnnotationFactory.generateImages(annotationStorage.values(),xref,pdfManager.evaluatorOptions.isOffscreenCanvasSupported);var newAnnotationPromises=void 0===structTreeRoot?promises:[];for(const[pageIndex,annotations]of newAnnotationsByPage)newAnnotationPromises.push(pdfManager.getPage(pageIndex).then(page=>{const task=new WorkerTask("Save (editor): page "+pageIndex);return page.saveNewAnnotations(handler,task,annotations,imagePromises).finally(function(){finishWorkerTask(task)})}));null===structTreeRoot?promises.push(Promise.all(newAnnotationPromises).then(async newRefs=>(await StructTreeRoot.createStructureTree({newAnnotationsByPage:newAnnotationsByPage,xref:xref,catalogRef:catalogRef,pdfManager:pdfManager,newRefs:newRefs}),newRefs))):structTreeRoot&&promises.push(Promise.all(newAnnotationPromises).then(async newRefs=>(await structTreeRoot.updateStructureTree({newAnnotationsByPage:newAnnotationsByPage,pdfManager:pdfManager,newRefs:newRefs}),newRefs)))}if(isPureXfa)promises.push(pdfManager.serializeXfaData(annotationStorage));else for(let pageIndex=0;pageIndexref.needAppearances),xfa=acroForm instanceof Dict&&acroForm.get("XFA")||null;let xfaDatasetsRef=null,hasXfaDatasetsEntry=!1;if(Array.isArray(xfa)){for(let i=0,ii=xfa.length;i{"string"==typeof value&&(infoObj[key]=stringToPDFString(value))}),newXrefInfo={rootRef:catalogRef,encryptRef:xref.trailer.getRaw("Encrypt")||null,newRef:xref.getNewTemporaryRef(),infoRef:xref.trailer.getRaw("Info")||null,info:infoObj,fileIds:xref.trailer.get("ID")||null,startXRef:linearization?startXRef:xref.lastXRefStreamPos??startXRef,filename:filename}}return incrementalUpdate({originalData:stream.bytes,xrefInfo:newXrefInfo,newRefs:newRefs,xref:xref,hasXfa:!!xfa,xfaDatasetsRef:xfaDatasetsRef,hasXfaDatasetsEntry:hasXfaDatasetsEntry,needAppearances:isPureXfa,acroFormRef:acroFormRef,acroForm:acroForm,xfaData:xfaData,useXrefStream:isDict(xref.topDict,"XRef")}).finally(()=>{xref.resetNewTemporaryRef()})}),handler.on("GetOperatorList",function(data,sink){const pageIndex=data.pageIndex;pdfManager.getPage(pageIndex).then(function(page){const task=new WorkerTask("GetOperatorList: page "+pageIndex),start=(startWorkerTask(task),verbosity>=VerbosityLevel.INFOS?Date.now():0);page.getOperatorList({handler:handler,sink:sink,task:task,intent:data.intent,cacheKey:data.cacheKey,annotationStorage:data.annotationStorage}).then(function(operatorListInfo){finishWorkerTask(task),start&&info(`page=${pageIndex+1} - getOperatorList: time=`+(Date.now()-start)+"ms, len="+operatorListInfo.length),sink.close()},function(reason){finishWorkerTask(task),task.terminated||sink.error(reason)})})}),handler.on("GetTextContent",function(data,sink){const{pageIndex,includeMarkedContent,disableNormalization}=data;pdfManager.getPage(pageIndex).then(function(page){const task=new WorkerTask("GetTextContent: page "+pageIndex),start=(startWorkerTask(task),verbosity>=VerbosityLevel.INFOS?Date.now():0);page.extractTextContent({handler:handler,task:task,sink:sink,includeMarkedContent:includeMarkedContent,disableNormalization:disableNormalization}).then(function(){finishWorkerTask(task),start&&info(`page=${pageIndex+1} - getTextContent: time=`+(Date.now()-start)+"ms"),sink.close()},function(reason){finishWorkerTask(task),task.terminated||sink.error(reason)})})}),handler.on("GetStructTree",function(data){return pdfManager.getPage(data.pageIndex).then(function(page){return pdfManager.ensure(page,"getStructTree")})}),handler.on("FontFallback",function(data){return pdfManager.fontFallback(data.id,handler)}),handler.on("Cleanup",function(data){return pdfManager.cleanup(!0)}),handler.on("Terminate",function(data){terminated=!0;var cleanupPromise,waitOn=[];pdfManager?(pdfManager.terminate(new AbortException("Worker was terminated.")),cleanupPromise=pdfManager.cleanup(),waitOn.push(cleanupPromise),pdfManager=null):clearGlobalCaches(),cancelXHRs&&cancelXHRs(new AbortException("Worker was terminated."));for(const task of WorkerTasks)waitOn.push(task.finished),task.terminate();return Promise.all(waitOn).then(function(){handler.destroy(),handler=null})}),handler.on("Ready",function(data){!function(data){function onSuccess(doc){ensureNotTerminated(),handler.send("GetDoc",{pdfInfo:doc})}function onFailure(ex){if(ensureNotTerminated(),ex instanceof PasswordException){const task=new WorkerTask("PasswordException: response "+ex.code);startWorkerTask(task),handler.sendWithPromise("PasswordRequest",ex).then(function({password}){finishWorkerTask(task),pdfManager.updatePassword(password),pdfManagerReady()}).catch(function(){finishWorkerTask(task),handler.send("DocException",ex)})}else ex instanceof InvalidPDFException||ex instanceof MissingPDFException||ex instanceof UnexpectedResponseException||ex instanceof UnknownErrorException?handler.send("DocException",ex):handler.send("DocException",new UnknownErrorException(ex.message,ex.toString()))}function pdfManagerReady(){ensureNotTerminated(),loadDocument(!1).then(onSuccess,function(reason){ensureNotTerminated(),reason instanceof XRefParseException?pdfManager.requestLoadedStream().then(function(){ensureNotTerminated(),loadDocument(!0).then(onSuccess,onFailure)}):onFailure(reason)})}ensureNotTerminated(),getPdfManager(data).then(function(newPdfManager){if(terminated)throw newPdfManager.terminate(new AbortException("Worker was terminated.")),new Error("Worker was terminated");(pdfManager=newPdfManager).requestLoadedStream(!0).then(stream=>{handler.send("DataLoaded",{length:stream.bytes.byteLength})})}).then(pdfManagerReady,onFailure)}(docParams),docParams=null}),workerHandlerName}static initializeFromPort(port){var handler=new MessageHandler("worker","main",port);WorkerMessageHandler.setup(handler,port),handler.send("ready",null)}}function isMessagePort(maybePort){return"function"==typeof maybePort.postMessage&&"onmessage"in maybePort}"undefined"==typeof window&&!isNodeJS&&"undefined"!=typeof self&&isMessagePort(self)&&WorkerMessageHandler.initializeFromPort(self);const pdfjsVersion="4.2.67",pdfjsBuild="49b388101";var __webpack_exports__WorkerMessageHandler=__webpack_exports__.WorkerMessageHandler;export{__webpack_exports__WorkerMessageHandler as WorkerMessageHandler}; \ No newline at end of file diff --git a/projects/web/public/pdfjs-dist/build/test.js b/projects/web/public/pdfjs-dist/build/test.js deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/projects/web/public/pdfjs-dist/web/cmaps/78-EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/78-EUC-H.bcmap deleted file mode 100644 index 2655fc70ae706c7ba52a5d647cbfdfad6072c697..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/78-EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/78-EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/78-EUC-V.bcmap deleted file mode 100644 index f1ed8538287499647d923d7d8f517a00cdac4e3a..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/78-EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/78-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/78-H.bcmap deleted file mode 100644 index 39e89d3339c74cbe06e7e4f76d60bf3556b0d4b6..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/78-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/78-RKSJ-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/78-RKSJ-H.bcmap deleted file mode 100644 index e4167cb51f66c60ef7d9500b450303b5da175574..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/78-RKSJ-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/78-RKSJ-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/78-RKSJ-V.bcmap deleted file mode 100644 index 50b1646e94bba61b3242a680fe3023337e191123..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/78-RKSJ-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/78-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/78-V.bcmap deleted file mode 100644 index d7af99b5e2ae9a21d534f1965c35a2b572143322..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/78-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/78ms-RKSJ-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/78ms-RKSJ-H.bcmap deleted file mode 100644 index 37077d01e26f9ee2427592f6deebb145d628e731..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/78ms-RKSJ-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/78ms-RKSJ-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/78ms-RKSJ-V.bcmap deleted file mode 100644 index acf23231aea22e1a95761f7eafd35f1d42ea6b84..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/78ms-RKSJ-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/83pv-RKSJ-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/83pv-RKSJ-H.bcmap deleted file mode 100644 index 2359bc529d160857cce4c1d1bfca1322290205c1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/83pv-RKSJ-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/90ms-RKSJ-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/90ms-RKSJ-H.bcmap deleted file mode 100644 index af8293829c90ce63cc4c5eda0318003785ffcba1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/90ms-RKSJ-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/90ms-RKSJ-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/90ms-RKSJ-V.bcmap deleted file mode 100644 index 780549de19de05b6cbea4ccd4737351bc9ff6104..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/90ms-RKSJ-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/90msp-RKSJ-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/90msp-RKSJ-H.bcmap deleted file mode 100644 index bfd3119c62d9976dde9b1e59c572c678cf5811a0..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/90msp-RKSJ-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/90msp-RKSJ-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/90msp-RKSJ-V.bcmap deleted file mode 100644 index 25ef14ab4af42f4b70ccac76cddac8f3b22d8813..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/90msp-RKSJ-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/90pv-RKSJ-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/90pv-RKSJ-H.bcmap deleted file mode 100644 index 02f713bb838a8cd46f5b262c934d0edc8c6e8fe9..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/90pv-RKSJ-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/90pv-RKSJ-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/90pv-RKSJ-V.bcmap deleted file mode 100644 index d08e0cc5d98b2d933ab848c69dd6c504fbf1787d..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/90pv-RKSJ-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Add-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Add-H.bcmap deleted file mode 100644 index 59442acafb613b0c090314379f9f4c2fa134a1a1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Add-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Add-RKSJ-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Add-RKSJ-H.bcmap deleted file mode 100644 index a3065e441a0e1f1a65e9109ec9bc4f826fccac24..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Add-RKSJ-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Add-RKSJ-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Add-RKSJ-V.bcmap deleted file mode 100644 index 040014cfc0880371c20a89212942727c5dc30a78..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Add-RKSJ-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Add-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Add-V.bcmap deleted file mode 100644 index 2f816d320f08b8671498299c4d00e4564d2ece6c..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Add-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-0.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-0.bcmap deleted file mode 100644 index 88ec04af49d1e8ab6038e3b36dd28daf4dcf0119..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-0.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-1.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-1.bcmap deleted file mode 100644 index 03a501477c91d8156723f0c274a37d397ed65bad..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-1.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-2.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-2.bcmap deleted file mode 100644 index 2aa95141f9f5802818e34b0aa626e34e7cfee805..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-2.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-3.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-3.bcmap deleted file mode 100644 index 86d8b8c79cfa3907281aa3f25a46f178b87aedfa..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-3.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-4.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-4.bcmap deleted file mode 100644 index f50fc6c14e67a228c4ba9a61b1357c16410e8228..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-4.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-5.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-5.bcmap deleted file mode 100644 index 6caf4a83146a60a2db652647b9cfed5fb71bd97c..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-5.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-6.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-6.bcmap deleted file mode 100644 index b77fb0705c28d647d0bf7b25246af566a791b2ec..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-6.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-UCS2.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-UCS2.bcmap deleted file mode 100644 index 69d79a2c2c2b00207ab27b68ebf4404aa17c6f2c..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-CNS1-UCS2.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-0.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-0.bcmap deleted file mode 100644 index 36101083fa8fd22399728ccf533c48e830781de0..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-0.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-1.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-1.bcmap deleted file mode 100644 index 707bb1065c76d69551c287141cb258519132ef8e..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-1.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-2.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-2.bcmap deleted file mode 100644 index f7648cc3ff02c44e9594ccbd71deec742e253c2f..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-2.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-3.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-3.bcmap deleted file mode 100644 index 852145890ede3dc04339de284993da270d62311d..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-3.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-4.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-4.bcmap deleted file mode 100644 index e40c63ab1e5c240841f3b465ade920d60be6328f..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-4.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-5.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-5.bcmap deleted file mode 100644 index d7623b500232b6e62f29c2c232e6c2469a527314..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-5.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-UCS2.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-UCS2.bcmap deleted file mode 100644 index 7586525936cc5398b86d3752a4eb45b15825b25c..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-GB1-UCS2.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-0.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-0.bcmap deleted file mode 100644 index f0e94ec196757e8660b567d8ece7f99869927913..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-0.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-1.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-1.bcmap deleted file mode 100644 index dad42c5ad7dad57954fc9a051ee7e222e83bee45..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-1.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-2.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-2.bcmap deleted file mode 100644 index 090819a064533f20aa68f562275556397683ae81..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-2.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-3.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-3.bcmap deleted file mode 100644 index 087dfc155860e65d2dc828dd432ffe88239fde23..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-3.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-4.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-4.bcmap deleted file mode 100644 index 46aa9bffe576e9a8b714646aed7f9e1a4e99dfe2..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-4.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-5.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-5.bcmap deleted file mode 100644 index 5b4b65cc6292a5ba7d89e976565bf08814bb88b6..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-5.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-6.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-6.bcmap deleted file mode 100644 index e77d699ab6a1bfd1e3eab6db428222e108342aec..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-6.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-UCS2.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-UCS2.bcmap deleted file mode 100644 index 128a14107750da2939d920c3e0802798c36f2e18..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Japan1-UCS2.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-0.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-0.bcmap deleted file mode 100644 index cef1a9985191f53c4a8a35811d1caeecdd1a1820..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-0.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-1.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-1.bcmap deleted file mode 100644 index 11ffa36df8404ab970df2a24b2d80b1dc6348436..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-1.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-2.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-2.bcmap deleted file mode 100644 index 3172308c79d57147cdbe05930228043faa48ca54..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-2.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-UCS2.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-UCS2.bcmap deleted file mode 100644 index f3371c0cbd14c89a7d2b5a72e4e4f9cdc6d6017e..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Adobe-Korea1-UCS2.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/B5-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/B5-H.bcmap deleted file mode 100644 index beb4d228104cd985130e6eed7ccabdb63e94ce27..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/B5-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/B5-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/B5-V.bcmap deleted file mode 100644 index 2d4f87d5035f03485616d4986b6373fa0820d0af..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/B5-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/B5pc-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/B5pc-H.bcmap deleted file mode 100644 index ce0013167f852a873b639e301088c094d468a750..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/B5pc-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/B5pc-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/B5pc-V.bcmap deleted file mode 100644 index 73b99ff2fbca40e7ca5501f61e3f2f29c1fc1af6..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/B5pc-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/CNS-EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/CNS-EUC-H.bcmap deleted file mode 100644 index 61d1d0cb001dd484630e52eb7e47eaabbdee62cd..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/CNS-EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/CNS-EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/CNS-EUC-V.bcmap deleted file mode 100644 index 1a393a51e079d1b5e7898423463fac5e87170da2..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/CNS-EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/CNS1-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/CNS1-H.bcmap deleted file mode 100644 index f738e218ae2b4e9c33a1833a49fe20027e869aa1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/CNS1-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/CNS1-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/CNS1-V.bcmap deleted file mode 100644 index 9c3169f0d9a083b462427bf4e46a25296ebbd862..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/CNS1-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/CNS2-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/CNS2-H.bcmap deleted file mode 100644 index c89b3527fe57ad3b32061f36b73c756ead3fb071..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/CNS2-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/CNS2-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/CNS2-V.bcmap deleted file mode 100644 index 7588cec83e271feb04e3c7f3a6ee3a4c153f2052..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/cmaps/CNS2-V.bcmap +++ /dev/null @@ -1,3 +0,0 @@ -RCopyright 1990-2009 Adobe Systems Incorporated. -All rights reserved. -See ./LICENSECNS2-H \ No newline at end of file diff --git a/projects/web/public/pdfjs-dist/web/cmaps/ETHK-B5-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/ETHK-B5-H.bcmap deleted file mode 100644 index cb29415de4f5a669c1b47e34ab889b5fdee6e428..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/ETHK-B5-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/ETHK-B5-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/ETHK-B5-V.bcmap deleted file mode 100644 index f09aec6318dbec88491e3e488526882eaa930f37..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/ETHK-B5-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/ETen-B5-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/ETen-B5-H.bcmap deleted file mode 100644 index c2d77462d298cdb261f5e2eed5218fcba35cbe4e..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/ETen-B5-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/ETen-B5-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/ETen-B5-V.bcmap deleted file mode 100644 index 89bff159ec62cc86b7c4a3258ee0455cab10b76a..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/ETen-B5-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/ETenms-B5-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/ETenms-B5-H.bcmap deleted file mode 100644 index a7d69db5e32646c3fecf51bd03dc1a61c8189fae..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/cmaps/ETenms-B5-H.bcmap +++ /dev/null @@ -1,3 +0,0 @@ -RCopyright 1990-2009 Adobe Systems Incorporated. -All rights reserved. -See ./LICENSE ETen-B5-H` ^ \ No newline at end of file diff --git a/projects/web/public/pdfjs-dist/web/cmaps/ETenms-B5-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/ETenms-B5-V.bcmap deleted file mode 100644 index adc5d618d6912cb3a67e4745b63764120f93d17f..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/ETenms-B5-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/EUC-H.bcmap deleted file mode 100644 index e92ea5b3b99b1f20d31c9760481de0472e72685b..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/EUC-V.bcmap deleted file mode 100644 index 7a7c183228dfdc5c236b7914ca68298520ac60a1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Ext-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Ext-H.bcmap deleted file mode 100644 index 3b5cde44dbaf7f78c716c3705590ae28e9bed265..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Ext-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Ext-RKSJ-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Ext-RKSJ-H.bcmap deleted file mode 100644 index ea4d2d97b8bc1df2abebce0d4f8c58789f723eb1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Ext-RKSJ-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Ext-RKSJ-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Ext-RKSJ-V.bcmap deleted file mode 100644 index 3457c2770913963731993654c838df133deabbb3..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Ext-RKSJ-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Ext-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Ext-V.bcmap deleted file mode 100644 index 4999ca40412b66e87c56870c80cff32212483ee8..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Ext-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GB-EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GB-EUC-H.bcmap deleted file mode 100644 index e39908b9844939a3c6d6baccced5771b8c1b1b2d..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GB-EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GB-EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GB-EUC-V.bcmap deleted file mode 100644 index d5be5446aa40898742183202ce0624b8acee5234..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GB-EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GB-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GB-H.bcmap deleted file mode 100644 index 39189c54e363ebe2ea542addd6b629bdacd0e8e9..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/cmaps/GB-H.bcmap +++ /dev/null @@ -1,4 +0,0 @@ -RCopyright 1990-2009 Adobe Systems Incorporated. -All rights reserved. -See ./LICENSE!!]aX!!]`21> p z$]"Rd-U7* 4%+ Z {/%<9Kb1]." `],"] -"]h"]F"]$"]"]`"]>"]"]z"]X"]6"]"]r"]P"]."] "]j"]H"]&"]"]b"]@"]"]|"]Z"]8"]"]t"]R"]0"]"]l"]J"]("]"]d"]B"] "X~']W"]5"]"]q"]O"]-"] "]i"]G"]%"]"]a"]?"]"]{"]Y"]7"]"]s"]Q"]/"] "]k"]I"]'"]"]c"]A"]"]}"]["]9 \ No newline at end of file diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GB-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GB-V.bcmap deleted file mode 100644 index 310834512ffe49cbb7ca903abc2dc1aaa934e6f4..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GB-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBK-EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBK-EUC-H.bcmap deleted file mode 100644 index 05fff7e8254c995031783fb3b4892d58a6b176ac..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBK-EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBK-EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBK-EUC-V.bcmap deleted file mode 100644 index 0cdf6bed6d450473f92e691e9015e4028113607e..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBK-EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBK2K-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBK2K-H.bcmap deleted file mode 100644 index 46f6ba5967cdfb381f001eb1193f17b43d943962..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBK2K-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBK2K-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBK2K-V.bcmap deleted file mode 100644 index d9a9479843eda25fb0a8fd69fb302740813d925f..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBK2K-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBKp-EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBKp-EUC-H.bcmap deleted file mode 100644 index 5cb0af687ee20a10ecc367892ae49d7b1e74acd1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBKp-EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBKp-EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBKp-EUC-V.bcmap deleted file mode 100644 index bca93b8efbb18a13e15025ad41d23db8267d2577..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBKp-EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBT-EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBT-EUC-H.bcmap deleted file mode 100644 index 4b4e2d32294538b5093ed3870bb9de37abf21599..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBT-EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBT-EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBT-EUC-V.bcmap deleted file mode 100644 index 38f706699f395dcdad5c6ad93d1a9b6fe9f66c78..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBT-EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBT-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBT-H.bcmap deleted file mode 100644 index 8437ac33771536813228e3f9c1cb6c35af3acc72..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBT-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBT-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBT-V.bcmap deleted file mode 100644 index 697ab4a8e756204de9d089c8c136579973c9c0c6..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBT-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBTpc-EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBTpc-EUC-H.bcmap deleted file mode 100644 index f6e50e89363483070b25106b94f729ae38587d28..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBTpc-EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBTpc-EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBTpc-EUC-V.bcmap deleted file mode 100644 index 6c0d71a2d04473870c60dc59342400fe1b4ccc48..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBTpc-EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBpc-EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBpc-EUC-H.bcmap deleted file mode 100644 index c9edf67cf6d640607080ad2775c14760df77dd96..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBpc-EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/GBpc-EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/GBpc-EUC-V.bcmap deleted file mode 100644 index 31450c97f640ff40bd79677cd3e97f4485453d9b..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/GBpc-EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/H.bcmap deleted file mode 100644 index 7b24ea4629d0d4cc9f0cd5852edde324156ef0b1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKdla-B5-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKdla-B5-H.bcmap deleted file mode 100644 index 7d30c0500520d563d0e5891c8f4781c61ddcca5e..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKdla-B5-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKdla-B5-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKdla-B5-V.bcmap deleted file mode 100644 index 78946940d68cdd2ea1bec1230b1eb0b19b8d5deb..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKdla-B5-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKdlb-B5-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKdlb-B5-H.bcmap deleted file mode 100644 index d829a231015161e107123e211d4a78110daab6bf..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKdlb-B5-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKdlb-B5-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKdlb-B5-V.bcmap deleted file mode 100644 index 2b572b50a47f09a51c777efabcaf6a9e3faa26c2..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKdlb-B5-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKgccs-B5-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKgccs-B5-H.bcmap deleted file mode 100644 index 971a4f23f791f75d4e604ad717735ee55529eda5..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKgccs-B5-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKgccs-B5-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKgccs-B5-V.bcmap deleted file mode 100644 index d353ca256b54236a4acefafdbc08e5b719892014..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKgccs-B5-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKm314-B5-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKm314-B5-H.bcmap deleted file mode 100644 index 576dc01112bd7f28c30804661f546ece203c53d8..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKm314-B5-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKm314-B5-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKm314-B5-V.bcmap deleted file mode 100644 index 0e96d0e228e0608f77f035655140c6a235d4ea56..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKm314-B5-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKm471-B5-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKm471-B5-H.bcmap deleted file mode 100644 index 11d170c75ed8696f0705f9fb9f5afcf3b0aff4c9..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKm471-B5-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKm471-B5-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKm471-B5-V.bcmap deleted file mode 100644 index 54959bf9e776c990460f2582adee80d317062d20..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKm471-B5-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKscs-B5-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKscs-B5-H.bcmap deleted file mode 100644 index 6ef7857ad17cefc4ab714d209716002317c23baa..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKscs-B5-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/HKscs-B5-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/HKscs-B5-V.bcmap deleted file mode 100644 index 1fb2fa2a2ecdf5abd6b7cbf2cb5f2ee4f0b11fe2..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/HKscs-B5-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Hankaku.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Hankaku.bcmap deleted file mode 100644 index 4b8ec7fcef466bc4090dc13c8edb354cb94d0b67..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Hankaku.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Hiragana.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Hiragana.bcmap deleted file mode 100644 index 17e983e77264c62ee149d1c8ec576a23e8f90eda..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Hiragana.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSC-EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSC-EUC-H.bcmap deleted file mode 100644 index a45c65f008e7d6ff34edaf53af15ea471d4f6d90..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSC-EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSC-EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSC-EUC-V.bcmap deleted file mode 100644 index 0e7b21f0a612b1acc41c1b23ad0060da539eaf2b..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSC-EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSC-H.bcmap deleted file mode 100644 index b9b22b67879d4043c75b617a24f96b0bd47cf4ca..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSC-Johab-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSC-Johab-H.bcmap deleted file mode 100644 index 2531ffcf41acc01338f781c845c7f50f62fcc84a..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSC-Johab-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSC-Johab-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSC-Johab-V.bcmap deleted file mode 100644 index 367ceb226ab1e33624b30512716a3b65feb5a100..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSC-Johab-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSC-V.bcmap deleted file mode 100644 index 6ae2f0b6b7238adc67bd9231668d9853ea3c8e1e..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-H.bcmap deleted file mode 100644 index a8d4240e6adb3ac1db859085b769a0715be03c72..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-HW-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-HW-H.bcmap deleted file mode 100644 index 8b4ae18fd3efdbe020e4e1407d2f65125085a71a..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-HW-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-HW-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-HW-V.bcmap deleted file mode 100644 index b655dbcfb123ed06c7eeb87dfc96ecf6759363dd..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-HW-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-V.bcmap deleted file mode 100644 index 21f97f65b4a61adfa13f55d5a096ceab45eb485b..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSCms-UHC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSCpc-EUC-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSCpc-EUC-H.bcmap deleted file mode 100644 index e06f361eb6d429290806b9f9cd7a0aebce22be4d..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSCpc-EUC-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/KSCpc-EUC-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/KSCpc-EUC-V.bcmap deleted file mode 100644 index f3c9113fcf0b02e1deea8246bfd27408becc8401..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/KSCpc-EUC-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Katakana.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Katakana.bcmap deleted file mode 100644 index 524303c4f0c20e6cd19aa1d35805e98c2c05cb7c..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Katakana.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/LICENSE b/projects/web/public/pdfjs-dist/web/cmaps/LICENSE deleted file mode 100644 index b1ad168ad0dd09b578cafec31d2666049b4d8718..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/cmaps/LICENSE +++ /dev/null @@ -1,36 +0,0 @@ -%%Copyright: ----------------------------------------------------------- -%%Copyright: Copyright 1990-2009 Adobe Systems Incorporated. -%%Copyright: All rights reserved. -%%Copyright: -%%Copyright: Redistribution and use in source and binary forms, with or -%%Copyright: without modification, are permitted provided that the -%%Copyright: following conditions are met: -%%Copyright: -%%Copyright: Redistributions of source code must retain the above -%%Copyright: copyright notice, this list of conditions and the following -%%Copyright: disclaimer. -%%Copyright: -%%Copyright: Redistributions in binary form must reproduce the above -%%Copyright: copyright notice, this list of conditions and the following -%%Copyright: disclaimer in the documentation and/or other materials -%%Copyright: provided with the distribution. -%%Copyright: -%%Copyright: Neither the name of Adobe Systems Incorporated nor the names -%%Copyright: of its contributors may be used to endorse or promote -%%Copyright: products derived from this software without specific prior -%%Copyright: written permission. -%%Copyright: -%%Copyright: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -%%Copyright: CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -%%Copyright: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -%%Copyright: MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -%%Copyright: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -%%Copyright: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -%%Copyright: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -%%Copyright: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -%%Copyright: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -%%Copyright: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -%%Copyright: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -%%Copyright: OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -%%Copyright: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -%%Copyright: ----------------------------------------------------------- diff --git a/projects/web/public/pdfjs-dist/web/cmaps/NWP-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/NWP-H.bcmap deleted file mode 100644 index afc5e4b05ee6f4be4f17eb616742b59aee4c5ac1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/NWP-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/NWP-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/NWP-V.bcmap deleted file mode 100644 index bb5785e3278ab7a24b3080cf22ea0f609aab4595..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/NWP-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/RKSJ-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/RKSJ-H.bcmap deleted file mode 100644 index fb8d298e9bb8e090139bbc5e958f11a237672825..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/RKSJ-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/RKSJ-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/RKSJ-V.bcmap deleted file mode 100644 index a2555a6c048de98d68f534fbba18baf4b4311e50..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/RKSJ-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/Roman.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/Roman.bcmap deleted file mode 100644 index f896dcf1c7fb118fc491094edd6244e16856d586..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/Roman.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UCS2-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UCS2-H.bcmap deleted file mode 100644 index d5db27c5cf1f5b0e66e16f6314d042a4ef707222..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UCS2-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UCS2-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UCS2-V.bcmap deleted file mode 100644 index 1dc9b7a21bc59b6540d55b3d8933e5a6ba9f8947..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UCS2-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF16-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF16-H.bcmap deleted file mode 100644 index 961afefb66cb70ea2f10784029572e5f68ae4740..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF16-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF16-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF16-V.bcmap deleted file mode 100644 index df0cffe86b5e9f154c5ef6207120d6bd43706631..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF16-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF32-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF32-H.bcmap deleted file mode 100644 index 1ab18a14367cf31113eddf5ae15d9fb3549f39ab..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF32-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF32-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF32-V.bcmap deleted file mode 100644 index ad14662e25e7a4e3bd7f543c126ac24417bc3665..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF32-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF8-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF8-H.bcmap deleted file mode 100644 index 83c6bd7c4ff0abf4634765312b8a3026942d2b35..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF8-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF8-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF8-V.bcmap deleted file mode 100644 index 22a27e4ddbe26664c57f778a864b6872f6c2ba03..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniCNS-UTF8-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UCS2-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UCS2-H.bcmap deleted file mode 100644 index 5bd6228ce62ec10f00316b136663ed6b60ebf9e5..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UCS2-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UCS2-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UCS2-V.bcmap deleted file mode 100644 index 53c534b7fecfd84e465c8943fe3adf500a4444f4..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UCS2-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF16-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF16-H.bcmap deleted file mode 100644 index b95045b400a77419292cab245f9f66f6298dbb5d..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF16-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF16-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF16-V.bcmap deleted file mode 100644 index 51f023e0d609798e72d46bf41309e092d72ccb07..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF16-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF32-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF32-H.bcmap deleted file mode 100644 index f0dbd14f3795a40b23cbe5b826f776f4ea7cba4c..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF32-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF32-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF32-V.bcmap deleted file mode 100644 index ce9c30a98541e23244876fef9dc67c2639fdd746..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF32-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF8-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF8-H.bcmap deleted file mode 100644 index 982ca462b1b047c945d3b7b0123eb42dfd8d48cd..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF8-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF8-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF8-V.bcmap deleted file mode 100644 index f78020dd4028d56497c44b7afa94985f0d18f8ce..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniGB-UTF8-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-H.bcmap deleted file mode 100644 index 7daf56afabf65a4707d7bb06d829f56b247c9e80..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-HW-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-HW-H.bcmap deleted file mode 100644 index ac9975c585ede6958758980ade161f687d40d58b..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-HW-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-HW-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-HW-V.bcmap deleted file mode 100644 index 3da0a1c62f19f720590b54fc1de7b027af100945..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-HW-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-V.bcmap deleted file mode 100644 index c50b9ddfde9da7ebb2f67eba68d58fa2cdee902a..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UCS2-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF16-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF16-H.bcmap deleted file mode 100644 index 6761344639bcde069cf7133d52e127536dcdd037..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF16-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF16-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF16-V.bcmap deleted file mode 100644 index 70bf90c0efb66da2a7aa19a820d766cfe3ef3183..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF16-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF32-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF32-H.bcmap deleted file mode 100644 index 7a83d53ae70ca3d81cda827cc224ec8c5efa4f17..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF32-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF32-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF32-V.bcmap deleted file mode 100644 index 7a8713539491f51c52ba3a1525d181efd32c1f0f..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF32-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF8-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF8-H.bcmap deleted file mode 100644 index 9f0334cac7f3852b4d06dc9e5cf0f9646ba21a5e..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF8-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF8-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF8-V.bcmap deleted file mode 100644 index 808a94f0fd9c3b3cb0267e5cfe4dced2e65ecb1c..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS-UTF8-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF16-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF16-H.bcmap deleted file mode 100644 index d768bf811ffeb0d794b732a82940fa1442af499f..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF16-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF16-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF16-V.bcmap deleted file mode 100644 index 3d5bf6fb4ef94b452ed1ef0df926fc2bee55e973..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF16-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF32-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF32-H.bcmap deleted file mode 100644 index 09eee10d4fb4b9fe1e70a1ee56825a207ae8034a..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF32-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF32-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF32-V.bcmap deleted file mode 100644 index 6c546001331cf4f2f68563229f994b55730dfdb1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF32-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF8-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF8-H.bcmap deleted file mode 100644 index 1b1a64f50d204b03ef0c5575233687830a1b053a..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF8-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF8-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF8-V.bcmap deleted file mode 100644 index 994aa9ef9f50495a3ac558630b0234680be23c2f..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJIS2004-UTF8-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJISPro-UCS2-HW-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJISPro-UCS2-HW-V.bcmap deleted file mode 100644 index 643f921b65819c9e8c80a97c51fc68a89053bd51..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJISPro-UCS2-HW-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJISPro-UCS2-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJISPro-UCS2-V.bcmap deleted file mode 100644 index c148f67f5e9fe4a108519eeaace89e708a51f8f5..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJISPro-UCS2-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJISPro-UTF8-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJISPro-UTF8-V.bcmap deleted file mode 100644 index 1849d809a679e56414f4e18dce8ca3c41109e84e..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJISPro-UTF8-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJISX0213-UTF32-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJISX0213-UTF32-H.bcmap deleted file mode 100644 index a83a677c56df6f1ac395d2ba71e60a08b0985e97..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJISX0213-UTF32-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJISX0213-UTF32-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJISX0213-UTF32-V.bcmap deleted file mode 100644 index f527248ad547015ad8af1181e646da3b235de08f..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJISX0213-UTF32-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJISX02132004-UTF32-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJISX02132004-UTF32-H.bcmap deleted file mode 100644 index e1a988dc9e80be9a0803e22d021b1e81fdcc5b94..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJISX02132004-UTF32-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniJISX02132004-UTF32-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniJISX02132004-UTF32-V.bcmap deleted file mode 100644 index 47e054a961adb3d97caaa31c854d9b8ef4555bf9..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniJISX02132004-UTF32-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UCS2-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UCS2-H.bcmap deleted file mode 100644 index b5b94852a57b19bcb357a6cae2cae2e7910e05a1..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UCS2-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UCS2-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UCS2-V.bcmap deleted file mode 100644 index 026adcaad4c56cb1989bd31cbcf3ad21f3965a17..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UCS2-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF16-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF16-H.bcmap deleted file mode 100644 index fd4e66e81f3507b190fb2986a26a45c1c380e302..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF16-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF16-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF16-V.bcmap deleted file mode 100644 index 075efb7054901b1022af68e723647769cbe1d556..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF16-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF32-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF32-H.bcmap deleted file mode 100644 index 769d2142c03b10680800b3b6ae883e27fe04c5a2..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF32-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF32-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF32-V.bcmap deleted file mode 100644 index bdab208b69d287128195eccbd084c8cf4ca658c3..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF32-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF8-H.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF8-H.bcmap deleted file mode 100644 index 6ff8674af772af896d7d33c7addc37c57822f8a2..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF8-H.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF8-V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF8-V.bcmap deleted file mode 100644 index 8dfa76a58eb720dd1992c2cc9abf1dd4b39c5a66..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/UniKS-UTF8-V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/V.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/V.bcmap deleted file mode 100644 index fdec9906621904180f42bd5c91f377397fd6cf95..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/V.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/cmaps/WP-Symbol.bcmap b/projects/web/public/pdfjs-dist/web/cmaps/WP-Symbol.bcmap deleted file mode 100644 index 46729bbf30f3b2f176492d907fb8ca3f6a1e3026..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/cmaps/WP-Symbol.bcmap and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/custom.css b/projects/web/public/pdfjs-dist/web/custom.css deleted file mode 100644 index e593b142e83b3328b69f85b52be309e2228b3c80..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/custom.css +++ /dev/null @@ -1,20 +0,0 @@ -.tooltip { - position: absolute; - background-color: #333; - color: white; - padding: 5px 10px; - border-radius: 4px; - font-size: 14px; - z-index: 1000; - pointer-events: none; -} -.tooltip::before { - content: ''; - position: absolute; - top: -5px; - left: 50%; - transform: translateX(-50%); - border-left: 5px solid transparent; - border-right: 5px solid transparent; - border-bottom: 5px solid #333; -} diff --git a/projects/web/public/pdfjs-dist/web/custom.js b/projects/web/public/pdfjs-dist/web/custom.js deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/custom.js +++ /dev/null @@ -1 +0,0 @@ - diff --git a/projects/web/public/pdfjs-dist/web/images/altText_add.svg b/projects/web/public/pdfjs-dist/web/images/altText_add.svg deleted file mode 100644 index 3451b536ce7253b9341022f1fc2d7138f7840f79..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/altText_add.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/altText_done.svg b/projects/web/public/pdfjs-dist/web/images/altText_done.svg deleted file mode 100644 index f54924ebf92890ce3148ade2313f471cc385b710..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/altText_done.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-check.svg b/projects/web/public/pdfjs-dist/web/images/annotation-check.svg deleted file mode 100644 index 71cd16df576f158da70e8007c946cf25ad25e397..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-check.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-comment.svg b/projects/web/public/pdfjs-dist/web/images/annotation-comment.svg deleted file mode 100644 index 86f1f17249f0a2e49e54a6610fa928c91815c2d7..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-comment.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-help.svg b/projects/web/public/pdfjs-dist/web/images/annotation-help.svg deleted file mode 100644 index 00938fefe048b07fede7186d235179fe6ac2482c..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-help.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-insert.svg b/projects/web/public/pdfjs-dist/web/images/annotation-insert.svg deleted file mode 100644 index 519ef6826e56b178cbad9d91adf0b7a870696602..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-insert.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-key.svg b/projects/web/public/pdfjs-dist/web/images/annotation-key.svg deleted file mode 100644 index 8d09d5378d5be7d1350e08c3ece3d87e2e711a96..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-key.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-newparagraph.svg b/projects/web/public/pdfjs-dist/web/images/annotation-newparagraph.svg deleted file mode 100644 index 38d2497da9112076d3e88876d03aedbb1437a1a2..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-newparagraph.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-noicon.svg b/projects/web/public/pdfjs-dist/web/images/annotation-noicon.svg deleted file mode 100644 index c07d1080832bebea22ad1cf45fe3bac16ca90642..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-noicon.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-note.svg b/projects/web/public/pdfjs-dist/web/images/annotation-note.svg deleted file mode 100644 index 70173651c7e2a3d53492f234e7444c9d775b3b2c..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-note.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-paperclip.svg b/projects/web/public/pdfjs-dist/web/images/annotation-paperclip.svg deleted file mode 100644 index 2bed2250aee5b1e1aa4b884ae5eb984ad6aa1c91..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-paperclip.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-paragraph.svg b/projects/web/public/pdfjs-dist/web/images/annotation-paragraph.svg deleted file mode 100644 index 6ae5212b75d6855aa2cf7964de2b27650a6a2b80..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-paragraph.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/annotation-pushpin.svg b/projects/web/public/pdfjs-dist/web/images/annotation-pushpin.svg deleted file mode 100644 index 6e0896cf4ac0e9d2368ea4cfb11fe106b3855dbf..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/annotation-pushpin.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/cursor-editorFreeHighlight.svg b/projects/web/public/pdfjs-dist/web/images/cursor-editorFreeHighlight.svg deleted file mode 100644 index 513f6bdfdaa928912c1220fee3d95f2978c8cdf0..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/cursor-editorFreeHighlight.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/cursor-editorFreeText.svg b/projects/web/public/pdfjs-dist/web/images/cursor-editorFreeText.svg deleted file mode 100644 index de2838ef102b5b7666fa192bc7d620b9b0fffb3b..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/cursor-editorFreeText.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/cursor-editorInk.svg b/projects/web/public/pdfjs-dist/web/images/cursor-editorInk.svg deleted file mode 100644 index 1dadb5c0155e91dd36fdaf6a0e270627fd314f8a..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/cursor-editorInk.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/cursor-editorTextHighlight.svg b/projects/web/public/pdfjs-dist/web/images/cursor-editorTextHighlight.svg deleted file mode 100644 index 800340cb5b18aba3528973b7a9e846ddda450ba4..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/cursor-editorTextHighlight.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/editor-toolbar-delete.svg b/projects/web/public/pdfjs-dist/web/images/editor-toolbar-delete.svg deleted file mode 100644 index f84520d85a3406933e8f5d5d66f7c56c90a375ed..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/editor-toolbar-delete.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - \ No newline at end of file diff --git a/projects/web/public/pdfjs-dist/web/images/findbarButton-next.svg b/projects/web/public/pdfjs-dist/web/images/findbarButton-next.svg deleted file mode 100644 index 8cb39bec6f1a491aa6ee2fabf6c20a9432b2ee6f..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/findbarButton-next.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/findbarButton-previous.svg b/projects/web/public/pdfjs-dist/web/images/findbarButton-previous.svg deleted file mode 100644 index b610879dafcce529a81fcba83d34262cb6460612..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/findbarButton-previous.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/gv-toolbarButton-download.svg b/projects/web/public/pdfjs-dist/web/images/gv-toolbarButton-download.svg deleted file mode 100644 index d56cf3ce70e11286d2b8f33483db252e85a5d30e..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/gv-toolbarButton-download.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/layer-button-show.svg b/projects/web/public/pdfjs-dist/web/images/layer-button-show.svg deleted file mode 100644 index fc4582a966f39d22d81b4aedda5e4956e85cc2f6..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/layer-button-show.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/layer-button.svg b/projects/web/public/pdfjs-dist/web/images/layer-button.svg deleted file mode 100644 index 342230c72782b21fa0f1b5ccf611b6fe8753893d..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/layer-button.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/loading-icon.gif b/projects/web/public/pdfjs-dist/web/images/loading-icon.gif deleted file mode 100644 index 1c72ebb554be018511ae972c3f2361dff02dce02..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/images/loading-icon.gif and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/images/loading.svg b/projects/web/public/pdfjs-dist/web/images/loading.svg deleted file mode 100644 index 0a15ff6885de8c9e8423e98dd066840d56f3df19..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/loading.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-documentProperties.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-documentProperties.svg deleted file mode 100644 index dd3917b91d981d9b522c7c822cc2113d6a758f70..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-documentProperties.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-firstPage.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-firstPage.svg deleted file mode 100644 index f5c917f12a67772571b35880e90beecc58b30db4..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-firstPage.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-handTool.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-handTool.svg deleted file mode 100644 index b7073b598957c43288998b17fa5d424e4a782517..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-handTool.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-lastPage.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-lastPage.svg deleted file mode 100644 index c04f65079c59c6e966e51fc920b4d9c4db4db339..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-lastPage.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-rotateCcw.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-rotateCcw.svg deleted file mode 100644 index da73a1b16be7ec3f6b96ff3db884c8b6b853b3a9..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-rotateCcw.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-rotateCw.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-rotateCw.svg deleted file mode 100644 index c41ce7365eb4ca48558b71cca2d5d4e4a9b99a6f..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-rotateCw.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollHorizontal.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollHorizontal.svg deleted file mode 100644 index fb440b9465316f3511d680fad8aa08516a959797..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollHorizontal.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollPage.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollPage.svg deleted file mode 100644 index 64a9f500732d7072a9c5e771adaf5dfbba5cbdc8..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollPage.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollVertical.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollVertical.svg deleted file mode 100644 index dc7e80520072e254cb4cca66841ae4028ecef9da..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollVertical.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollWrapped.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollWrapped.svg deleted file mode 100644 index 75fe26bcfcc5149376058eea001acc44d3f319fb..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-scrollWrapped.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-selectTool.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-selectTool.svg deleted file mode 100644 index 94d51410dd43142275323c6fd3ae87859412f92a..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-selectTool.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-spreadEven.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-spreadEven.svg deleted file mode 100644 index ce201e33c0a5dd9815e1067a3c523bcea353d59a..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-spreadEven.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-spreadNone.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-spreadNone.svg deleted file mode 100644 index e8d487fa389e25b6aa35db299197d1c816ae5646..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-spreadNone.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-spreadOdd.svg b/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-spreadOdd.svg deleted file mode 100644 index 9211a427bfee600ad9c02cfe3c77bb108928c6f9..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/secondaryToolbarButton-spreadOdd.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-bookmark.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-bookmark.svg deleted file mode 100644 index c4c37c90582dd951e90804502902989cb4c8503e..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-bookmark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-download.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-download.svg deleted file mode 100644 index e2e850adf73d0cf2f499a3c33c9d4988676ad018..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-download.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorFreeText.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorFreeText.svg deleted file mode 100644 index 13a67bd9b6ab2106f5b4db06ce3a55263e2dbc4b..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorFreeText.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorHighlight.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorHighlight.svg deleted file mode 100644 index b3cd7fda9c960be975f276950a7b7c25966d0c8d..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorHighlight.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorInk.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorInk.svg deleted file mode 100644 index b579eec7ee58f1f9d43736ff1e671f542d942444..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorInk.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorStamp.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorStamp.svg deleted file mode 100644 index a1fef4922d97f073c59dfe409db557b2e968408a..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-editorStamp.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-menuArrow.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-menuArrow.svg deleted file mode 100644 index b04b9277a6f1e13cf37877e57266ba651a2c7d49..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-menuArrow.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-openFile.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-openFile.svg deleted file mode 100644 index e773781d607247c6807cd7fe17c7fb7fddd74119..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-openFile.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-pageDown.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-pageDown.svg deleted file mode 100644 index b04b9277a6f1e13cf37877e57266ba651a2c7d49..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-pageDown.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-pageUp.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-pageUp.svg deleted file mode 100644 index 44839da01fc528b5e43343a3c0d77a142ef631b1..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-pageUp.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-presentationMode.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-presentationMode.svg deleted file mode 100644 index 901d5672bcb34191c425679a1b35db14e0f5abd1..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-presentationMode.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-print.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-print.svg deleted file mode 100644 index 97a390474d93e6c34b17479f1781fc5266f72f0b..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-print.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-search.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-search.svg deleted file mode 100644 index 0cc7ae21ac16844b81e3861f0bd517fb2cb58a9b..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-search.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-secondaryToolbarToggle.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-secondaryToolbarToggle.svg deleted file mode 100644 index cace863728ade3088e92292458c28d9d0022c42f..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-secondaryToolbarToggle.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-sidebarToggle-open.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-sidebarToggle-open.svg deleted file mode 100644 index b57dab1ad99b64534dfcc4d7ac9139770b4862f6..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-sidebarToggle-open.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-sidebarToggle.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-sidebarToggle.svg deleted file mode 100644 index b2d250b6ee541426f6c4cfda82e5f4ff920bf605..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-sidebarToggle.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewAttachments.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewAttachments.svg deleted file mode 100644 index ab73f6e6e071e95c3c90b94b219c9c94a49e307f..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewAttachments.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewLayers.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewLayers.svg deleted file mode 100644 index 1d726682642bf968612180bfba62a2edd0882cfb..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewLayers.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewOutline.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewOutline.svg deleted file mode 100644 index 7ed1bd97f2f5b57aef1e73046e1df0d2b3ccf6ef..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewOutline.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewThumbnail.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewThumbnail.svg deleted file mode 100644 index 040d123266a20cc089b2af50a0a39b9760e2d493..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-viewThumbnail.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-zoomIn.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-zoomIn.svg deleted file mode 100644 index 30ec51a2ffdff5fc1f7bb6088bd9fa492c428a09..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-zoomIn.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/toolbarButton-zoomOut.svg b/projects/web/public/pdfjs-dist/web/images/toolbarButton-zoomOut.svg deleted file mode 100644 index f273b5995cdb234502a123a7e384af651f1e47bd..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/toolbarButton-zoomOut.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/projects/web/public/pdfjs-dist/web/images/treeitem-collapsed.svg b/projects/web/public/pdfjs-dist/web/images/treeitem-collapsed.svg deleted file mode 100644 index 831cddfc869518822c6d70e289ea5fe4b175cb94..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/treeitem-collapsed.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/projects/web/public/pdfjs-dist/web/images/treeitem-expanded.svg b/projects/web/public/pdfjs-dist/web/images/treeitem-expanded.svg deleted file mode 100644 index 2d45f0c8d18dd66c1cbc6756b97299051b9886e2..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/images/treeitem-expanded.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/projects/web/public/pdfjs-dist/web/layer.js b/projects/web/public/pdfjs-dist/web/layer.js deleted file mode 100644 index fb35621938f9976a170dd0a80b15d9ec2c52cc21..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/layer.js +++ /dev/null @@ -1,333 +0,0 @@ -var LAYER_CHANGE_ACTIVE_CLASS = 'layerChange-active' - -// 获取 button 元素 -var layerChangeButton = document.getElementById('layerChange'); - -var isLayerChangeButtonActive = () => { - return layerChangeButton.classList.contains(LAYER_CHANGE_ACTIVE_CLASS) -} - -var getLocale = () => { - console.log('test-iframe-locale', localStorage.getItem('umi-locale') ,localStorage.getItem('locale') , '') - return localStorage.getItem('umi_locale') || localStorage.getItem('locale') || 'zh-CN'; -} - -// 添加tooltip -function createHoverTooltip(element, tooltipText, id, options = {}) { - const tooltip = document.createElement('div'); - tooltip.className = `tooltip-${id} tooltip`; - tooltip.style.display = 'none'; - tooltip.style.zIndex = '999'; - document.body.appendChild(tooltip); - - const defaultOptions = { - offset: { y: 10 }, - delay: 200, - duration: 200, - }; - - const mergedOptions = { ...defaultOptions, ...options }; - - let tooltipTimer; - - function positionTooltip() { - const rect = element.getBoundingClientRect(); - const tooltipRect = tooltip.getBoundingClientRect(); - const left = rect.left + (rect.width - tooltipRect.width) / 2; - const top = rect.bottom + mergedOptions.offset.y; - - tooltip.style.left = `${left}px`; - tooltip.style.top = `${top}px`; - } - - function showTooltip() { - tooltip.textContent = tooltipText; - tooltip.style.display = 'block'; - tooltip.style.opacity = '0'; - tooltip.style.transition = `opacity ${mergedOptions.duration}ms`; - positionTooltip(); - setTimeout(() => { - tooltip.style.opacity = '1'; - }, 10); - } - - function hideTooltip() { - tooltip.style.opacity = '0'; - setTimeout(() => { - tooltip.style.display = 'none'; - }, mergedOptions.duration); - } - - element.addEventListener('mouseenter', () => { - tooltipTimer = setTimeout(showTooltip, mergedOptions.delay); - }); - - element.addEventListener('mouseleave', () => { - clearTimeout(tooltipTimer); - hideTooltip(); - }); - - window.addEventListener('resize', positionTooltip); - window.addEventListener('scroll', positionTooltip); - - // 返回对象,包含 updateTooltipText 函数 - return { - updateTooltipText: (newText) => { - tooltipText = newText; - positionTooltip() - if (tooltip.style.display !== 'none') { - showTooltip(); - tooltipText = newText; - } - } - }; -} - -const tooltipLayer = createHoverTooltip(layerChangeButton, getLocale() === 'zh-CN' ? '隐藏识别结果': 'Hide recognition results', 'layerChange', { offset: { y: 22 } }); - - - -window.addEventListener('storage', function(event) { - // 检查事件是否与监听的键相关 - if (event.key === 'umi_locale'|| event.key === 'locale') { - const text = isLayerChangeButtonActive() ? event?.newValue === 'zh-CN' ? '隐藏识别结果': 'Hide recognition results': getLocale() === 'zh-CN' ? '显示识别结果': 'Display recognition results' - tooltipLayer?.updateTooltipText(text) - } -}); - - -// 添加点击事件监听器 -layerChangeButton.addEventListener('click', function() { - // 检查当前 button 的选中状态 - if (isLayerChangeButtonActive()) { - // 如果已经处于选中状态,则移除选中状态的 class - const annotationLayerList = document.getElementsByClassName('annotationLayer') - Array?.from(annotationLayerList)?.forEach(element => { - var extractLayer = element.querySelector('#extractLayer'); - if(extractLayer) { - extractLayer.style.opacity = 0 - } - }); - console.log('test-dd', annotationLayerList, typeof annotationLayerList) - tooltipLayer?.updateTooltipText( getLocale() === 'zh-CN' ? '显示识别结果': 'Display recognition results') - this.classList.remove(LAYER_CHANGE_ACTIVE_CLASS); - } else { - // 如果未处于选中状态,则添加选中状态的 class - this.classList.add(LAYER_CHANGE_ACTIVE_CLASS); - tooltipLayer?.updateTooltipText(getLocale() === 'zh-CN' ? '隐藏识别结果': 'Hide recognition results') - const scale = 0.943 / 0.7071 * window?.PDFViewerApplication?.pdfViewer?._currentScale || 1 - window.renderExtractLayer(window.pdfExtractData, Number(0), scale) - - const annotationLayerList = document.getElementsByClassName('annotationLayer') - Array?.from(annotationLayerList)?.forEach(element => { - var extractLayer = element.querySelector('#extractLayer'); - if(extractLayer) { - extractLayer.style.opacity = 1 - } - }) - } -}); - - -// 获取显示消息的元素 -const messageDisplay = document.getElementById('messageDisplay'); -function removeDuplicates(arr) { - return [...new Set(arr)]; -} - -window.addEventListener('error', function(event) { - if (event.target && event.target.tagName === 'SCRIPT') { - console.error("Script error detected: ", event); - } -}, true); - -// 添加消息监听器 -window.addEventListener('message', function(event) { - const receivedMessage = event.data; - const data = receivedMessage?.data - const type = receivedMessage?.type - function setHasRenderAnimatedPage (num) { - if(!window.hasRenderAnimatedPage ) { - window.hasRenderAnimatedPage = [] - } - if( typeof window.hasRenderAnimatedPage === 'object'){ - window.hasRenderAnimatedPage = removeDuplicates([...window.hasRenderAnimatedPage, num]) - } - } - let animatingBox = new Map() - function renderExtractLayer(data, pageNum, scale) { - // 判断按钮是开的还是关的 - if(!isLayerChangeButtonActive()) return; - - const bboxes = data?.[pageNum]?.bboxes || [] - - function drawBoxes(boxes, scale) { - if(animatingBox.get(pageNum)) return - - // const annotationLayer = document.querySelector('.canvasWrapper'); - const pageLayer = document.getElementsByClassName('page')?.[pageNum] - const annotationLayer = pageLayer.querySelectorAll('.annotationLayer')?.[0]; - // annotationLayer.removeAttribute('hidden'); - if(!annotationLayer) { - // console.error('error: annotationLayer has not been rendered') - return - } - const extractLayer = annotationLayer.querySelector('#extractLayer'); - - // 因为pdfjs只会缓存8页的内容,所以采用每次切换移除重建canvas的方式 - if (extractLayer) { - extractLayer?.remove(); - } - annotationLayer.style.width = '100%'; - annotationLayer.style.height = '100%' - annotationLayer.style.position = 'absolute'; - annotationLayer.style.top = 0; - annotationLayer.style.left = 0; - const computedLayer = document.querySelector('.canvasWrapper'); - const canvas = document.createElement('canvas'); - canvas.id = 'extractLayer' - const w = pageLayer?.offsetWidth - 18; - const h = pageLayer?.offsetHeight - 18; - canvas.width = true ? `${w}` : '100%'; - canvas.height = true ? `${h}`: '100%'; - canvas.style.width = true ? `${w}px` : '100%'; - canvas.style.height = true ? `${h}px`: '100%'; - canvas.style.position = 'absolute'; - canvas.style.top = 0; - canvas.style.left = 0; - annotationLayer.append(canvas) - const ctx = canvas.getContext('2d'); - - // 移除之前的画布内容 - // ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.save(); - // console.log('renderExtractLayer: draw boxes') - - function drawPartialRect(ctx, box, progress, scale) { - const [x, y, x2, y2]= box.bbox.map((i) => (i * scale)); - const width = x2 - x; - const height = y2 - y; - const color = box?.color?.line - const fillColor = box?.color?.fill - ctx.beginPath(); - ctx.strokeStyle = color; - - // 左边竖线 - ctx.moveTo(x, y); - ctx.lineTo(x, y2); - - // 上边横线 - ctx.moveTo(x, y); - ctx.lineTo(x + width * (progress < 0 ? 0: progress), y); - - // 右边竖线 (只在进度完成时绘制) - if (progress === 1) { - ctx.moveTo(x2, y); - ctx.lineTo(x2, y2); - ctx.fillStyle = fillColor; - ctx.fillRect(x, y, width, height); - } - - // 下边横线 - ctx.moveTo(x, y2); - ctx.lineTo(x + width * (progress < 0 ? 0: progress), y2); - - ctx.stroke(); - } - - function fillRect(ctx, box, scale) { - const [x, y, x2, y2]= box.bbox.map((i) => (i * scale)); - const width = x2 - x; - const height = y2 - y; - const color = box?.color?.fill - - ctx.fillStyle = color; - ctx.fillRect(x, y, width, height); - } - - function animateBox(ctx, box, duration = 1000) { - const startTime = performance.now(); - - function animate(currentTime) { - const elapsedTime = currentTime - startTime; - const progress = Math.min(elapsedTime / duration, 1); - // ctx.clearRect(...box.bbox); // 清除之前的绘制 - drawPartialRect(ctx, box, progress, scale); - - if (progress < 1) { - requestAnimationFrame(animate); - } - } - - requestAnimationFrame(animate); - } - - async function animateAllBoxes() { - // const [index, value] of array.entries() - for (const [index, box] of boxes?.entries()) { - await animateBox(ctx, box, 600); // 动画时间改为500ms - await new Promise(resolve => setTimeout(resolve, 200)); // 每个框之间的延迟也减少到100ms - } - - // 所有线框动画完成后,一次性填充所有矩形 - // ctx.clearRect(...box.bbox); // 清除之前的绘制 - // boxes.forEach(box => fillRect(ctx, box, scale)); - console.log("test-animate All animations completed and boxes filled"); - animatingBox.set(pageNum, false) - } - - boxes.forEach((box, index) => { - drawPartialRect(ctx, box, 1, scale); - }); - - - canvas.style.width = false ? `${w}px` : '100%'; - canvas.style.height = false ? `${h}px`: '100%'; - ctx.restore(); - } - !!bboxes?.length&&drawBoxes(bboxes, scale); - - } - - // init extractLayer data - if(type === 'initExtractLayerData') { - const scale = 0.943 / 0.7071 * window?.PDFViewerApplication?.pdfViewer?._currentScale || 1 - const currentPageNumber = window?.PDFViewerApplication?.pdfViewer?._currentPageNumber || 1 - window.pdfExtractData = data; - window.renderExtractLayer = renderExtractLayer - // window.renderExtractLayer(window.pdfExtractData, currentPageNumber - 1, scale) - // use the picture view rather than outlined view - window.renderExtractLayer(window.pdfExtractData, Number(0), scale) - window?.PDFViewerApplication?.pdfSidebar?.switchView(1, false) - } - - if(type === 'pageChange') { - if(window.renderExtractLayer - && window.pdfExtractData - ) { - const scale = 0.943 / 0.7071 * window?.PDFViewerApplication?.pdfViewer?._currentScale || 1 - const currentPageNumber = data || 0 - window.renderExtractLayer(window.pdfExtractData, Number(0), scale) - window.renderExtractLayer(window.pdfExtractData, Number(data), scale) - } else if(!window.pdfExtractData) { - // console.error('extract pdf render data has not been initialized') - } - } - - if( type === 'title') { - const odlPdfTitle = document.getElementById("odl-pdf-title"); - odlPdfTitle.innerText = data; - } - - if( type === 'setPage') { - window?.PDFViewerApplication?.eventBus?.dispatch("pagenumberchanged", { - value: data - }) - } - - if( type === '') { - - } -}); - - diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitDingbats.pfb b/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitDingbats.pfb deleted file mode 100644 index 30d52963e281dcd7e6dd70555340fc987d3568ef..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitDingbats.pfb and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixed.pfb b/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixed.pfb deleted file mode 100644 index f12dcbce52babb40fb61765aa46ddf47e3846511..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixed.pfb and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixedBold.pfb b/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixedBold.pfb deleted file mode 100644 index cf8e24aee5962ebcf7e4d58d932cc3321f3cdd38..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixedBold.pfb and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixedBoldItalic.pfb b/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixedBoldItalic.pfb deleted file mode 100644 index d2880017c25716417f837a1c26044a0342fa3f9a..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixedBoldItalic.pfb and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixedItalic.pfb b/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixedItalic.pfb deleted file mode 100644 index d71697d4b638737a5545dd0cb28cba8f613e4eec..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitFixedItalic.pfb and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerif.pfb b/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerif.pfb deleted file mode 100644 index 3fa682efbb4b1d1941194a5dd8b78f39b33b72b0..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerif.pfb and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerifBold.pfb b/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerifBold.pfb deleted file mode 100644 index ff7c6ddecf6b689d93823c4c2a8c41e6e058de46..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerifBold.pfb and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerifBoldItalic.pfb b/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerifBoldItalic.pfb deleted file mode 100644 index 460231fb88a0083e577ed534760307d7779fd82f..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerifBoldItalic.pfb and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerifItalic.pfb b/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerifItalic.pfb deleted file mode 100644 index d03a7c781e1a2b91481103dc3227a6bdca4a461c..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSerifItalic.pfb and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSymbol.pfb b/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSymbol.pfb deleted file mode 100644 index c8f9bca78c2f89ce40dff0afe6cdd7068061b3e6..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/FoxitSymbol.pfb and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/LICENSE_FOXIT b/projects/web/public/pdfjs-dist/web/standard_fonts/LICENSE_FOXIT deleted file mode 100644 index 8b4ed6dddf22b2fcc9f7f520cd23613b49307fa0..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/standard_fonts/LICENSE_FOXIT +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/LICENSE_LIBERATION b/projects/web/public/pdfjs-dist/web/standard_fonts/LICENSE_LIBERATION deleted file mode 100644 index aba73e8a403084a93a245ca00e4a0db007886e0a..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/standard_fonts/LICENSE_LIBERATION +++ /dev/null @@ -1,102 +0,0 @@ -Digitized data copyright (c) 2010 Google Corporation - with Reserved Font Arimo, Tinos and Cousine. -Copyright (c) 2012 Red Hat, Inc. - with Reserved Font Name Liberation. - -This Font Software is licensed under the SIL Open Font License, -Version 1.1. - -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 - -PREAMBLE The goals of the Open Font License (OFL) are to stimulate -worldwide development of collaborative font projects, to support the font -creation efforts of academic and linguistic communities, and to provide -a free and open framework in which fonts may be shared and improved in -partnership with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. -The fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply to -any document created using the fonts or their derivatives. - - - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. -This may include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components -as distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting ? in part or in whole ? -any of the components of the Original Version, by changing formats or -by porting the Font Software to a new environment. - -"Author" refers to any designer, engineer, programmer, technical writer -or other person who contributed to the Font Software. - - -PERMISSION & CONDITIONS - -Permission is hereby granted, free of charge, to any person obtaining a -copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components,in - Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, - redistributed and/or sold with any software, provided that each copy - contains the above copyright notice and this license. These can be - included either as stand-alone text files, human-readable headers or - in the appropriate machine-readable metadata fields within text or - binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font - Name(s) unless explicit written permission is granted by the - corresponding Copyright Holder. This restriction only applies to the - primary font name as presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font - Software shall not be used to promote, endorse or advertise any - Modified Version, except to acknowledge the contribution(s) of the - Copyright Holder(s) and the Author(s) or with their explicit written - permission. - -5) The Font Software, modified or unmodified, in part or in whole, must - be distributed entirely under this license, and must not be distributed - under any other license. The requirement for fonts to remain under - this license does not apply to any document created using the Font - Software. - - - -TERMINATION -This license becomes null and void if any of the above conditions are not met. - - - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER -DEALINGS IN THE FONT SOFTWARE. - diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-Bold.ttf b/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-Bold.ttf deleted file mode 100644 index ee2371540417ffbc652745b059effa260430179f..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-Bold.ttf and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-BoldItalic.ttf b/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-BoldItalic.ttf deleted file mode 100644 index 42b5717ddb92dc6e85edc72fb5c3a798b380902e..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-BoldItalic.ttf and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-Italic.ttf b/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-Italic.ttf deleted file mode 100644 index 0cf61263494608cbf1fccecce606bc01a247d1e4..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-Italic.ttf and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-Regular.ttf b/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-Regular.ttf deleted file mode 100644 index 366d1489cdde3523e488ed1ee85583618fb0c120..0000000000000000000000000000000000000000 Binary files a/projects/web/public/pdfjs-dist/web/standard_fonts/LiberationSans-Regular.ttf and /dev/null differ diff --git a/projects/web/public/pdfjs-dist/web/viewer.css b/projects/web/public/pdfjs-dist/web/viewer.css deleted file mode 100644 index 92ac363543966dfb482ec97037e3bb2088ba067c..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/viewer.css +++ /dev/null @@ -1,4575 +0,0 @@ -/* Copyright 2014 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* custom */ - .tooltip { - position: absolute; - background-color: #333; - color: white; - padding: 5px 10px; - border-radius: 4px; - font-size: 14px; - z-index: 100; - pointer-events: none; -} -.tooltip::before { - content: ''; - position: absolute; - top: -5px; - left: 50%; - transform: translateX(-50%); - border-left: 5px solid transparent; - border-right: 5px solid transparent; - border-bottom: 5px solid #333; -} - - -.textLayer{ - position:absolute; - text-align:initial; - inset:0; - overflow:hidden; - opacity:1; - line-height:1; - -webkit-text-size-adjust:none; - -moz-text-size-adjust:none; - text-size-adjust:none; - forced-color-adjust:none; - transform-origin:0 0; - caret-color:CanvasText; -} - -.textLayer.highlighting{ - touch-action:none; - } - -.textLayer :is(span, br){ - color:transparent; - /* color: rgba(18, 19, 22, 80%); */ - position:absolute; - white-space:pre; - cursor:text; - transform-origin:0% 0%; - z-index: 999; - } - -.textLayer span.markedContent{ - top:0; - height:0; - } - -.textLayer .highlight{ - --highlight-bg-color:rgb(180 0 170 / 0.25); - --highlight-selected-bg-color:rgb(0 100 0 / 0.25); - --highlight-backdrop-filter:none; - --highlight-selected-backdrop-filter:none; - - margin:-1px; - padding:1px; - background-color:var(--highlight-bg-color); - -webkit-backdrop-filter:var(--highlight-backdrop-filter); - backdrop-filter:var(--highlight-backdrop-filter); - border-radius:4px; - } - -@media screen and (forced-colors: active){ - -.textLayer .highlight{ - --highlight-bg-color:transparent; - --highlight-selected-bg-color:transparent; - --highlight-backdrop-filter:var(--hcm-highlight-filter); - --highlight-selected-backdrop-filter:var( - --hcm-highlight-selected-filter - ); - } - } - -.textLayer .highlight.appended{ - position:initial; - } - -.textLayer .highlight.begin{ - border-radius:4px 0 0 4px; - } - -.textLayer .highlight.end{ - border-radius:0 4px 4px 0; - } - -.textLayer .highlight.middle{ - border-radius:0; - } - -.textLayer .highlight.selected{ - background-color:var(--highlight-selected-bg-color); - -webkit-backdrop-filter:var(--highlight-selected-backdrop-filter); - backdrop-filter:var(--highlight-selected-backdrop-filter); - } - -.textLayer ::-moz-selection{ - background:rgba(0 0 255 / 0.25); - background:color-mix(in srgb, AccentColor, transparent 75%); - } - -.textLayer ::selection{ - background:rgba(0 0 255 / 0.25); - background:color-mix(in srgb, AccentColor, transparent 75%); - } - -.textLayer br::-moz-selection{ - background:transparent; - } - -.textLayer br::selection{ - background:transparent; - } - -.textLayer .endOfContent{ - display:block; - position:absolute; - inset:100% 0 0; - z-index:-1; - cursor:default; - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; - } - -.textLayer .endOfContent.active{ - top:0; - } - -.annotationLayer{ - --annotation-unfocused-field-background:url("data:image/svg+xml;charset=UTF-8,"); - --input-focus-border-color:Highlight; - --input-focus-outline:1px solid Canvas; - --input-unfocused-border-color:transparent; - --input-disabled-border-color:transparent; - --input-hover-border-color:black; - --link-outline:none; - - position:absolute; - top:0; - left:0; - pointer-events:none; - transform-origin:0 0; -} - -@media screen and (forced-colors: active){ - -.annotationLayer{ - --input-focus-border-color:CanvasText; - --input-unfocused-border-color:ActiveText; - --input-disabled-border-color:GrayText; - --input-hover-border-color:Highlight; - --link-outline:1.5px solid LinkText; -} - - .annotationLayer .textWidgetAnnotation :is(input, textarea):required, .annotationLayer .choiceWidgetAnnotation select:required, .annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:required{ - outline:1.5px solid selectedItem; - } - - .annotationLayer .linkAnnotation{ - outline:var(--link-outline); - } - - .annotationLayer .linkAnnotation:hover{ - -webkit-backdrop-filter:var(--hcm-highlight-filter); - backdrop-filter:var(--hcm-highlight-filter); - } - - .annotationLayer .linkAnnotation > a:hover{ - opacity:0 !important; - background:none !important; - box-shadow:none; - } - - .annotationLayer .popupAnnotation .popup{ - outline:calc(1.5px * var(--scale-factor)) solid CanvasText !important; - background-color:ButtonFace !important; - color:ButtonText !important; - } - - .annotationLayer .highlightArea:hover::after{ - position:absolute; - top:0; - left:0; - width:100%; - height:100%; - -webkit-backdrop-filter:var(--hcm-highlight-filter); - backdrop-filter:var(--hcm-highlight-filter); - content:""; - pointer-events:none; - } - - .annotationLayer .popupAnnotation.focused .popup{ - outline:calc(3px * var(--scale-factor)) solid Highlight !important; - } - } - -.annotationLayer[data-main-rotation="90"] .norotate{ - transform:rotate(270deg) translateX(-100%); - } - -.annotationLayer[data-main-rotation="180"] .norotate{ - transform:rotate(180deg) translate(-100%, -100%); - } - -.annotationLayer[data-main-rotation="270"] .norotate{ - transform:rotate(90deg) translateY(-100%); - } - -.annotationLayer.disabled section, - .annotationLayer.disabled .popup{ - pointer-events:none; - } - -.annotationLayer .annotationContent{ - position:absolute; - width:100%; - height:100%; - pointer-events:none; - } - -.annotationLayer .annotationContent.freetext{ - background:transparent; - border:none; - inset:0; - overflow:visible; - white-space:nowrap; - font:10px sans-serif; - line-height:1.35; - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; - } - -.annotationLayer section{ - position:absolute; - text-align:initial; - pointer-events:auto; - box-sizing:border-box; - transform-origin:0 0; - } - -.annotationLayer section:has(div.annotationContent) canvas.annotationContent{ - display:none; - } - -.annotationLayer :is(.linkAnnotation, .buttonWidgetAnnotation.pushButton) > a{ - position:absolute; - font-size:1em; - top:0; - left:0; - width:100%; - height:100%; - } - -.annotationLayer :is(.linkAnnotation, .buttonWidgetAnnotation.pushButton):not(.hasBorder) - > a:hover{ - opacity:0.2; - background-color:rgb(255 255 0); - box-shadow:0 2px 10px rgb(255 255 0); - } - -.annotationLayer .linkAnnotation.hasBorder:hover{ - background-color:rgb(255 255 0 / 0.2); - } - -.annotationLayer .hasBorder{ - background-size:100% 100%; - } - -.annotationLayer .textAnnotation img{ - position:absolute; - cursor:pointer; - width:100%; - height:100%; - top:0; - left:0; - } - -.annotationLayer .textWidgetAnnotation :is(input, textarea), .annotationLayer .choiceWidgetAnnotation select, .annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input{ - background-image:var(--annotation-unfocused-field-background); - border:2px solid var(--input-unfocused-border-color); - box-sizing:border-box; - font:calc(9px * var(--scale-factor)) sans-serif; - height:100%; - margin:0; - vertical-align:top; - width:100%; - } - -.annotationLayer .textWidgetAnnotation :is(input, textarea):required, .annotationLayer .choiceWidgetAnnotation select:required, .annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:required{ - outline:1.5px solid red; - } - -.annotationLayer .choiceWidgetAnnotation select option{ - padding:0; - } - -.annotationLayer .buttonWidgetAnnotation.radioButton input{ - border-radius:50%; - } - -.annotationLayer .textWidgetAnnotation textarea{ - resize:none; - } - -.annotationLayer .textWidgetAnnotation [disabled]:is(input, textarea), .annotationLayer .choiceWidgetAnnotation select[disabled], .annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input[disabled]{ - background:none; - border:2px solid var(--input-disabled-border-color); - cursor:not-allowed; - } - -.annotationLayer .textWidgetAnnotation :is(input, textarea):hover, .annotationLayer .choiceWidgetAnnotation select:hover, .annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input:hover{ - border:2px solid var(--input-hover-border-color); - } - -.annotationLayer .textWidgetAnnotation :is(input, textarea):hover, .annotationLayer .choiceWidgetAnnotation select:hover, .annotationLayer .buttonWidgetAnnotation.checkBox input:hover{ - border-radius:2px; - } - -.annotationLayer .textWidgetAnnotation :is(input, textarea):focus, .annotationLayer .choiceWidgetAnnotation select:focus{ - background:none; - border:2px solid var(--input-focus-border-color); - border-radius:2px; - outline:var(--input-focus-outline); - } - -.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) :focus{ - background-image:none; - background-color:transparent; - } - -.annotationLayer .buttonWidgetAnnotation.checkBox :focus{ - border:2px solid var(--input-focus-border-color); - border-radius:2px; - outline:var(--input-focus-outline); - } - -.annotationLayer .buttonWidgetAnnotation.radioButton :focus{ - border:2px solid var(--input-focus-border-color); - outline:var(--input-focus-outline); - } - -.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::before, - .annotationLayer .buttonWidgetAnnotation.checkBox input:checked::after, - .annotationLayer .buttonWidgetAnnotation.radioButton input:checked::before{ - background-color:CanvasText; - content:""; - display:block; - position:absolute; - } - -.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::before, - .annotationLayer .buttonWidgetAnnotation.checkBox input:checked::after{ - height:80%; - left:45%; - width:1px; - } - -.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::before{ - transform:rotate(45deg); - } - -.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::after{ - transform:rotate(-45deg); - } - -.annotationLayer .buttonWidgetAnnotation.radioButton input:checked::before{ - border-radius:50%; - height:50%; - left:25%; - top:25%; - width:50%; - } - -.annotationLayer .textWidgetAnnotation input.comb{ - font-family:monospace; - padding-left:2px; - padding-right:0; - } - -.annotationLayer .textWidgetAnnotation input.comb:focus{ - width:103%; - } - -.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input{ - -webkit-appearance:none; - -moz-appearance:none; - appearance:none; - } - -.annotationLayer .fileAttachmentAnnotation .popupTriggerArea{ - height:100%; - width:100%; - } - -.annotationLayer .popupAnnotation{ - position:absolute; - font-size:calc(9px * var(--scale-factor)); - pointer-events:none; - width:-moz-max-content; - width:max-content; - max-width:45%; - height:auto; - } - -.annotationLayer .popup{ - background-color:rgb(255 255 153); - box-shadow:0 calc(2px * var(--scale-factor)) calc(5px * var(--scale-factor)) rgb(136 136 136); - border-radius:calc(2px * var(--scale-factor)); - outline:1.5px solid rgb(255 255 74); - padding:calc(6px * var(--scale-factor)); - cursor:pointer; - font:message-box; - white-space:normal; - word-wrap:break-word; - pointer-events:auto; - } - -.annotationLayer .popupAnnotation.focused .popup{ - outline-width:3px; - } - -.annotationLayer .popup *{ - font-size:calc(9px * var(--scale-factor)); - } - -.annotationLayer .popup > .header{ - display:inline-block; - } - -.annotationLayer .popup > .header h1{ - display:inline; - } - -.annotationLayer .popup > .header .popupDate{ - display:inline-block; - margin-left:calc(5px * var(--scale-factor)); - width:-moz-fit-content; - width:fit-content; - } - -.annotationLayer .popupContent{ - border-top:1px solid rgb(51 51 51); - margin-top:calc(2px * var(--scale-factor)); - padding-top:calc(2px * var(--scale-factor)); - } - -.annotationLayer .richText > *{ - white-space:pre-wrap; - font-size:calc(9px * var(--scale-factor)); - } - -.annotationLayer .popupTriggerArea{ - cursor:pointer; - } - -.annotationLayer section svg{ - position:absolute; - width:100%; - height:100%; - top:0; - left:0; - } - -.annotationLayer .annotationTextContent{ - position:absolute; - width:100%; - height:100%; - opacity:0; - color:transparent; - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; - pointer-events:none; - } - -.annotationLayer .annotationTextContent span{ - width:100%; - display:inline-block; - } - -.annotationLayer svg.quadrilateralsContainer{ - contain:strict; - width:0; - height:0; - position:absolute; - top:0; - left:0; - z-index:-1; - } - -:root{ - --xfa-unfocused-field-background:url("data:image/svg+xml;charset=UTF-8,"); - --xfa-focus-outline:auto; -} - -@media screen and (forced-colors: active){ - :root{ - --xfa-focus-outline:2px solid CanvasText; - } - .xfaLayer *:required{ - outline:1.5px solid selectedItem; - } -} - -.xfaLayer{ - background-color:transparent; -} - -.xfaLayer .highlight{ - margin:-1px; - padding:1px; - background-color:rgb(239 203 237); - border-radius:4px; -} - -.xfaLayer .highlight.appended{ - position:initial; -} - -.xfaLayer .highlight.begin{ - border-radius:4px 0 0 4px; -} - -.xfaLayer .highlight.end{ - border-radius:0 4px 4px 0; -} - -.xfaLayer .highlight.middle{ - border-radius:0; -} - -.xfaLayer .highlight.selected{ - background-color:rgb(203 223 203); -} - -.xfaPage{ - overflow:hidden; - position:relative; -} - -.xfaContentarea{ - position:absolute; -} - -.xfaPrintOnly{ - display:none; -} - -.xfaLayer{ - position:absolute; - text-align:initial; - top:0; - left:0; - transform-origin:0 0; - line-height:1.2; -} - -.xfaLayer *{ - color:inherit; - font:inherit; - font-style:inherit; - font-weight:inherit; - font-kerning:inherit; - letter-spacing:-0.01px; - text-align:inherit; - text-decoration:inherit; - box-sizing:border-box; - background-color:transparent; - padding:0; - margin:0; - pointer-events:auto; - line-height:inherit; -} - -.xfaLayer *:required{ - outline:1.5px solid red; -} - -.xfaLayer div, -.xfaLayer svg, -.xfaLayer svg *{ - pointer-events:none; -} - -.xfaLayer a{ - color:blue; -} - -.xfaRich li{ - margin-left:3em; -} - -.xfaFont{ - color:black; - font-weight:normal; - font-kerning:none; - font-size:10px; - font-style:normal; - letter-spacing:0; - text-decoration:none; - vertical-align:0; -} - -.xfaCaption{ - overflow:hidden; - flex:0 0 auto; -} - -.xfaCaptionForCheckButton{ - overflow:hidden; - flex:1 1 auto; -} - -.xfaLabel{ - height:100%; - width:100%; -} - -.xfaLeft{ - display:flex; - flex-direction:row; - align-items:center; -} - -.xfaRight{ - display:flex; - flex-direction:row-reverse; - align-items:center; -} - -:is(.xfaLeft, .xfaRight) > :is(.xfaCaption, .xfaCaptionForCheckButton){ - max-height:100%; -} - -.xfaTop{ - display:flex; - flex-direction:column; - align-items:flex-start; -} - -.xfaBottom{ - display:flex; - flex-direction:column-reverse; - align-items:flex-start; -} - -:is(.xfaTop, .xfaBottom) > :is(.xfaCaption, .xfaCaptionForCheckButton){ - width:100%; -} - -.xfaBorder{ - background-color:transparent; - position:absolute; - pointer-events:none; -} - -.xfaWrapped{ - width:100%; - height:100%; -} - -:is(.xfaTextfield, .xfaSelect):focus{ - background-image:none; - background-color:transparent; - outline:var(--xfa-focus-outline); - outline-offset:-1px; -} - -:is(.xfaCheckbox, .xfaRadio):focus{ - outline:var(--xfa-focus-outline); -} - -.xfaTextfield, -.xfaSelect{ - height:100%; - width:100%; - flex:1 1 auto; - border:none; - resize:none; - background-image:var(--xfa-unfocused-field-background); -} - -.xfaSelect{ - padding-inline:2px; -} - -:is(.xfaTop, .xfaBottom) > :is(.xfaTextfield, .xfaSelect){ - flex:0 1 auto; -} - -.xfaButton{ - cursor:pointer; - width:100%; - height:100%; - border:none; - text-align:center; -} - -.xfaLink{ - width:100%; - height:100%; - position:absolute; - top:0; - left:0; -} - -.xfaCheckbox, -.xfaRadio{ - width:100%; - height:100%; - flex:0 0 auto; - border:none; -} - -.xfaRich{ - white-space:pre-wrap; - width:100%; - height:100%; -} - -.xfaImage{ - -o-object-position:left top; - object-position:left top; - -o-object-fit:contain; - object-fit:contain; - width:100%; - height:100%; -} - -.xfaLrTb, -.xfaRlTb, -.xfaTb{ - display:flex; - flex-direction:column; - align-items:stretch; -} - -.xfaLr{ - display:flex; - flex-direction:row; - align-items:stretch; -} - -.xfaRl{ - display:flex; - flex-direction:row-reverse; - align-items:stretch; -} - -.xfaTb > div{ - justify-content:left; -} - -.xfaPosition{ - position:relative; -} - -.xfaArea{ - position:relative; -} - -.xfaValignMiddle{ - display:flex; - align-items:center; -} - -.xfaTable{ - display:flex; - flex-direction:column; - align-items:stretch; -} - -.xfaTable .xfaRow{ - display:flex; - flex-direction:row; - align-items:stretch; -} - -.xfaTable .xfaRlRow{ - display:flex; - flex-direction:row-reverse; - align-items:stretch; - flex:1; -} - -.xfaTable .xfaRlRow > div{ - flex:1; -} - -:is(.xfaNonInteractive, .xfaDisabled, .xfaReadOnly) :is(input, textarea){ - background:initial; -} - -@media print{ - .xfaTextfield, - .xfaSelect{ - background:transparent; - } - - .xfaSelect{ - -webkit-appearance:none; - -moz-appearance:none; - appearance:none; - text-indent:1px; - text-overflow:""; - } -} - -/* .canvasWrapper svg{ - transform:none; - } - -.canvasWrapper svg[data-main-rotation="90"] mask, - .canvasWrapper svg[data-main-rotation="90"] use:not(.clip, .mask){ - transform:matrix(0, 1, -1, 0, 1, 0); - } - -.canvasWrapper svg[data-main-rotation="180"] mask, - .canvasWrapper svg[data-main-rotation="180"] use:not(.clip, .mask){ - transform:matrix(-1, 0, 0, -1, 1, 1); - } - -.canvasWrapper svg[data-main-rotation="270"] mask, - .canvasWrapper svg[data-main-rotation="270"] use:not(.clip, .mask){ - transform:matrix(0, -1, 1, 0, 0, 1); - } - -.canvasWrapper svg.highlight{ - --blend-mode:multiply; - - position:absolute; - mix-blend-mode:var(--blend-mode); - } */ - -@media screen and (forced-colors: active){ - -.canvasWrapper svg.highlight{ - --blend-mode:difference; - } - } - -.canvasWrapper svg.highlight:not(.free){ - fill-rule:evenodd; - } - -.canvasWrapper svg.highlightOutline{ - position:absolute; - mix-blend-mode:normal; - fill-rule:evenodd; - fill:none; - } - -.canvasWrapper svg.highlightOutline.hovered:not(.free):not(.selected){ - stroke:var(--hover-outline-color); - stroke-width:var(--outline-width); - } - -.canvasWrapper svg.highlightOutline.selected:not(.free) .mainOutline{ - stroke:var(--outline-around-color); - stroke-width:calc( - var(--outline-width) + 2 * var(--outline-around-width) - ); - } - -.canvasWrapper svg.highlightOutline.selected:not(.free) .secondaryOutline{ - stroke:var(--outline-color); - stroke-width:var(--outline-width); - } - -.canvasWrapper svg.highlightOutline.free.hovered:not(.selected){ - stroke:var(--hover-outline-color); - stroke-width:calc(2 * var(--outline-width)); - } - -.canvasWrapper svg.highlightOutline.free.selected .mainOutline{ - stroke:var(--outline-around-color); - stroke-width:calc( - 2 * (var(--outline-width) + var(--outline-around-width)) - ); - } - -.canvasWrapper svg.highlightOutline.free.selected .secondaryOutline{ - stroke:var(--outline-color); - stroke-width:calc(2 * var(--outline-width)); - } - -.toggle-button{ - --button-background-color:#f0f0f4; - --button-background-color-hover:#e0e0e6; - --button-background-color-active:#cfcfd8; - --color-accent-primary:#0060df; - --color-accent-primary-hover:#0250bb; - --color-accent-primary-active:#054096; - --border-interactive-color:#8f8f9d; - --border-radius-circle:9999px; - --border-width:1px; - --size-item-small:16px; - --size-item-large:32px; - --color-canvas:white; - - --toggle-background-color:var(--button-background-color); - --toggle-background-color-hover:var(--button-background-color-hover); - --toggle-background-color-active:var(--button-background-color-active); - --toggle-background-color-pressed:var(--color-accent-primary); - --toggle-background-color-pressed-hover:var(--color-accent-primary-hover); - --toggle-background-color-pressed-active:var(--color-accent-primary-active); - --toggle-border-color:var(--border-interactive-color); - --toggle-border-color-hover:var(--toggle-border-color); - --toggle-border-color-active:var(--toggle-border-color); - --toggle-border-radius:var(--border-radius-circle); - --toggle-border-width:var(--border-width); - --toggle-height:var(--size-item-small); - --toggle-width:var(--size-item-large); - --toggle-dot-background-color:var(--toggle-border-color); - --toggle-dot-background-color-hover:var(--toggle-dot-background-color); - --toggle-dot-background-color-active:var(--toggle-dot-background-color); - --toggle-dot-background-color-on-pressed:var(--color-canvas); - --toggle-dot-margin:1px; - --toggle-dot-height:calc( - var(--toggle-height) - 2 * var(--toggle-dot-margin) - 2 * - var(--toggle-border-width) - ); - --toggle-dot-width:var(--toggle-dot-height); - --toggle-dot-transform-x:calc( - var(--toggle-width) - 4 * var(--toggle-dot-margin) - var(--toggle-dot-width) - ); - - -webkit-appearance:none; - - -moz-appearance:none; - - appearance:none; - padding:0; - margin:0; - border:var(--toggle-border-width) solid var(--toggle-border-color); - height:var(--toggle-height); - width:var(--toggle-width); - border-radius:var(--toggle-border-radius); - background:var(--toggle-background-color); - box-sizing:border-box; - flex-shrink:0; -} - -@media (prefers-color-scheme: light){ - -:where(html:not(.is-light)) .toggle-button{ - --button-background-color:color-mix(in srgb, currentColor 7%, transparent); - --button-background-color-hover:color-mix( - in srgb, - currentColor 14%, - transparent - ); - --button-background-color-active:color-mix( - in srgb, - currentColor 21%, - transparent - ); - --color-accent-primary:#0df; - --color-accent-primary-hover:#80ebff; - --color-accent-primary-active:#aaf2ff; - --border-interactive-color:#bfbfc9; - --color-canvas:#1c1b22; -} - } - -:where(html.is-dark) .toggle-button{ - --button-background-color:color-mix(in srgb, currentColor 7%, transparent); - --button-background-color-hover:color-mix( - in srgb, - currentColor 14%, - transparent - ); - --button-background-color-active:color-mix( - in srgb, - currentColor 21%, - transparent - ); - --color-accent-primary:#0df; - --color-accent-primary-hover:#80ebff; - --color-accent-primary-active:#aaf2ff; - --border-interactive-color:#bfbfc9; - --color-canvas:#1c1b22; -} - -@media (forced-colors: active){ - -.toggle-button{ - --color-accent-primary:ButtonText; - --color-accent-primary-hover:SelectedItem; - --color-accent-primary-active:SelectedItem; - --border-interactive-color:ButtonText; - --button-background-color:ButtonFace; - --border-interactive-color-hover:SelectedItem; - --border-interactive-color-active:SelectedItem; - --border-interactive-color-disabled:GrayText; - --color-canvas:ButtonText; -} - } - -.toggle-button:focus-visible{ - outline:var(--focus-outline); - outline-offset:var(--focus-outline-offset); - } - -.toggle-button:enabled:hover{ - background:var(--toggle-background-color-hover); - border-color:var(--toggle-border-color); - } - -.toggle-button:enabled:active{ - background:var(--toggle-background-color-active); - border-color:var(--toggle-border-color); - } - -.toggle-button[aria-pressed="true"]{ - background:var(--toggle-background-color-pressed); - border-color:transparent; - } - -.toggle-button[aria-pressed="true"]:enabled:hover{ - background:var(--toggle-background-color-pressed-hover); - border-color:transparent; - } - -.toggle-button[aria-pressed="true"]:enabled:active{ - background:var(--toggle-background-color-pressed-active); - border-color:transparent; - } - -.toggle-button::before{ - display:block; - content:""; - background-color:var(--toggle-dot-background-color); - height:var(--toggle-dot-height); - width:var(--toggle-dot-width); - margin:var(--toggle-dot-margin); - border-radius:var(--toggle-border-radius); - translate:0; - } - -.toggle-button[aria-pressed="true"]::before{ - translate:var(--toggle-dot-transform-x); - background-color:var(--toggle-dot-background-color-on-pressed); - } - -.toggle-button[aria-pressed="true"]:enabled:hover::before, - .toggle-button[aria-pressed="true"]:enabled:active::before{ - background-color:var(--toggle-dot-background-color-on-pressed); - } - -[dir="rtl"] .toggle-button[aria-pressed="true"]::before{ - translate:calc(-1 * var(--toggle-dot-transform-x)); - } - -@media (prefers-reduced-motion: no-preference){ - .toggle-button::before{ - transition:translate 100ms; - } - } - -@media (prefers-contrast){ - .toggle-button:enabled:hover{ - border-color:var(--toggle-border-color-hover); - } - - .toggle-button:enabled:active{ - border-color:var(--toggle-border-color-active); - } - - .toggle-button[aria-pressed="true"]:enabled{ - border-color:var(--toggle-border-color); - position:relative; - } - - .toggle-button[aria-pressed="true"]:enabled:hover, - .toggle-button[aria-pressed="true"]:enabled:hover:active{ - border-color:var(--toggle-border-color-hover); - } - - .toggle-button[aria-pressed="true"]:enabled:active{ - background-color:var(--toggle-dot-background-color-active); - border-color:var(--toggle-dot-background-color-hover); - } - - .toggle-button:hover::before, - .toggle-button:active::before{ - background-color:var(--toggle-dot-background-color-hover); - } - } - -@media (forced-colors){ - -.toggle-button{ - --toggle-dot-background-color:var(--color-accent-primary); - --toggle-dot-background-color-hover:var(--color-accent-primary-hover); - --toggle-dot-background-color-active:var(--color-accent-primary-active); - --toggle-dot-background-color-on-pressed:var(--button-background-color); - --toggle-background-color-disabled:var(--button-background-color-disabled); - --toggle-border-color-hover:var(--border-interactive-color-hover); - --toggle-border-color-active:var(--border-interactive-color-active); - --toggle-border-color-disabled:var(--border-interactive-color-disabled); -} - - .toggle-button[aria-pressed="true"]:enabled::after{ - border:1px solid var(--button-background-color); - content:""; - position:absolute; - height:var(--toggle-height); - width:var(--toggle-width); - display:block; - border-radius:var(--toggle-border-radius); - inset:-2px; - } - - .toggle-button[aria-pressed="true"]:enabled:active::after{ - border-color:var(--toggle-border-color-active); - } - } - -:root{ - --outline-width:2px; - --outline-color:#0060df; - --outline-around-width:1px; - --outline-around-color:#f0f0f4; - --hover-outline-around-color:var(--outline-around-color); - --focus-outline:solid var(--outline-width) var(--outline-color); - --unfocus-outline:solid var(--outline-width) transparent; - --focus-outline-around:solid var(--outline-around-width) var(--outline-around-color); - --hover-outline-color:#8f8f9d; - --hover-outline:solid var(--outline-width) var(--hover-outline-color); - --hover-outline-around:solid var(--outline-around-width) var(--hover-outline-around-color); - --freetext-line-height:1.35; - --freetext-padding:2px; - --resizer-bg-color:var(--outline-color); - --resizer-size:6px; - --resizer-shift:calc( - 0px - (var(--outline-width) + var(--resizer-size)) / 2 - - var(--outline-around-width) - ); - --editorFreeText-editing-cursor:text; - --editorInk-editing-cursor:url(images/cursor-editorInk.svg) 0 16, pointer; - --editorHighlight-editing-cursor:url(images/cursor-editorTextHighlight.svg) 24 24, text; - --editorFreeHighlight-editing-cursor:url(images/cursor-editorFreeHighlight.svg) 1 18, pointer; -} -.visuallyHidden{ - position:absolute; - top:0; - left:0; - border:0; - margin:0; - padding:0; - width:0; - height:0; - overflow:hidden; - white-space:nowrap; - font-size:0; -} - -.textLayer.highlighting{ - cursor:var(--editorFreeHighlight-editing-cursor); -} - -.textLayer.highlighting:not(.free) span{ - cursor:var(--editorHighlight-editing-cursor); - } - -.textLayer.highlighting.free span{ - cursor:var(--editorFreeHighlight-editing-cursor); - } - -@media (min-resolution: 1.1dppx){ - :root{ - --editorFreeText-editing-cursor:url(images/cursor-editorFreeText.svg) 0 16, text; - } -} - -@media screen and (forced-colors: active){ - :root{ - --outline-color:CanvasText; - --outline-around-color:ButtonFace; - --resizer-bg-color:ButtonText; - --hover-outline-color:Highlight; - --hover-outline-around-color:SelectedItemText; - } -} - -[data-editor-rotation="90"]{ - transform:rotate(90deg); -} - -[data-editor-rotation="180"]{ - transform:rotate(180deg); -} - -[data-editor-rotation="270"]{ - transform:rotate(270deg); -} - -.annotationEditorLayer{ - background:transparent; - position:absolute; - inset:0; - font-size:calc(100px * var(--scale-factor)); - transform-origin:0 0; - cursor:auto; -} - -.annotationEditorLayer.waiting{ - content:""; - cursor:wait; - position:absolute; - inset:0; - width:100%; - height:100%; -} - -.annotationEditorLayer.disabled{ - pointer-events:none; -} - -.annotationEditorLayer.freetextEditing{ - cursor:var(--editorFreeText-editing-cursor); -} - -.annotationEditorLayer.inkEditing{ - cursor:var(--editorInk-editing-cursor); -} - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor){ - position:absolute; - background:transparent; - z-index:1; - transform-origin:0 0; - cursor:auto; - max-width:100%; - max-height:100%; - border:var(--unfocus-outline); -} - -.annotationEditorLayer .draggable.selectedEditor:is(.freeTextEditor, .inkEditor, .stampEditor){ - cursor:move; - } - -.annotationEditorLayer .moving:is(.freeTextEditor, .inkEditor, .stampEditor){ - touch-action:none; - } - -.annotationEditorLayer .selectedEditor:is(.freeTextEditor, .inkEditor, .stampEditor){ - border:var(--focus-outline); - outline:var(--focus-outline-around); - } - -.annotationEditorLayer .selectedEditor:is(.freeTextEditor, .inkEditor, .stampEditor)::before{ - content:""; - position:absolute; - inset:0; - border:var(--focus-outline-around); - pointer-events:none; - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor):hover:not(.selectedEditor){ - border:var(--hover-outline); - outline:var(--hover-outline-around); - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor):hover:not(.selectedEditor)::before{ - content:""; - position:absolute; - inset:0; - border:var(--focus-outline-around); - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{ - --editor-toolbar-delete-image:url(images/editor-toolbar-delete.svg); - --editor-toolbar-bg-color:#f0f0f4; - --editor-toolbar-highlight-image:url(images/toolbarButton-editorHighlight.svg); - --editor-toolbar-fg-color:#2e2e56; - --editor-toolbar-border-color:#8f8f9d; - --editor-toolbar-hover-border-color:var(--editor-toolbar-border-color); - --editor-toolbar-hover-bg-color:#e0e0e6; - --editor-toolbar-hover-fg-color:var(--editor-toolbar-fg-color); - --editor-toolbar-hover-outline:none; - --editor-toolbar-focus-outline-color:#0060df; - --editor-toolbar-shadow:0 2px 6px 0 rgb(58 57 68 / 0.2); - --editor-toolbar-vert-offset:6px; - --editor-toolbar-height:28px; - --editor-toolbar-padding:2px; - - display:flex; - width:-moz-fit-content; - width:fit-content; - height:var(--editor-toolbar-height); - flex-direction:column; - justify-content:center; - align-items:center; - cursor:default; - pointer-events:auto; - box-sizing:content-box; - padding:var(--editor-toolbar-padding); - - position:absolute; - inset-inline-end:0; - inset-block-start:calc(100% + var(--editor-toolbar-vert-offset)); - - border-radius:6px; - background-color:var(--editor-toolbar-bg-color); - border:1px solid var(--editor-toolbar-border-color); - box-shadow:var(--editor-toolbar-shadow); - } - -@media (prefers-color-scheme: light){ - -:where(html:not(.is-light)) :is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{ - --editor-toolbar-bg-color:#2b2a33; - --editor-toolbar-fg-color:#fbfbfe; - --editor-toolbar-hover-bg-color:#52525e; - --editor-toolbar-focus-outline-color:#0df; - } - } - -:where(html.is-dark) :is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{ - --editor-toolbar-bg-color:#2b2a33; - --editor-toolbar-fg-color:#fbfbfe; - --editor-toolbar-hover-bg-color:#52525e; - --editor-toolbar-focus-outline-color:#0df; - } - -@media screen and (forced-colors: active){ - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{ - --editor-toolbar-bg-color:ButtonFace; - --editor-toolbar-fg-color:ButtonText; - --editor-toolbar-border-color:ButtonText; - --editor-toolbar-hover-border-color:AccentColor; - --editor-toolbar-hover-bg-color:ButtonFace; - --editor-toolbar-hover-fg-color:AccentColor; - --editor-toolbar-hover-outline:2px solid var(--editor-toolbar-hover-border-color); - --editor-toolbar-focus-outline-color:ButtonBorder; - --editor-toolbar-shadow:none; - } - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar.hidden{ - display:none; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar:has(:focus-visible){ - border-color:transparent; - } - -[dir="ltr"] :is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{ - transform-origin:100% 0; - } - -[dir="rtl"] :is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar{ - transform-origin:0 0; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons{ - display:flex; - justify-content:center; - align-items:center; - gap:0; - height:100%; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .divider{ - width:1px; - height:calc( - 2 * var(--editor-toolbar-padding) + var(--editor-toolbar-height) - ); - background-color:var(--editor-toolbar-border-color); - display:inline-block; - margin-inline:2px; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .highlightButton{ - width:var(--editor-toolbar-height); - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .highlightButton::before{ - content:""; - -webkit-mask-image:var(--editor-toolbar-highlight-image); - mask-image:var(--editor-toolbar-highlight-image); - -webkit-mask-repeat:no-repeat; - mask-repeat:no-repeat; - -webkit-mask-position:center; - mask-position:center; - display:inline-block; - background-color:var(--editor-toolbar-fg-color); - width:100%; - height:100%; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .highlightButton:hover::before{ - background-color:var(--editor-toolbar-hover-fg-color); - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .delete{ - width:var(--editor-toolbar-height); - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .delete::before{ - content:""; - -webkit-mask-image:var(--editor-toolbar-delete-image); - mask-image:var(--editor-toolbar-delete-image); - -webkit-mask-repeat:no-repeat; - mask-repeat:no-repeat; - -webkit-mask-position:center; - mask-position:center; - display:inline-block; - background-color:var(--editor-toolbar-fg-color); - width:100%; - height:100%; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .delete:hover::before{ - background-color:var(--editor-toolbar-hover-fg-color); - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons > *{ - height:var(--editor-toolbar-height); - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons > :not(.divider){ - border:none; - background-color:transparent; - cursor:pointer; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons > :not(.divider):hover{ - border-radius:2px; - background-color:var(--editor-toolbar-hover-bg-color); - color:var(--editor-toolbar-hover-fg-color); - outline:var(--editor-toolbar-hover-outline); - outline-offset:1px; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons > :not(.divider):hover:active{ - outline:none; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons > :not(.divider):focus-visible{ - border-radius:2px; - outline:2px solid var(--editor-toolbar-focus-outline-color); - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText{ - --alt-text-add-image:url(images/altText_add.svg); - --alt-text-done-image:url(images/altText_done.svg); - - display:flex; - align-items:center; - justify-content:center; - width:-moz-max-content; - width:max-content; - padding-inline:8px; - pointer-events:all; - font:menu; - font-weight:590; - font-size:12px; - color:var(--editor-toolbar-fg-color); - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText:disabled{ - pointer-events:none; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText::before{ - content:""; - -webkit-mask-image:var(--alt-text-add-image); - mask-image:var(--alt-text-add-image); - -webkit-mask-repeat:no-repeat; - mask-repeat:no-repeat; - -webkit-mask-position:center; - mask-position:center; - display:inline-block; - width:12px; - height:13px; - background-color:var(--editor-toolbar-fg-color); - margin-inline-end:4px; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText:hover::before{ - background-color:var(--editor-toolbar-hover-fg-color); - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText.done::before{ - -webkit-mask-image:var(--alt-text-done-image); - mask-image:var(--alt-text-done-image); - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText .tooltip{ - display:none; - } - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText .tooltip.show{ - --alt-text-tooltip-bg:#f0f0f4; - --alt-text-tooltip-fg:#15141a; - --alt-text-tooltip-border:#8f8f9d; - --alt-text-tooltip-shadow:0px 2px 6px 0px rgb(58 57 68 / 0.2); - - display:inline-flex; - flex-direction:column; - align-items:center; - justify-content:center; - position:absolute; - top:calc(100% + 2px); - inset-inline-start:0; - padding-block:2px 3px; - padding-inline:3px; - max-width:300px; - width:-moz-max-content; - width:max-content; - height:auto; - font-size:12px; - - border:0.5px solid var(--alt-text-tooltip-border); - background:var(--alt-text-tooltip-bg); - box-shadow:var(--alt-text-tooltip-shadow); - color:var(--alt-text-tooltip-fg); - - pointer-events:none; - } - -@media (prefers-color-scheme: light){ - -:where(html:not(.is-light)) :is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText .tooltip.show{ - --alt-text-tooltip-bg:#1c1b22; - --alt-text-tooltip-fg:#fbfbfe; - --alt-text-tooltip-shadow:0px 2px 6px 0px #15141a; - } - } - -:where(html.is-dark) :is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText .tooltip.show{ - --alt-text-tooltip-bg:#1c1b22; - --alt-text-tooltip-fg:#fbfbfe; - --alt-text-tooltip-shadow:0px 2px 6px 0px #15141a; - } - -@media screen and (forced-colors: active){ - -:is(.annotationEditorLayer - :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),.textLayer) .editToolbar .buttons .altText .tooltip.show{ - --alt-text-tooltip-bg:Canvas; - --alt-text-tooltip-fg:CanvasText; - --alt-text-tooltip-border:CanvasText; - --alt-text-tooltip-shadow:none; - } - } - -.annotationEditorLayer .freeTextEditor{ - padding:calc(var(--freetext-padding) * var(--scale-factor)); - width:auto; - height:auto; - touch-action:none; -} - -.annotationEditorLayer .freeTextEditor .internal{ - background:transparent; - border:none; - inset:0; - overflow:visible; - white-space:nowrap; - font:10px sans-serif; - line-height:var(--freetext-line-height); - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; -} - -.annotationEditorLayer .freeTextEditor .overlay{ - position:absolute; - display:none; - background:transparent; - inset:0; - width:100%; - height:100%; -} - -.annotationEditorLayer freeTextEditor .overlay.enabled{ - display:block; -} - -.annotationEditorLayer .freeTextEditor .internal:empty::before{ - content:attr(default-content); - color:gray; -} - -.annotationEditorLayer .freeTextEditor .internal:focus{ - outline:none; - -webkit-user-select:auto; - -moz-user-select:auto; - user-select:auto; -} - -.annotationEditorLayer .inkEditor{ - width:100%; - height:100%; -} - -.annotationEditorLayer .inkEditor.editing{ - cursor:inherit; -} - -.annotationEditorLayer .inkEditor .inkEditorCanvas{ - position:absolute; - inset:0; - width:100%; - height:100%; - touch-action:none; -} - -.annotationEditorLayer .stampEditor{ - width:auto; - height:auto; -} - -.annotationEditorLayer .stampEditor canvas{ - width:100%; - height:100%; -} - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers{ - position:absolute; - inset:0; - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers.hidden{ - display:none; - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer{ - width:var(--resizer-size); - height:var(--resizer-size); - background:content-box var(--resizer-bg-color); - border:var(--focus-outline-around); - border-radius:2px; - position:absolute; - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.topLeft{ - top:var(--resizer-shift); - left:var(--resizer-shift); - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.topMiddle{ - top:var(--resizer-shift); - left:calc(50% + var(--resizer-shift)); - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.topRight{ - top:var(--resizer-shift); - right:var(--resizer-shift); - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.middleRight{ - top:calc(50% + var(--resizer-shift)); - right:var(--resizer-shift); - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.bottomRight{ - bottom:var(--resizer-shift); - right:var(--resizer-shift); - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.bottomMiddle{ - bottom:var(--resizer-shift); - left:calc(50% + var(--resizer-shift)); - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.bottomLeft{ - bottom:var(--resizer-shift); - left:var(--resizer-shift); - } - -.annotationEditorLayer :is(.freeTextEditor, .inkEditor, .stampEditor) > .resizers > .resizer.middleLeft{ - top:calc(50% + var(--resizer-shift)); - left:var(--resizer-shift); - } - -.annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topLeft, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topLeft, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topLeft, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topLeft, - .annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomRight, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomRight, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomRight, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomRight{ - cursor:nwse-resize; - } - -.annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topMiddle, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topMiddle, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topMiddle, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topMiddle, - .annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomMiddle, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomMiddle, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomMiddle, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomMiddle{ - cursor:ns-resize; - } - -.annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topRight, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topRight, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topRight, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topRight, - .annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomLeft, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomLeft, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomLeft, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomLeft{ - cursor:nesw-resize; - } - -.annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.middleRight, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.middleRight, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.middleRight, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.middleRight, - .annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.middleLeft, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.middleLeft, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.middleLeft, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.middleLeft{ - cursor:ew-resize; - } - -.annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topLeft, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topLeft, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topLeft, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topLeft, - .annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomRight, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomRight, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomRight, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomRight{ - cursor:nesw-resize; - } - -.annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topMiddle, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topMiddle, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topMiddle, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topMiddle, - .annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomMiddle, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomMiddle, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomMiddle, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomMiddle{ - cursor:ew-resize; - } - -.annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.topRight, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.topRight, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.topRight, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.topRight, - .annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.bottomLeft, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.bottomLeft, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.bottomLeft, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.bottomLeft{ - cursor:nwse-resize; - } - -.annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.middleRight, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.middleRight, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.middleRight, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.middleRight, - .annotationEditorLayer[data-main-rotation="0"] - :is([data-editor-rotation="90"], [data-editor-rotation="270"]) > .resizers > .resizer.middleLeft, - .annotationEditorLayer[data-main-rotation="90"] - :is([data-editor-rotation="0"], [data-editor-rotation="180"]) > .resizers > .resizer.middleLeft, - .annotationEditorLayer[data-main-rotation="180"] - :is([data-editor-rotation="270"], [data-editor-rotation="90"]) > .resizers > .resizer.middleLeft, - .annotationEditorLayer[data-main-rotation="270"] - :is([data-editor-rotation="180"], [data-editor-rotation="0"]) > .resizers > .resizer.middleLeft{ - cursor:ns-resize; - } - -.annotationEditorLayer - :is( - [data-main-rotation="0"] [data-editor-rotation="90"], - [data-main-rotation="90"] [data-editor-rotation="0"], - [data-main-rotation="180"] [data-editor-rotation="270"], - [data-main-rotation="270"] [data-editor-rotation="180"] - ) .editToolbar{ - rotate:270deg; - } - -[dir="ltr"] .annotationEditorLayer - :is( - [data-main-rotation="0"] [data-editor-rotation="90"], - [data-main-rotation="90"] [data-editor-rotation="0"], - [data-main-rotation="180"] [data-editor-rotation="270"], - [data-main-rotation="270"] [data-editor-rotation="180"] - ) .editToolbar{ - inset-inline-end:calc(0px - var(--editor-toolbar-vert-offset)); - inset-block-start:0; - } - -[dir="rtl"] .annotationEditorLayer - :is( - [data-main-rotation="0"] [data-editor-rotation="90"], - [data-main-rotation="90"] [data-editor-rotation="0"], - [data-main-rotation="180"] [data-editor-rotation="270"], - [data-main-rotation="270"] [data-editor-rotation="180"] - ) .editToolbar{ - inset-inline-end:calc(100% + var(--editor-toolbar-vert-offset)); - inset-block-start:0; - } - -.annotationEditorLayer - :is( - [data-main-rotation="0"] [data-editor-rotation="180"], - [data-main-rotation="90"] [data-editor-rotation="90"], - [data-main-rotation="180"] [data-editor-rotation="0"], - [data-main-rotation="270"] [data-editor-rotation="270"] - ) .editToolbar{ - rotate:180deg; - inset-inline-end:100%; - inset-block-start:calc(0pc - var(--editor-toolbar-vert-offset)); - } - -.annotationEditorLayer - :is( - [data-main-rotation="0"] [data-editor-rotation="270"], - [data-main-rotation="90"] [data-editor-rotation="180"], - [data-main-rotation="180"] [data-editor-rotation="90"], - [data-main-rotation="270"] [data-editor-rotation="0"] - ) .editToolbar{ - rotate:90deg; - } - -[dir="ltr"] .annotationEditorLayer - :is( - [data-main-rotation="0"] [data-editor-rotation="270"], - [data-main-rotation="90"] [data-editor-rotation="180"], - [data-main-rotation="180"] [data-editor-rotation="90"], - [data-main-rotation="270"] [data-editor-rotation="0"] - ) .editToolbar{ - inset-inline-end:calc(100% + var(--editor-toolbar-vert-offset)); - inset-block-start:100%; - } - -[dir="rtl"] .annotationEditorLayer - :is( - [data-main-rotation="0"] [data-editor-rotation="270"], - [data-main-rotation="90"] [data-editor-rotation="180"], - [data-main-rotation="180"] [data-editor-rotation="90"], - [data-main-rotation="270"] [data-editor-rotation="0"] - ) .editToolbar{ - inset-inline-start:calc(0px - var(--editor-toolbar-vert-offset)); - inset-block-start:0; - } - -#altTextDialog{ - --dialog-bg-color:white; - --dialog-border-color:white; - --dialog-shadow:0 2px 14px 0 rgb(58 57 68 / 0.2); - --text-primary-color:#15141a; - --text-secondary-color:#5b5b66; - --hover-filter:brightness(0.9); - --focus-ring-color:#0060df; - --focus-ring-outline:2px solid var(--focus-ring-color); - - --textarea-border-color:#8f8f9d; - --textarea-bg-color:white; - --textarea-fg-color:var(--text-secondary-color); - - --radio-bg-color:#f0f0f4; - --radio-checked-bg-color:#fbfbfe; - --radio-border-color:#8f8f9d; - --radio-checked-border-color:#0060df; - - --button-cancel-bg-color:#f0f0f4; - --button-cancel-fg-color:var(--text-primary-color); - --button-cancel-border-color:var(--button-cancel-bg-color); - --button-cancel-hover-bg-color:var(--button-cancel-bg-color); - --button-cancel-hover-fg-color:var(--button-cancel-fg-color); - --button-cancel-hover-border-color:var(--button-cancel-hover-bg-color); - - --button-save-bg-color:#0060df; - --button-save-fg-color:#fbfbfe; - --button-save-hover-bg-color:var(--button-save-bg-color); - --button-save-hover-fg-color:var(--button-save-fg-color); - --button-save-hover-border-color:var(--button-save-hover-bg-color); - - font:message-box; - font-size:13px; - font-weight:400; - line-height:150%; - border-radius:4px; - padding:12px 16px; - border:1px solid var(--dialog-border-color); - background:var(--dialog-bg-color); - color:var(--text-primary-color); - box-shadow:var(--dialog-shadow); -} - -@media (prefers-color-scheme: light){ - -:where(html:not(.is-light)) #altTextDialog{ - --dialog-bg-color:#1c1b22; - --dialog-border-color:#1c1b22; - --dialog-shadow:0 2px 14px 0 #15141a; - --text-primary-color:#fbfbfe; - --text-secondary-color:#cfcfd8; - --focus-ring-color:#0df; - --hover-filter:brightness(1.4); - - --textarea-bg-color:#42414d; - - --radio-bg-color:#2b2a33; - --radio-checked-bg-color:#15141a; - --radio-checked-border-color:#0df; - - --button-cancel-bg-color:#2b2a33; - --button-save-bg-color:#0df; - --button-save-fg-color:#15141a; -} - } - -:where(html.is-dark) #altTextDialog{ - --dialog-bg-color:#1c1b22; - --dialog-border-color:#1c1b22; - --dialog-shadow:0 2px 14px 0 #15141a; - --text-primary-color:#fbfbfe; - --text-secondary-color:#cfcfd8; - --focus-ring-color:#0df; - --hover-filter:brightness(1.4); - - --textarea-bg-color:#42414d; - - --radio-bg-color:#2b2a33; - --radio-checked-bg-color:#15141a; - --radio-checked-border-color:#0df; - - --button-cancel-bg-color:#2b2a33; - --button-save-bg-color:#0df; - --button-save-fg-color:#15141a; -} - -@media screen and (forced-colors: active){ - -#altTextDialog{ - --dialog-bg-color:Canvas; - --dialog-border-color:CanvasText; - --dialog-shadow:none; - --text-primary-color:CanvasText; - --text-secondary-color:CanvasText; - --hover-filter:none; - --focus-ring-color:ButtonBorder; - - --textarea-border-color:ButtonBorder; - --textarea-bg-color:Field; - --textarea-fg-color:ButtonText; - - --radio-bg-color:ButtonFace; - --radio-checked-bg-color:ButtonFace; - --radio-border-color:ButtonText; - --radio-checked-border-color:ButtonText; - - --button-cancel-bg-color:ButtonFace; - --button-cancel-fg-color:ButtonText; - --button-cancel-border-color:ButtonText; - --button-cancel-hover-bg-color:AccentColor; - --button-cancel-hover-fg-color:AccentColorText; - - --button-save-bg-color:ButtonText; - --button-save-fg-color:ButtonFace; - --button-save-hover-bg-color:AccentColor; - --button-save-hover-fg-color:AccentColorText; -} - } - -#altTextDialog::backdrop{ - -webkit-mask:url(#alttext-manager-mask); - mask:url(#alttext-manager-mask); - } - -#altTextDialog.positioned{ - margin:0; - } - -#altTextDialog #altTextContainer{ - width:300px; - height:-moz-fit-content; - height:fit-content; - display:inline-flex; - flex-direction:column; - align-items:flex-start; - gap:16px; - } - -#altTextDialog #altTextContainer *:focus-visible{ - outline:var(--focus-ring-outline); - outline-offset:2px; - } - -#altTextDialog #altTextContainer .radio{ - display:flex; - flex-direction:column; - align-items:flex-start; - gap:4px; - } - -#altTextDialog #altTextContainer .radio .radioButton{ - display:flex; - gap:8px; - align-self:stretch; - align-items:center; - } - -#altTextDialog #altTextContainer .radio .radioButton input{ - -webkit-appearance:none; - -moz-appearance:none; - appearance:none; - box-sizing:border-box; - width:16px; - height:16px; - border-radius:50%; - background-color:var(--radio-bg-color); - border:1px solid var(--radio-border-color); - } - -#altTextDialog #altTextContainer .radio .radioButton input:hover{ - filter:var(--hover-filter); - } - -#altTextDialog #altTextContainer .radio .radioButton input:checked{ - background-color:var(--radio-checked-bg-color); - border:4px solid var(--radio-checked-border-color); - } - -#altTextDialog #altTextContainer .radio .radioLabel{ - display:flex; - padding-inline-start:24px; - align-items:flex-start; - gap:10px; - align-self:stretch; - } - -#altTextDialog #altTextContainer .radio .radioLabel span{ - flex:1 0 0; - font-size:11px; - color:var(--text-secondary-color); - } - -#altTextDialog #altTextContainer #overallDescription{ - display:flex; - flex-direction:column; - align-items:flex-start; - gap:4px; - align-self:stretch; - } - -#altTextDialog #altTextContainer #overallDescription span{ - align-self:stretch; - } - -#altTextDialog #altTextContainer #overallDescription .title{ - font-size:13px; - font-style:normal; - font-weight:590; - } - -#altTextDialog #altTextContainer #addDescription{ - display:flex; - flex-direction:column; - align-items:stretch; - gap:8px; - } - -#altTextDialog #altTextContainer #addDescription .descriptionArea{ - flex:1; - padding-inline:24px 10px; - } - -#altTextDialog #altTextContainer #addDescription .descriptionArea textarea{ - font:inherit; - width:100%; - min-height:75px; - padding:8px; - resize:none; - margin:0; - box-sizing:border-box; - border-radius:4px; - border:1px solid var(--textarea-border-color); - background:var(--textarea-bg-color); - color:var(--textarea-fg-color); - } - -#altTextDialog #altTextContainer #addDescription .descriptionArea textarea:focus{ - outline-offset:0; - border-color:transparent; - } - -#altTextDialog #altTextContainer #addDescription .descriptionArea textarea:disabled{ - pointer-events:none; - opacity:0.4; - } - -#altTextDialog #altTextContainer #buttons{ - display:flex; - justify-content:flex-end; - align-items:flex-start; - gap:8px; - align-self:stretch; - } - -#altTextDialog #altTextContainer #buttons button{ - border-radius:4px; - border:1px solid; - font:menu; - font-weight:600; - padding:4px 16px; - width:auto; - height:32px; - } - -#altTextDialog #altTextContainer #buttons button:hover{ - cursor:pointer; - filter:var(--hover-filter); - } - -#altTextDialog #altTextContainer #buttons button#altTextCancel{ - color:var(--button-cancel-fg-color); - background-color:var(--button-cancel-bg-color); - border-color:var(--button-cancel-border-color); - } - -#altTextDialog #altTextContainer #buttons button#altTextCancel:hover{ - color:var(--button-cancel-hover-fg-color); - background-color:var(--button-cancel-hover-bg-color); - border-color:var(--button-cancel-hover-border-color); - } - -#altTextDialog #altTextContainer #buttons button#altTextSave{ - color:var(--button-save-hover-fg-color); - background-color:var(--button-save-hover-bg-color); - border-color:var(--button-save-hover-border-color); - opacity:1; - } - -#altTextDialog #altTextContainer #buttons button#altTextSave:hover{ - color:var(--button-save-hover-fg-color); - background-color:var(--button-save-hover-bg-color); - border-color:var(--button-save-hover-border-color); - } - -.colorPicker{ - --hover-outline-color:#0250bb; - --selected-outline-color:#0060df; - --swatch-border-color:#cfcfd8; -} - -@media (prefers-color-scheme: light){ - -:where(html:not(.is-light)) .colorPicker{ - --hover-outline-color:#80ebff; - --selected-outline-color:#aaf2ff; - --swatch-border-color:#52525e; -} - } - -:where(html.is-dark) .colorPicker{ - --hover-outline-color:#80ebff; - --selected-outline-color:#aaf2ff; - --swatch-border-color:#52525e; -} - -@media screen and (forced-colors: active){ - -.colorPicker{ - --hover-outline-color:Highlight; - --selected-outline-color:var(--hover-outline-color); - --swatch-border-color:ButtonText; -} - } - -.colorPicker .swatch{ - width:16px; - height:16px; - border:1px solid var(--swatch-border-color); - border-radius:100%; - outline-offset:2px; - box-sizing:border-box; - forced-color-adjust:none; - } - -.colorPicker button:is(:hover, .selected) > .swatch{ - border:none; - } - -.annotationEditorLayer[data-main-rotation="0"] .highlightEditor:not(.free) > .editToolbar{ - rotate:0deg; - } - -.annotationEditorLayer[data-main-rotation="90"] .highlightEditor:not(.free) > .editToolbar{ - rotate:270deg; - } - -.annotationEditorLayer[data-main-rotation="180"] .highlightEditor:not(.free) > .editToolbar{ - rotate:180deg; - } - -.annotationEditorLayer[data-main-rotation="270"] .highlightEditor:not(.free) > .editToolbar{ - rotate:90deg; - } - -.annotationEditorLayer .highlightEditor{ - position:absolute; - background:transparent; - z-index:1; - cursor:auto; - max-width:100%; - max-height:100%; - border:none; - outline:none; - pointer-events:none; - transform-origin:0 0; - } - -.annotationEditorLayer .highlightEditor:not(.free){ - transform:none; - } - -.annotationEditorLayer .highlightEditor .internal{ - position:absolute; - top:0; - left:0; - width:100%; - height:100%; - pointer-events:auto; - } - -.annotationEditorLayer .highlightEditor.disabled .internal{ - pointer-events:none; - } - -.annotationEditorLayer .highlightEditor.selectedEditor .internal{ - cursor:pointer; - } - -.annotationEditorLayer .highlightEditor .editToolbar{ - --editor-toolbar-colorpicker-arrow-image:url(images/toolbarButton-menuArrow.svg); - - transform-origin:center !important; - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker{ - position:relative; - width:auto; - display:flex; - justify-content:center; - align-items:center; - gap:4px; - padding:4px; - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker::after{ - content:""; - -webkit-mask-image:var(--editor-toolbar-colorpicker-arrow-image); - mask-image:var(--editor-toolbar-colorpicker-arrow-image); - -webkit-mask-repeat:no-repeat; - mask-repeat:no-repeat; - -webkit-mask-position:center; - mask-position:center; - display:inline-block; - background-color:var(--editor-toolbar-fg-color); - width:12px; - height:12px; - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker:hover::after{ - background-color:var(--editor-toolbar-hover-fg-color); - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker:has(.dropdown:not(.hidden)){ - background-color:var(--editor-toolbar-hover-bg-color); - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker:has(.dropdown:not(.hidden))::after{ - scale:-1; - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown{ - position:absolute; - display:flex; - justify-content:center; - align-items:center; - flex-direction:column; - gap:11px; - padding-block:8px; - border-radius:6px; - background-color:var(--editor-toolbar-bg-color); - border:1px solid var(--editor-toolbar-border-color); - box-shadow:var(--editor-toolbar-shadow); - inset-block-start:calc(100% + 4px); - width:calc(100% + 2 * var(--editor-toolbar-padding)); - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown button{ - width:100%; - height:auto; - border:none; - cursor:pointer; - display:flex; - justify-content:center; - align-items:center; - background:none; - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown button:is(:active, :focus-visible){ - outline:none; - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown button > .swatch{ - outline-offset:2px; - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown button[aria-selected="true"] > .swatch{ - outline:2px solid var(--selected-outline-color); - } - -.annotationEditorLayer .highlightEditor .editToolbar .buttons .colorPicker .dropdown button:is(:hover, :active, :focus-visible) > .swatch{ - outline:2px solid var(--hover-outline-color); - } - -.editorParamsToolbar:has(#highlightParamsToolbarContainer){ - padding:unset; -} - -#highlightParamsToolbarContainer{ - height:auto; - padding-inline:10px; - padding-block:10px 16px; - gap:16px; - display:flex; - flex-direction:column; - box-sizing:border-box; -} - -#highlightParamsToolbarContainer .editorParamsLabel{ - width:-moz-fit-content; - width:fit-content; - inset-inline-start:0; - } - -#highlightParamsToolbarContainer .colorPicker{ - display:flex; - flex-direction:column; - gap:8px; - } - -#highlightParamsToolbarContainer .colorPicker .dropdown{ - display:flex; - justify-content:space-between; - align-items:center; - flex-direction:row; - height:auto; - } - -#highlightParamsToolbarContainer .colorPicker .dropdown button{ - width:auto; - height:auto; - border:none; - cursor:pointer; - display:flex; - justify-content:center; - align-items:center; - background:none; - flex:0 0 auto; - } - -#highlightParamsToolbarContainer .colorPicker .dropdown button .swatch{ - width:24px; - height:24px; - } - -#highlightParamsToolbarContainer .colorPicker .dropdown button:is(:active, :focus-visible){ - outline:none; - } - -#highlightParamsToolbarContainer .colorPicker .dropdown button[aria-selected="true"] > .swatch{ - outline:2px solid var(--selected-outline-color); - } - -#highlightParamsToolbarContainer .colorPicker .dropdown button:is(:hover, :active, :focus-visible) > .swatch{ - outline:2px solid var(--hover-outline-color); - } - -#highlightParamsToolbarContainer #editorHighlightThickness{ - display:flex; - flex-direction:column; - align-items:center; - gap:4px; - align-self:stretch; - } - -#highlightParamsToolbarContainer #editorHighlightThickness .editorParamsLabel{ - width:100%; - height:auto; - align-self:stretch; - } - -#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker{ - display:flex; - justify-content:space-between; - align-items:center; - align-self:stretch; - - --example-color:#bfbfc9; - } - -@media (prefers-color-scheme: light){ - -:where(html:not(.is-light)) #highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker{ - --example-color:#80808e; - } - } - -:where(html.is-dark) #highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker{ - --example-color:#80808e; - } - -@media screen and (forced-colors: active){ - -#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker{ - --example-color:CanvasText; - } - } - -:is(#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker > .editorParamsSlider[disabled]){ - opacity:0.4; - } - -#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker::before, - #highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker::after{ - content:""; - width:8px; - aspect-ratio:1; - display:block; - border-radius:100%; - background-color:var(--example-color); - } - -#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker::after{ - width:24px; - } - -#highlightParamsToolbarContainer #editorHighlightThickness .thicknessPicker .editorParamsSlider{ - width:unset; - height:14px; - } - -#highlightParamsToolbarContainer #editorHighlightVisibility{ - display:flex; - flex-direction:column; - align-items:flex-start; - gap:8px; - align-self:stretch; - } - -#highlightParamsToolbarContainer #editorHighlightVisibility .divider{ - --divider-color:#d7d7db; - - margin-block:4px; - width:100%; - height:1px; - background-color:var(--divider-color); - } - -@media (prefers-color-scheme: light){ - -:where(html:not(.is-light)) #highlightParamsToolbarContainer #editorHighlightVisibility .divider{ - --divider-color:#8f8f9d; - } - } - -:where(html.is-dark) #highlightParamsToolbarContainer #editorHighlightVisibility .divider{ - --divider-color:#8f8f9d; - } - -@media screen and (forced-colors: active){ - -#highlightParamsToolbarContainer #editorHighlightVisibility .divider{ - --divider-color:CanvasText; - } - } - -#highlightParamsToolbarContainer #editorHighlightVisibility .toggler{ - display:flex; - justify-content:space-between; - align-items:center; - align-self:stretch; - } - -:root{ - --viewer-container-height:0; - --pdfViewer-padding-bottom:0; - --page-margin:1px auto -8px; - --page-border:9px solid transparent; - --spreadHorizontalWrapped-margin-LR:-3.5px; - --loading-icon-delay:400ms; - - --num-page-width: 10px; -} - -@media screen and (forced-colors: active){ - :root{ - --pdfViewer-padding-bottom:9px; - --page-margin:8px auto -1px; - --page-border:1px solid CanvasText; - --spreadHorizontalWrapped-margin-LR:3.5px; - } -} - -[data-main-rotation="90"]{ - transform:rotate(90deg) translateY(-100%); -} -[data-main-rotation="180"]{ - transform:rotate(180deg) translate(-100%, -100%); -} -[data-main-rotation="270"]{ - transform:rotate(270deg) translateX(-100%); -} - -#hiddenCopyElement, -.hiddenCanvasElement{ - position:absolute; - top:0; - left:0; - width:0; - height:0; - display:none; -} - -.pdfViewer{ - --scale-factor:1; - - padding-bottom:var(--pdfViewer-padding-bottom); - - --hcm-highlight-filter:none; - --hcm-highlight-selected-filter:none; -} - -@media screen and (forced-colors: active){ - -.pdfViewer{ - --hcm-highlight-filter:invert(100%); -} - } - -.pdfViewer .canvasWrapper{ - overflow:hidden; - width:100%; - height:100%; -} - -.pdfViewer .page{ - direction:ltr; - width:816px; - height:1056px; - margin:var(--page-margin); - position:relative; - overflow:visible; - border:var(--page-border); - background-clip:content-box; - background-color:rgb(255 255 255); -} - -.pdfViewer .dummyPage{ - position:relative; - width:0; - height:var(--viewer-container-height); -} - -.pdfViewer.noUserSelect{ - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; -} - -.pdfViewer.removePageBorders .page{ - margin:0 auto 10px; - border:none; -} - -.pdfViewer:is(.scrollHorizontal, .scrollWrapped), -.spread{ - margin-inline:3.5px; - text-align:center; - display: flex; - flex-direction: column; - align-items: center; -} - -.pdfViewer.scrollHorizontal, -.spread{ - white-space:nowrap; -} - -.pdfViewer.removePageBorders, -.pdfViewer:is(.scrollHorizontal, .scrollWrapped) .spread{ - margin-inline:0; -} - -.spread :is(.page, .dummyPage), -.pdfViewer:is(.scrollHorizontal, .scrollWrapped) :is(.page, .spread){ - display:inline-block; - vertical-align:middle; -} - -.spread .page, -.pdfViewer:is(.scrollHorizontal, .scrollWrapped) .page{ - margin-inline:var(--spreadHorizontalWrapped-margin-LR); -} - -.pdfViewer.removePageBorders .spread .page, -.pdfViewer.removePageBorders:is(.scrollHorizontal, .scrollWrapped) .page{ - margin-inline:5px; -} - -.pdfViewer .page canvas{ - margin:0; - display:block; -} - -.pdfViewer .page canvas .structTree{ - contain:strict; -} - -.pdfViewer .page canvas[hidden]{ - display:none; -} - -.pdfViewer .page canvas[zooming]{ - width:100%; - height:100%; -} - -.pdfViewer .page.loadingIcon::after{ - position:absolute; - top:0; - left:0; - content:""; - width:100%; - height:100%; - background:url("images/loading-icon.gif") center no-repeat; - display:none; - transition-property:display; - transition-delay:var(--loading-icon-delay); - z-index:5; - contain:strict; -} - -.pdfViewer .page.loading::after{ - display:block; -} - -.pdfViewer .page:not(.loading)::after{ - transition-property:none; - display:none; -} - -.pdfPresentationMode .pdfViewer{ - padding-bottom:0; -} - -.pdfPresentationMode .spread{ - margin:0; -} - -.pdfPresentationMode .pdfViewer .page{ - margin:0 auto; - border:2px solid transparent; -} - -:root{ - - --toolbar-height: 48px; - - --dir-factor:1; - --inline-start:left; - --inline-end:right; - - --sidebar-width:128px; - --sidebar-transition-duration:200ms; - --sidebar-transition-timing-function:ease; - - --toolbar-icon-opacity:0.7; - --doorhanger-icon-opacity:0.9; - --editor-toolbar-base-offset:105px; - - --main-color:rgb(12 12 13); - --body-bg-color:rgb(255, 255, 255); - --progressBar-color:rgb(10 132 255); - --progressBar-bg-color:rgb(221 221 222); - --progressBar-blend-color:rgb(116 177 239); - --scrollbar-color:auto; - --scrollbar-bg-color:auto; - --toolbar-icon-bg-color:rgb(0 0 0); - --toolbar-icon-hover-bg-color:rgb(0 0 0); - - --sidebar-narrow-bg-color:rgb(212 212 215 / 0.9); - --sidebar-toolbar-bg-color:rgb(245 246 247); - --toolbar-bg-color:rgb(255, 255, 255); - --toolbar-border-color:#EBECF0; - --toolbar-box-shadow:0 1px 0 var(--toolbar-border-color); - --toolbar-border-bottom:none; - --toolbarSidebar-box-shadow:inset calc(-1px * var(--dir-factor)) 0 0 rgb(0 0 0 / 0.25), 0 1px 0 rgb(0 0 0 / 0.15), 0 0 1px rgb(0 0 0 / 0.1); - --toolbarSidebar-border-bottom:none; - --button-hover-color: #F4F5F9; - --toggled-btn-color:rgb(0 0 0); - --toggled-btn-bg-color:rgb(0 0 0 / 0.3); - --toggled-hover-active-btn-color:rgb(0 0 0 / 0.4); - --toggled-hover-btn-outline:none; - --dropdown-btn-bg-color:rgb(215 215 219); - --dropdown-btn-border:none; - --separator-color:rgb(0 0 0 / 0.3); - --field-color:rgb(6 6 6); - --field-bg-color:rgb(255 255 255); - --field-border-color:rgb(187 187 188); - --treeitem-color:rgb(0 0 0 / 0.8); - --treeitem-bg-color:rgb(0 0 0 / 0.15); - --treeitem-hover-color:rgb(0 0 0 / 0.9); - --treeitem-selected-color:rgb(0 0 0 / 0.9); - --treeitem-selected-bg-color:rgb(0 0 0 / 0.25); - --thumbnail-hover-color: #0D53DE; - --thumbnail-selected-color: #0D53DE; - --doorhanger-bg-color:rgb(255 255 255); - --doorhanger-border-color:rgb(12 12 13 / 0.2); - --doorhanger-hover-color:rgb(12 12 13); - --doorhanger-hover-bg-color:rgb(237 237 237); - --doorhanger-separator-color:rgb(222 222 222); - --dialog-button-border:none; - --dialog-button-bg-color:rgb(12 12 13 / 0.1); - --dialog-button-hover-bg-color:rgb(12 12 13 / 0.3); - - --loading-icon:url(images/loading.svg); - --treeitem-expanded-icon:url(images/treeitem-expanded.svg); - --treeitem-collapsed-icon:url(images/treeitem-collapsed.svg); - --toolbarButton-editorFreeText-icon:url(images/toolbarButton-editorFreeText.svg); - --toolbarButton-editorHighlight-icon:url(images/toolbarButton-editorHighlight.svg); - --toolbarButton-editorInk-icon:url(images/toolbarButton-editorInk.svg); - --toolbarButton-editorStamp-icon:url(images/toolbarButton-editorStamp.svg); - --toolbarButton-menuArrow-icon:url(images/toolbarButton-menuArrow.svg); - --toolbarButton-sidebarToggle-icon:url(images/toolbarButton-sidebarToggle.svg); - --toolbarButton-sidebarToggle-icon-open:url(images/toolbarButton-sidebarToggle-open.svg); - --toolbarButton-secondaryToolbarToggle-icon:url(images/toolbarButton-secondaryToolbarToggle.svg); - --toolbarButton-pageUp-icon:url(images/toolbarButton-pageUp.svg); - --toolbarButton-pageDown-icon:url(images/toolbarButton-pageDown.svg); - --toolbarButton-layerChange-icon:url(images/layer-button.svg); - --toolbarButton-layerChange-icon-show:url(images/layer-button-show.svg); - --toolbarButton-zoomOut-icon:url(images/toolbarButton-zoomOut.svg); - --toolbarButton-zoomIn-icon:url(images/toolbarButton-zoomIn.svg); - --toolbarButton-presentationMode-icon:url(images/toolbarButton-presentationMode.svg); - --toolbarButton-print-icon:url(images/toolbarButton-print.svg); - --toolbarButton-openFile-icon:url(images/toolbarButton-openFile.svg); - --toolbarButton-download-icon:url(images/toolbarButton-download.svg); - --toolbarButton-bookmark-icon:url(images/toolbarButton-bookmark.svg); - --toolbarButton-viewThumbnail-icon:url(images/toolbarButton-viewThumbnail.svg); - --toolbarButton-viewOutline-icon:url(images/toolbarButton-viewOutline.svg); - --toolbarButton-viewAttachments-icon:url(images/toolbarButton-viewAttachments.svg); - --toolbarButton-viewLayers-icon:url(images/toolbarButton-viewLayers.svg); - --toolbarButton-currentOutlineItem-icon:url(images/toolbarButton-currentOutlineItem.svg); - --toolbarButton-search-icon:url(images/toolbarButton-search.svg); - --findbarButton-previous-icon:url(images/findbarButton-previous.svg); - --findbarButton-next-icon:url(images/findbarButton-next.svg); - --secondaryToolbarButton-firstPage-icon:url(images/secondaryToolbarButton-firstPage.svg); - --secondaryToolbarButton-lastPage-icon:url(images/secondaryToolbarButton-lastPage.svg); - --secondaryToolbarButton-rotateCcw-icon:url(images/secondaryToolbarButton-rotateCcw.svg); - --secondaryToolbarButton-rotateCw-icon:url(images/secondaryToolbarButton-rotateCw.svg); - --secondaryToolbarButton-selectTool-icon:url(images/secondaryToolbarButton-selectTool.svg); - --secondaryToolbarButton-handTool-icon:url(images/secondaryToolbarButton-handTool.svg); - --secondaryToolbarButton-scrollPage-icon:url(images/secondaryToolbarButton-scrollPage.svg); - --secondaryToolbarButton-scrollVertical-icon:url(images/secondaryToolbarButton-scrollVertical.svg); - --secondaryToolbarButton-scrollHorizontal-icon:url(images/secondaryToolbarButton-scrollHorizontal.svg); - --secondaryToolbarButton-scrollWrapped-icon:url(images/secondaryToolbarButton-scrollWrapped.svg); - --secondaryToolbarButton-spreadNone-icon:url(images/secondaryToolbarButton-spreadNone.svg); - --secondaryToolbarButton-spreadOdd-icon:url(images/secondaryToolbarButton-spreadOdd.svg); - --secondaryToolbarButton-spreadEven-icon:url(images/secondaryToolbarButton-spreadEven.svg); - --secondaryToolbarButton-documentProperties-icon:url(images/secondaryToolbarButton-documentProperties.svg); - --editorParams-stampAddImage-icon:url(images/toolbarButton-zoomIn.svg); -} - -[dir="rtl"]:root{ - --dir-factor:-1; - --inline-start:right; - --inline-end:left; -} - -@media (prefers-color-scheme: dark){ - :root:where(:not(.is-dark)){ - // custom ban dark theme - /* --main-color:rgb(249 249 250); - --body-bg-color:rgb(42 42 46); - --progressBar-color:rgb(0 96 223); - --progressBar-bg-color:rgb(40 40 43); - --progressBar-blend-color:rgb(20 68 133); - --scrollbar-color:rgb(121 121 123); - --scrollbar-bg-color:rgb(35 35 39); - --toolbar-icon-bg-color:rgb(255 255 255); - --toolbar-icon-hover-bg-color:rgb(255 255 255); - - --sidebar-narrow-bg-color:rgb(42 42 46 / 0.9); - --sidebar-toolbar-bg-color:rgb(50 50 52); - --toolbar-bg-color:rgb(56 56 61); - --toolbar-border-color:rgb(12 12 13); - --button-hover-color: #F4F5F9; - --toggled-btn-color:rgb(255 255 255); - --toggled-btn-bg-color:rgb(0 0 0 / 0.3); - --toggled-hover-active-btn-color:rgb(0 0 0 / 0.4); - --dropdown-btn-bg-color:rgb(74 74 79); - --separator-color:rgb(0 0 0 / 0.3); - --field-color:rgb(250 250 250); - --field-bg-color:rgb(64 64 68); - --field-border-color:rgb(115 115 115); - --treeitem-color:rgb(255 255 255 / 0.8); - --treeitem-bg-color:rgb(255 255 255 / 0.15); - --treeitem-hover-color:rgb(255 255 255 / 0.9); - --treeitem-selected-color:rgb(255 255 255 / 0.9); - --treeitem-selected-bg-color:rgb(255 255 255 / 0.25); - --thumbnail-hover-color:rgb(255 255 255 / 0.1); - --thumbnail-selected-color:rgb(255 255 255 / 0.2); - --doorhanger-bg-color:rgb(74 74 79); - --doorhanger-border-color:rgb(39 39 43); - --doorhanger-hover-color:rgb(249 249 250); - --doorhanger-hover-bg-color:rgb(93 94 98); - --doorhanger-separator-color:rgb(92 92 97); - --dialog-button-bg-color:rgb(92 92 97); - --dialog-button-hover-bg-color:rgb(115 115 115); */ - } -} - -:root:where(.is-dark){ - --main-color:rgb(249 249 250); - --body-bg-color:rgb(42 42 46); - --progressBar-color:rgb(0 96 223); - --progressBar-bg-color:rgb(40 40 43); - --progressBar-blend-color:rgb(20 68 133); - --scrollbar-color:rgb(121 121 123); - --scrollbar-bg-color:rgb(35 35 39); - --toolbar-icon-bg-color:rgb(255 255 255); - --toolbar-icon-hover-bg-color:rgb(255 255 255); - - --sidebar-narrow-bg-color:rgb(42 42 46 / 0.9); - --sidebar-toolbar-bg-color:rgb(50 50 52); - --toolbar-bg-color:rgb(56 56 61); - --toolbar-border-color:rgb(12 12 13); - --button-hover-color: #F4F5F9; - --toggled-btn-color:rgb(255 255 255); - --toggled-btn-bg-color:rgb(0 0 0 / 0.3); - --toggled-hover-active-btn-color:rgb(0 0 0 / 0.4); - --dropdown-btn-bg-color:rgb(74 74 79); - --separator-color:rgb(0 0 0 / 0.3); - --field-color:rgb(250 250 250); - --field-bg-color:rgb(64 64 68); - --field-border-color:rgb(115 115 115); - --treeitem-color:rgb(255 255 255 / 0.8); - --treeitem-bg-color:rgb(255 255 255 / 0.15); - --treeitem-hover-color:rgb(255 255 255 / 0.9); - --treeitem-selected-color:rgb(255 255 255 / 0.9); - --treeitem-selected-bg-color:rgb(255 255 255 / 0.25); - --thumbnail-hover-color:rgb(255 255 255 / 0.1); - --thumbnail-selected-color:rgb(255 255 255 / 0.2); - --doorhanger-bg-color:rgb(74 74 79); - --doorhanger-border-color:rgb(39 39 43); - --doorhanger-hover-color:rgb(249 249 250); - --doorhanger-hover-bg-color:rgb(93 94 98); - --doorhanger-separator-color:rgb(92 92 97); - --dialog-button-bg-color:rgb(92 92 97); - --dialog-button-hover-bg-color:rgb(115 115 115); - } - -@media screen and (forced-colors: active){ - :root{ - --button-hover-color:#F4F5F9; - --doorhanger-hover-bg-color:Highlight; - --toolbar-icon-opacity:1; - --toolbar-icon-bg-color:ButtonText; - --toolbar-icon-hover-bg-color:ButtonFace; - --toggled-hover-active-btn-color:ButtonText; - --toggled-hover-btn-outline:2px solid ButtonBorder; - --toolbar-border-color:CanvasText; - --toolbar-border-bottom:1px solid var(--toolbar-border-color); - --toolbar-box-shadow:none; - --toggled-btn-color:HighlightText; - --toggled-btn-bg-color:LinkText; - --doorhanger-hover-color:ButtonFace; - --doorhanger-border-color-whcm:1px solid ButtonText; - --doorhanger-triangle-opacity-whcm:0; - --dialog-button-border:1px solid Highlight; - --dialog-button-hover-bg-color:Highlight; - --dialog-button-hover-color:ButtonFace; - --dropdown-btn-border:1px solid ButtonText; - --field-border-color:ButtonText; - --main-color:CanvasText; - --separator-color:GrayText; - --doorhanger-separator-color:GrayText; - --toolbarSidebar-box-shadow:none; - --toolbarSidebar-border-bottom:1px solid var(--toolbar-border-color); - } -} - -@media screen and (prefers-reduced-motion: reduce){ - :root{ - --sidebar-transition-duration:0; - } -} - -*{ - padding:0; - margin:0; -} - -html, -body{ - height:100%; - width:100%; -} - -body{ - background-color:var(--body-bg-color); - scrollbar-color:var(--scrollbar-color) var(--scrollbar-bg-color); -} - -.hidden, -[hidden]{ - display:none !important; -} - -#viewerContainer.pdfPresentationMode:fullscreen{ - top:0; - background-color:rgb(0 0 0); - width:100%; - height:100%; - overflow:hidden; - cursor:none; - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; -} - -.pdfPresentationMode:fullscreen section:not([data-internal-link]){ - pointer-events:none; -} - -.pdfPresentationMode:fullscreen .textLayer span{ - cursor:none; -} - -.pdfPresentationMode.pdfPresentationModeControls > *, -.pdfPresentationMode.pdfPresentationModeControls .textLayer span{ - cursor:default; -} - -#outerContainer{ - width:100%; - height:100%; - position:relative; -} - -#sidebarContainer{ - position:absolute; - inset-block:var(--toolbar-height) 0; - inset-inline-start:calc(-1 * var(--sidebar-width)); - width:var(--sidebar-width); - visibility:hidden; - z-index:100; - font:message-box; - border-top:1px solid rgb(51 51 51); - border-inline-end:var(--doorhanger-border-color-whcm); - transition-property:inset-inline-start; - transition-duration:var(--sidebar-transition-duration); - transition-timing-function:var(--sidebar-transition-timing-function); -} - -#outerContainer:is(.sidebarMoving, .sidebarOpen) #sidebarContainer{ - visibility:visible; -} -#outerContainer.sidebarOpen #sidebarContainer{ - inset-inline-start:0; -} - -#mainContainer{ - position:absolute; - inset:0; - min-width:350px; -} - -#sidebarContent{ - inset-block:0; - inset-inline-start:0; - overflow:auto; - position:absolute; - width:100%; - border-right: 1px solid #EBECF0; -} - -#viewerContainer{ - overflow:auto; - position:absolute; - inset:var(--toolbar-height) 0 0; - outline:none; - &::-webkit-scrollbar { - scrollbar-gutter: stable; - background: white !important; - width: 6px !important; - height: 6px !important; - } - - /* 滚动条里面轨道 */ - &::-webkit-scrollbar-track { - scrollbar-gutter: stable; - background: white !important; - } - - /* 滑块 */ - &::-webkit-scrollbar-thumb { - background-color: #EBECF0 !important; - scrollbar-gutter: stable; - border-radius: 10px; - } -} -#viewerContainer:not(.pdfPresentationMode){ - transition-duration:var(--sidebar-transition-duration); - transition-timing-function:var(--sidebar-transition-timing-function); -} - -#outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode){ - inset-inline-start:var(--sidebar-width); - transition-property:inset-inline-start; -} - -.toolbar{ - position:relative; - inset-inline:0; - z-index:9999; - cursor:default; - font:message-box; -} - -:is(.toolbar, .editorParamsToolbar, .findbar, #sidebarContainer) - :is(input, button, select), -.secondaryToolbar :is(input, button, a, select){ - outline:none; - font:message-box; -} - -#toolbarContainer{ - display: flex; - width:100%; -} - -#toolbarSidebar{ - width:100%; - height:32px; - background-color:var(--sidebar-toolbar-bg-color); - box-shadow:var(--toolbarSidebar-box-shadow); - border-bottom:var(--toolbarSidebar-border-bottom); -} - -#sidebarResizer{ - position:absolute; - inset-block:0; - inset-inline-end:-6px; - width:6px; - z-index:200; - cursor:ew-resize; -} - -#toolbarContainer, -.findbar, -.secondaryToolbar, -.editorParamsToolbar{ - position:relative; - height: var(--toolbar-height); - background-color:var(--toolbar-bg-color); - box-shadow:var(--toolbar-box-shadow); - border-bottom:var(--toolbar-border-bottom); -} - -#toolbarViewer{ - height: var(--toolbar-height); - display: flex; - align-items: center; - justify-content: center; - width: 100%; -} - -#loadingBar{ - --progressBar-percent:0%; - --progressBar-end-offset:0; - - position:absolute; - inset-inline:0 var(--progressBar-end-offset); - height:4px; - bottom: 0; - transform: translateY(100%); - background-color:var(--progressBar-bg-color); - border-bottom:0px solid var(--toolbar-border-color); - transition-property:inset-inline-start; - transition-duration:var(--sidebar-transition-duration); - transition-timing-function:var(--sidebar-transition-timing-function); -} - -#outerContainer.sidebarOpen #loadingBar{ - inset-inline-start:var(--sidebar-width); -} - -#loadingBar .progress{ - position:absolute; - top:0; - inset-inline-start:0; - width:100%; - transform:scaleX(var(--progressBar-percent)); - transform-origin:calc(50% - 50% * var(--dir-factor)) 0; - height:100%; - background-color:var(--progressBar-color); - overflow:hidden; - transition:transform 200ms; -} - -@keyframes progressIndeterminate{ - 0%{ - transform:translateX(calc(-142px * var(--dir-factor))); - } - 100%{ - transform:translateX(0); - } -} - -#loadingBar.indeterminate .progress{ - transform:none; - background-color:var(--progressBar-bg-color); - transition:none; -} - -#loadingBar.indeterminate .progress .glimmer{ - position:absolute; - top:0; - inset-inline-start:0; - height:100%; - width:calc(100% + 150px); - background:repeating-linear-gradient( - 135deg, - var(--progressBar-blend-color) 0, - var(--progressBar-bg-color) 5px, - var(--progressBar-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-blend-color) 100px - ); - animation:progressIndeterminate 1s linear infinite; -} - -#outerContainer.sidebarResizing - :is(#sidebarContainer, #viewerContainer, #loadingBar){ - transition-duration:0s; -} - -.findbar, -.secondaryToolbar, -.editorParamsToolbar{ - top:32px; - position:absolute; - z-index:30000; - height:auto; - padding:0 4px; - margin:4px 2px; - font:message-box; - font-size:12px; - line-height:14px; - text-align:left; - cursor:default; -} - -.findbar{ - inset-inline-start:64px; - min-width:300px; - background-color:var(--toolbar-bg-color); -} -.findbar > div{ - height:32px; -} -.findbar > div#findbarInputContainer{ - margin-inline-end:4px; -} -.findbar.wrapContainers > div, -.findbar.wrapContainers > div#findbarMessageContainer > *{ - clear:both; -} -.findbar.wrapContainers > div#findbarMessageContainer{ - height:auto; -} - -.findbar input[type="checkbox"]{ - pointer-events:none; -} - -.findbar label{ - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; -} - -.findbar label:hover, -.findbar input:focus-visible + label{ - color:var(--toggled-btn-color); - background-color:var(--button-hover-color); -} - -.findbar .toolbarField[type="checkbox"]:checked + .toolbarLabel{ - background-color:var(--toggled-btn-bg-color) !important; - color:var(--toggled-btn-color); -} - -#findInput{ - width:200px; -} - -#findInput::-moz-placeholder{ - font-style:normal; - } - -#findInput::placeholder{ - font-style:normal; - } - -.loadingInput:has(> #findInput[data-status="pending"])::after{ - display:block; - visibility:visible; - } - -#findInput[data-status="notFound"]{ - background-color:rgb(255 102 102); - } - -.secondaryToolbar, -.editorParamsToolbar{ - padding:6px 0 10px; - inset-inline-end:4px; - height:auto; - background-color:var(--doorhanger-bg-color); -} - -.editorParamsToolbarContainer{ - width:220px; - margin-bottom:-4px; -} - -.editorParamsToolbarContainer > .editorParamsSetter{ - min-height:26px; - display:flex; - align-items:center; - justify-content:space-between; - padding-inline:10px; -} - -.editorParamsToolbarContainer .editorParamsLabel{ - padding-inline-end:10px; - flex:none; - font:menu; - font-size:13px; - font-style:normal; - font-weight:400; - line-height:150%; - color:var(--main-color); -} - -.editorParamsToolbarContainer .editorParamsColor{ - width:32px; - height:32px; - flex:none; -} - -.editorParamsToolbarContainer .editorParamsSlider{ - background-color:transparent; - width:90px; - flex:0 1 0; -} - -.editorParamsToolbarContainer .editorParamsSlider::-moz-range-progress{ - background-color:black; -} - -.editorParamsToolbarContainer .editorParamsSlider::-webkit-slider-runnable-track, -.editorParamsToolbarContainer .editorParamsSlider::-moz-range-track{ - background-color:black; -} - -.editorParamsToolbarContainer .editorParamsSlider::-webkit-slider-thumb, -.editorParamsToolbarContainer .editorParamsSlider::-moz-range-thumb{ - background-color:white; -} - -#secondaryToolbarButtonContainer{ - max-width:220px; - min-height:26px; - max-height:calc(var(--viewer-container-height) - 40px); - overflow-y:auto; - margin-bottom:-4px; -} - -#editorStampParamsToolbar{ - inset-inline-end:calc(var(--editor-toolbar-base-offset) + 0px); -} - -#editorInkParamsToolbar{ - inset-inline-end:calc(var(--editor-toolbar-base-offset) + 28px); -} - -#editorFreeTextParamsToolbar{ - inset-inline-end:calc(var(--editor-toolbar-base-offset) + 56px); -} - -#editorHighlightParamsToolbar{ - inset-inline-end:calc(var(--editor-toolbar-base-offset) + 84px); -} - -#editorStampAddImage::before{ - -webkit-mask-image:var(--editorParams-stampAddImage-icon); - mask-image:var(--editorParams-stampAddImage-icon); -} - -.doorHanger, -.doorHangerRight{ - border-radius:2px; - box-shadow:0 1px 5px var(--doorhanger-border-color), 0 0 0 1px var(--doorhanger-border-color); - border:var(--doorhanger-border-color-whcm); -} -:is(.doorHanger, .doorHangerRight)::after, -:is(.doorHanger, .doorHangerRight)::before{ - bottom:100%; - border:8px solid rgb(0 0 0 / 0); - content:" "; - height:0; - width:0; - position:absolute; - pointer-events:none; - opacity:var(--doorhanger-triangle-opacity-whcm); -} -.doorHanger::after{ - inset-inline-start:10px; - margin-inline-start:-8px; - border-bottom-color:var(--toolbar-bg-color); -} -.doorHangerRight::after{ - inset-inline-end:10px; - margin-inline-end:-8px; - border-bottom-color:var(--doorhanger-bg-color); -} -:is(.doorHanger, .doorHangerRight)::before{ - border-bottom-color:var(--doorhanger-border-color); - border-width:9px; -} -.doorHanger::before{ - inset-inline-start:10px; - margin-inline-start:-9px; -} -.doorHangerRight::before{ - inset-inline-end:10px; - margin-inline-end:-9px; -} - -#findResultsCount{ - background-color:rgb(217 217 217); - color:rgb(82 82 82); - text-align:center; - padding:4px 5px; - margin:5px; -} - -#findMsg[data-status="notFound"]{ - font-weight:bold; -} - -:is(#findResultsCount, #findMsg):empty{ - display:none; -} - -#toolbarViewerMiddle{ - margin-left:auto; - left:auto; - margin-right:16px; -} - -#toolbarViewerLeft, -#toolbarSidebarLeft{ - float:var(--inline-start); -} -#toolbarViewerRight, -#toolbarSidebarRight{ - float:var(--inline-end); -} - -#toolbarViewerLeft > *, -#toolbarViewerMiddle > *, -#toolbarViewerRight > *, -#toolbarSidebarLeft *, -#toolbarSidebarRight *, -.findbar *{ - position:relative; - float:var(--inline-start); -} - -#toolbarViewerLeft{ - padding-inline-start:1px; - width: calc(50% - 120px); -} -#toolbarViewerRight{ - padding-inline-end:1px; - z-index: 99; - position: absolute; - right: 0; - -} -#toolbarSidebarRight{ - padding-inline-end:2px; -} - -.splitToolbarButton{ - display: flex; - align-items: center; - white-space: nowrap; -} - -.odlPageControl { - position: absolute; - left: calc(50% - 14px); - transform: translateX(-50%); -} - -.splitToolbarButton > .toolbarButton{ - cursor: pointer; - float:var(--inline-start); -} - -.toolbarButton, -.secondaryToolbarButton, -.dialogButton{ - border:none; - background:none; - width:16px; - height: 16px; - outline:none; -} - -.dialogButton:is(:hover, :focus-visible){ - background-color:var(--dialog-button-hover-bg-color); -} - -.dialogButton:is(:hover, :focus-visible) > span{ - color:var(--dialog-button-hover-color); -} - -.toolbarButton > span{ - display:inline-block; - width:0; - height:0; - overflow:hidden; -} - -:is(.toolbarButton, .secondaryToolbarButton, .dialogButton)[disabled]{ - opacity:0.5; -} - -.splitToolbarButton > .toolbarButton:is(:hover, :focus-visible), -.dropdownToolbarButton:hover{ - background-color:var(--button-hover-color); -} -.splitToolbarButton > .toolbarButton{ - position:relative; - margin:0; -} -#toolbarSidebar .splitToolbarButton > .toolbarButton{ - margin-inline-end:2px; -} - -.splitToolbarButtonSeparator{ - float:var(--inline-start); - margin:4px 0; - width:1px; - height:20px; - background-color:var(--separator-color); -} - -.toolbarButton, -.dropdownToolbarButton, -.secondaryToolbarButton, -.dialogButton{ - min-width:16px; - margin:2px 1px; - border:none; - border-radius:2px; - color:var(--main-color); - font-size:12px; - line-height:14px; - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; - cursor:default; - box-sizing:border-box; -} - -.toolbarButton { - min-width:12px; -} - -.toolbarButton:is(:hover, :focus-visible){ - background-color:var(--button-hover-color); -} -.secondaryToolbarButton:is(:hover, :focus-visible){ - background-color:var(--doorhanger-hover-bg-color); - color:var(--doorhanger-hover-color); -} - -:is(.toolbarButton, .secondaryToolbarButton).toggled, -.splitToolbarButton.toggled > .toolbarButton.toggled{ - background-color:var(--toggled-btn-bg-color); - color:var(--toggled-btn-color); -} - -:is(.toolbarButton, .secondaryToolbarButton).toggled:hover, -.splitToolbarButton.toggled > .toolbarButton.toggled:hover{ - outline:var(--toggled-hover-btn-outline) !important; -} - -:is(.toolbarButton, .secondaryToolbarButton).toggled::before{ - background-color:var(--toggled-btn-color); -} - -:is(.toolbarButton, .secondaryToolbarButton).toggled:hover:active, -.splitToolbarButton.toggled > .toolbarButton.toggled:hover:active{ - background-color:var(--toggled-hover-active-btn-color); -} - -.dropdownToolbarButton{ - display:flex; - width:-moz-fit-content; - width:fit-content; - min-width:140px; - padding:0; - background-color:var(--dropdown-btn-bg-color); - border:var(--dropdown-btn-border); -} -.dropdownToolbarButton::after{ - top:6px; - inset-inline-end:6px; - pointer-events:none; - -webkit-mask-image:var(--toolbarButton-menuArrow-icon); - mask-image:var(--toolbarButton-menuArrow-icon); -} - -.dropdownToolbarButton > select{ - -webkit-appearance:none; - -moz-appearance:none; - appearance:none; - width:inherit; - min-width:inherit; - height:28px; - font-size:12px; - color:var(--main-color); - margin:0; - padding-block:1px 2px; - padding-inline:6px 38px; - border:none; - background-color:var(--dropdown-btn-bg-color); -} -.dropdownToolbarButton > select:is(:hover, :focus-visible){ - background-color:var(--button-hover-color); - color:var(--toggled-btn-color); -} -.dropdownToolbarButton > select > option{ - background:var(--doorhanger-bg-color); - color:var(--main-color); -} - -.toolbarButtonSpacer{ - width:30px; - display:inline-block; - height:1px; -} - -:is(.toolbarButton, .secondaryToolbarButton, .treeItemToggler)::before, -.dropdownToolbarButton::after{ - position:absolute; - display:inline-block; - width:16px; - height:16px; - - content:""; - background-color:var(--toolbar-icon-bg-color); - -webkit-mask-size:cover; - mask-size:cover; -} - -.dropdownToolbarButton:is(:hover, :focus-visible, :active)::after{ - background-color:var(--toolbar-icon-hover-bg-color); -} - -.toolbarButton::before{ - opacity:var(--toolbar-icon-opacity); - top:0px; - left: 0px; -} - -.toolbarButton:is(:hover, :focus-visible)::before, -.secondaryToolbarButton:is(:hover, :focus-visible)::before{ - background-color:var(--toolbar-icon-hover-bg-color); -} - -.secondaryToolbarButton::before{ - opacity:var(--doorhanger-icon-opacity); - top:5px; - inset-inline-start:12px; -} - -#sidebarToggle::before{ - -webkit-mask-image:var(--toolbarButton-sidebarToggle-icon); - mask-image:var(--toolbarButton-sidebarToggle-icon); - transform:scaleX(var(--dir-factor)); - margin-left: 1px; - margin-top: 1px; -} - -#secondaryToolbarToggle::before{ - -webkit-mask-image:var(--toolbarButton-secondaryToolbarToggle-icon); - mask-image:var(--toolbarButton-secondaryToolbarToggle-icon); - transform:scaleX(var(--dir-factor)); -} - -#findPrevious::before{ - -webkit-mask-image:var(--findbarButton-previous-icon); - mask-image:var(--findbarButton-previous-icon); -} - -#findNext::before{ - -webkit-mask-image:var(--findbarButton-next-icon); - mask-image:var(--findbarButton-next-icon); -} - -#previous::before{ - -webkit-mask-image:var(--toolbarButton-pageUp-icon); - mask-image:var(--toolbarButton-pageUp-icon); -} - -#next::before{ - -webkit-mask-image:var(--toolbarButton-pageDown-icon); - mask-image:var(--toolbarButton-pageDown-icon); -} - -#splitLine { - width: 1px; - height: 12px; - background: #D7D8DD; - margin-right: 16px; - margin-top: 2px; -} - -/* custom layerChange icon */ - -#layerChange { - margin-right: 16px; -} - -#layerChange::before{ - cursor: pointer; - -webkit-mask-image:var(--toolbarButton-layerChange-icon-show); - mask-image:var(--toolbarButton-layerChange-icon-show); -} - -.layerChange-active::before { - cursor: pointer; - -webkit-mask-image:var(--toolbarButton-layerChange-icon) !important; - mask-image:var(--toolbarButton-layerChange-icon) !important; - -} - - -#zoomOut::before{ - cursor: pointer; - -webkit-mask-image:var(--toolbarButton-zoomOut-icon); - mask-image:var(--toolbarButton-zoomOut-icon); -} - -#zoomIn::before{ - cursor: pointer; - -webkit-mask-image:var(--toolbarButton-zoomIn-icon); - mask-image:var(--toolbarButton-zoomIn-icon); -} - -#presentationMode::before{ - -webkit-mask-image:var(--toolbarButton-presentationMode-icon); - mask-image:var(--toolbarButton-presentationMode-icon); -} - -#editorFreeText::before{ - -webkit-mask-image:var(--toolbarButton-editorFreeText-icon); - mask-image:var(--toolbarButton-editorFreeText-icon); -} - -#editorHighlight::before{ - -webkit-mask-image:var(--toolbarButton-editorHighlight-icon); - mask-image:var(--toolbarButton-editorHighlight-icon); -} - -#editorInk::before{ - -webkit-mask-image:var(--toolbarButton-editorInk-icon); - mask-image:var(--toolbarButton-editorInk-icon); -} - -#editorStamp::before{ - -webkit-mask-image:var(--toolbarButton-editorStamp-icon); - mask-image:var(--toolbarButton-editorStamp-icon); -} - -:is(#print, #secondaryPrint)::before{ - -webkit-mask-image:var(--toolbarButton-print-icon); - mask-image:var(--toolbarButton-print-icon); -} - -#secondaryOpenFile::before{ - -webkit-mask-image:var(--toolbarButton-openFile-icon); - mask-image:var(--toolbarButton-openFile-icon); -} - -:is(#download, #secondaryDownload)::before{ - -webkit-mask-image:var(--toolbarButton-download-icon); - mask-image:var(--toolbarButton-download-icon); -} - -a.secondaryToolbarButton{ - padding-top:5px; - text-decoration:none; -} -a:is(.toolbarButton, .secondaryToolbarButton)[href="#"]{ - opacity:0.5; - pointer-events:none; -} - -#viewBookmark::before{ - -webkit-mask-image:var(--toolbarButton-bookmark-icon); - mask-image:var(--toolbarButton-bookmark-icon); -} - -#viewThumbnail::before{ - -webkit-mask-image:var(--toolbarButton-viewThumbnail-icon); - mask-image:var(--toolbarButton-viewThumbnail-icon); -} - -#viewOutline::before{ - -webkit-mask-image:var(--toolbarButton-viewOutline-icon); - mask-image:var(--toolbarButton-viewOutline-icon); - transform:scaleX(var(--dir-factor)); -} - -#viewAttachments::before{ - -webkit-mask-image:var(--toolbarButton-viewAttachments-icon); - mask-image:var(--toolbarButton-viewAttachments-icon); -} - -#viewLayers::before{ - -webkit-mask-image:var(--toolbarButton-viewLayers-icon); - mask-image:var(--toolbarButton-viewLayers-icon); -} - -#currentOutlineItem::before{ - -webkit-mask-image:var(--toolbarButton-currentOutlineItem-icon); - mask-image:var(--toolbarButton-currentOutlineItem-icon); - transform:scaleX(var(--dir-factor)); -} - -#viewFind::before{ - -webkit-mask-image:var(--toolbarButton-search-icon); - mask-image:var(--toolbarButton-search-icon); -} - -.pdfSidebarNotification::after{ - position:absolute; - display:inline-block; - top:2px; - inset-inline-end:2px; - content:""; - background-color:rgb(112 219 85); - height:9px; - width:9px; - border-radius:50%; - /* [custom] */ - display: none; -} - -.secondaryToolbarButton{ - position:relative; - margin:0; - padding:0 0 1px; - padding-inline-start:36px; - height:auto; - min-height:26px; - width:auto; - min-width:100%; - text-align:start; - white-space:normal; - border-radius:0; - box-sizing:border-box; - display:inline-block; -} -.secondaryToolbarButton > span{ - padding-inline-end:4px; -} - -#firstPage::before{ - -webkit-mask-image:var(--secondaryToolbarButton-firstPage-icon); - mask-image:var(--secondaryToolbarButton-firstPage-icon); -} - -#lastPage::before{ - -webkit-mask-image:var(--secondaryToolbarButton-lastPage-icon); - mask-image:var(--secondaryToolbarButton-lastPage-icon); -} - -#pageRotateCcw::before{ - -webkit-mask-image:var(--secondaryToolbarButton-rotateCcw-icon); - mask-image:var(--secondaryToolbarButton-rotateCcw-icon); -} - -#pageRotateCw::before{ - -webkit-mask-image:var(--secondaryToolbarButton-rotateCw-icon); - mask-image:var(--secondaryToolbarButton-rotateCw-icon); -} - -#cursorSelectTool::before{ - -webkit-mask-image:var(--secondaryToolbarButton-selectTool-icon); - mask-image:var(--secondaryToolbarButton-selectTool-icon); -} - -#cursorHandTool::before{ - -webkit-mask-image:var(--secondaryToolbarButton-handTool-icon); - mask-image:var(--secondaryToolbarButton-handTool-icon); -} - -#scrollPage::before{ - -webkit-mask-image:var(--secondaryToolbarButton-scrollPage-icon); - mask-image:var(--secondaryToolbarButton-scrollPage-icon); -} - -#scrollVertical::before{ - -webkit-mask-image:var(--secondaryToolbarButton-scrollVertical-icon); - mask-image:var(--secondaryToolbarButton-scrollVertical-icon); -} - -#scrollHorizontal::before{ - -webkit-mask-image:var(--secondaryToolbarButton-scrollHorizontal-icon); - mask-image:var(--secondaryToolbarButton-scrollHorizontal-icon); -} - -#scrollWrapped::before{ - -webkit-mask-image:var(--secondaryToolbarButton-scrollWrapped-icon); - mask-image:var(--secondaryToolbarButton-scrollWrapped-icon); -} - -#spreadNone::before{ - -webkit-mask-image:var(--secondaryToolbarButton-spreadNone-icon); - mask-image:var(--secondaryToolbarButton-spreadNone-icon); -} - -#spreadOdd::before{ - -webkit-mask-image:var(--secondaryToolbarButton-spreadOdd-icon); - mask-image:var(--secondaryToolbarButton-spreadOdd-icon); -} - -#spreadEven::before{ - -webkit-mask-image:var(--secondaryToolbarButton-spreadEven-icon); - mask-image:var(--secondaryToolbarButton-spreadEven-icon); -} - -#documentProperties::before{ - -webkit-mask-image:var(--secondaryToolbarButton-documentProperties-icon); - mask-image:var(--secondaryToolbarButton-documentProperties-icon); -} - -.verticalToolbarSeparator{ - display:block; - margin:5px 2px; - width:1px; - height:22px; - background-color:var(--separator-color); -} -.horizontalToolbarSeparator{ - display:block; - margin:6px 0; - height:1px; - width:100%; - background-color:var(--doorhanger-separator-color); -} - -.toolbarField{ - padding:1px 7px; - margin:3px 2px; - border-radius:2px; - background-color:var(--field-bg-color); - background-clip:padding-box; - border:1px solid var(--field-border-color); - box-shadow:none; - color:var(--field-color); - outline:none; -} - -.toolbarField[type="checkbox"]{ - opacity:0; - position:absolute !important; - left:0; - margin:10px 0 3px; - margin-inline-start:7px; -} - - -#pageNumber{ - -moz-appearance:textfield; - text-align:center; - width: fit-content !important; - background-size:0 0; - font-size: 14px !important; - transition-property:none; - margin-top: 6px; -} - -#pageNumber::-webkit-inner-spin-button{ - -webkit-appearance:none; - } - -.loadingInput:has(> #pageNumber.loading)::after{ - display:block; - visibility:visible; - - transition-property:visibility; - transition-delay:var(--loading-icon-delay); - } - -.loadingInput::after{ - position:absolute; - visibility:hidden; - display:none; - top:calc(50% - 8px); - width:16px; - height:16px; - - content:""; - background-color:var(--toolbar-icon-bg-color); - -webkit-mask-size:cover; - mask-size:cover; - -webkit-mask-image:var(--loading-icon); - mask-image:var(--loading-icon); - } - -.loadingInput.start::after{ - inset-inline-start:4px; - } - -.loadingInput.end::after{ - inset-inline-end:4px; - } - -.toolbarField:focus{ - border-color:#0a84ff; -} - -.toolbarLabel{ - min-width:16px; - padding:7px; - margin:2px; - padding-top: 10px; - border-radius:2px; - color:var(--main-color); - font-size:12px; - line-height:14px; - text-align:left; - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; - cursor:default; -} - - -#numPages.toolbarLabel{ - min-width: var(--num-page-width); - margin-right: -4px; - padding-inline-start:3px; - font-size: 14px; -} - -#thumbnailView, -#outlineView, -#attachmentsView, -#layersView{ - position:absolute; - width:calc(100% - 8px); - inset-block:0; - padding:4px 4px 0; - overflow:auto; - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; -} -#thumbnailView{ - width: 100%; - padding:10px 0px 0; - background-color: white; - display: flex; - flex-direction: column; - align-items: center; - - /* 滚动条整体部分 */ - &::-webkit-scrollbar { - scrollbar-gutter: stable; - background: white !important; - width: 6px !important; - height: 6px !important; - } - - /* 滚动条里面轨道 */ - &::-webkit-scrollbar-track { - scrollbar-gutter: stable; - background: white !important; - } - - /* 滑块 */ - &::-webkit-scrollbar-thumb { - background-color: #EBECF0 !important; - scrollbar-gutter: stable; - border-radius: 10px; - } - - & > a { - text-decoration: none; - } -} - -#thumbnailView > a:is(:active, :focus){ - outline:0; -} - -.thumbnail{ - --thumbnail-width:0; - --thumbnail-height:0; - - float:var(--inline-start); - width:var(--thumbnail-width); - height:var(--thumbnail-height); - margin:0 0px 8px; - padding:1px; - border:1px solid #EBECF0; - border-radius:4px; -} - -#thumbnailView > a:last-of-type > .thumbnail{ - margin-bottom:10px; -} - -/* a:focus > .thumbnail, -.thumbnail:hover{ - border-color:var(--thumbnail-hover-color); -} */ - -a:hover > .thumbnail, -.thumbnail:hover{ - border-color:var(--thumbnail-hover-color); -} - -.thumbnail.selected{ - border-color:var(--thumbnail-selected-color) !important; -} - -.thumbnailImage{ - width:var(--thumbnail-width); - height:var(--thumbnail-height); - opacity:0.9; -} -a:focus > .thumbnail > .thumbnailImage, -.thumbnail:hover > .thumbnailImage{ - opacity:0.95; -} -.thumbnail.selected > .thumbnailImage{ - opacity:1 !important; -} - -.thumbnail:not([data-loaded]) > .thumbnailImage{ - width:calc(var(--thumbnail-width) - 2px); - height:calc(var(--thumbnail-height) - 2px); - border:1px dashed rgb(132 132 132); -} - -.treeWithDeepNesting > .treeItem, -.treeItem > .treeItems{ - margin-inline-start:20px; -} - -.treeItem > a{ - text-decoration:none; - display:inline-block; - min-width:calc(100% - 4px); - height:auto; - margin-bottom:1px; - padding:2px 0 5px; - padding-inline-start:4px; - border-radius:2px; - color:var(--treeitem-color); - font-size:13px; - line-height:15px; - -webkit-user-select:none; - -moz-user-select:none; - user-select:none; - white-space:normal; - cursor:pointer; -} - -#layersView .treeItem > a *{ - cursor:pointer; -} -#layersView .treeItem > a > label{ - padding-inline-start:4px; -} -#layersView .treeItem > a > label > input{ - float:var(--inline-start); - margin-top:1px; -} - -.treeItemToggler{ - position:relative; - float:var(--inline-start); - height:0; - width:0; - color:rgb(255 255 255 / 0.5); -} -.treeItemToggler::before{ - inset-inline-end:4px; - -webkit-mask-image:var(--treeitem-expanded-icon); - mask-image:var(--treeitem-expanded-icon); -} -.treeItemToggler.treeItemsHidden::before{ - -webkit-mask-image:var(--treeitem-collapsed-icon); - mask-image:var(--treeitem-collapsed-icon); - transform:scaleX(var(--dir-factor)); -} -.treeItemToggler.treeItemsHidden ~ .treeItems{ - display:none; -} - -.treeItem.selected > a{ - background-color:var(--treeitem-selected-bg-color); - color:var(--treeitem-selected-color); -} - -.treeItemToggler:hover, -.treeItemToggler:hover + a, -.treeItemToggler:hover ~ .treeItems, -.treeItem > a:hover{ - background-color:var(--treeitem-bg-color); - background-clip:padding-box; - border-radius:2px; - color:var(--treeitem-hover-color); -} - -#outlineOptionsContainer{ - display:none; -} - -#sidebarContainer:has(#outlineView:not(.hidden)) #outlineOptionsContainer{ - display:inherit; - } - -.dialogButton{ - width:auto; - margin:3px 4px 2px !important; - padding:2px 11px; - color:var(--main-color); - background-color:var(--dialog-button-bg-color); - border:var(--dialog-button-border) !important; -} - -dialog{ - margin:auto; - padding:15px; - border-spacing:4px; - color:var(--main-color); - font:message-box; - font-size:12px; - line-height:14px; - background-color:var(--doorhanger-bg-color); - border:1px solid rgb(0 0 0 / 0.5); - border-radius:4px; - box-shadow:0 1px 4px rgb(0 0 0 / 0.3); -} -dialog::backdrop{ - background-color:rgb(0 0 0 / 0.2); -} - -dialog > .row{ - display:table-row; -} - -dialog > .row > *{ - display:table-cell; -} - -dialog .toolbarField{ - margin:5px 0; -} - -dialog .separator{ - display:block; - margin:4px 0; - height:1px; - width:100%; - background-color:var(--separator-color); -} - -dialog .buttonRow{ - text-align:center; - vertical-align:middle; -} - -dialog :link{ - color:rgb(255 255 255); -} - -#passwordDialog{ - text-align:center; -} -#passwordDialog .toolbarField{ - width:200px; -} - -#documentPropertiesDialog{ - text-align:left; -} -#documentPropertiesDialog .row > *{ - min-width:100px; - text-align:start; -} -#documentPropertiesDialog .row > span{ - width:125px; - word-wrap:break-word; -} -#documentPropertiesDialog .row > p{ - max-width:225px; - word-wrap:break-word; -} -#documentPropertiesDialog .buttonRow{ - margin-top:10px; -} - -.grab-to-pan-grab{ - cursor:grab !important; -} -.grab-to-pan-grab - *:not(input):not(textarea):not(button):not(select):not(:link){ - cursor:inherit !important; -} -.grab-to-pan-grab:active, -.grab-to-pan-grabbing{ - cursor:grabbing !important; -} -.grab-to-pan-grabbing{ - position:fixed; - background:rgb(0 0 0 / 0); - display:block; - inset:0; - overflow:hidden; - z-index:50000; -} - -@page{ - margin:0; -} - -#printContainer{ - display:none; -} - -@media print{ - body{ - background:rgb(0 0 0 / 0) none; - } - body[data-pdfjsprinting] #outerContainer{ - display:none; - } - body[data-pdfjsprinting] #printContainer{ - display:block; - } - #printContainer{ - height:100%; - } - #printContainer > .printedPage{ - page-break-after:always; - page-break-inside:avoid; - height:100%; - width:100%; - - display:flex; - flex-direction:column; - justify-content:center; - align-items:center; - } - - #printContainer > .xfaPrintedPage .xfaPage{ - position:absolute; - } - - #printContainer > .xfaPrintedPage{ - page-break-after:always; - page-break-inside:avoid; - width:100%; - height:100%; - position:relative; - } - - #printContainer > .printedPage :is(canvas, img){ - max-width:100%; - max-height:100%; - - direction:ltr; - display:block; - } -} - -.visibleMediumView{ - display:none; -} - -@media all and (max-width: 900px){ - -} - -@media all and (max-width: 840px){ - #sidebarContainer{ - background-color:var(--sidebar-narrow-bg-color); - } - #outerContainer.sidebarOpen #viewerContainer{ - inset-inline-start:0 !important; - } -} - -@media all and (max-width: 750px){ - :root{ - --editor-toolbar-base-offset:40px; - } - #outerContainer .hiddenMediumView{ - display:none; - } - #outerContainer .visibleMediumView{ - display:inherit; - } -} - -@media all and (max-width: 690px){ - .hiddenSmallView, - .hiddenSmallView *{ - /* display:none; */ - } - .toolbarButtonSpacer{ - width:0; - } - .findbar{ - inset-inline-start:34px; - } -} - -@media all and (max-width: 560px){ - #scaleSelectContainer{ - display:none; - } -} - -#odlCustomRatio { - min-width: 10px; -} - -#scaleSelect { - border: none; - background: transparent; -} - -.odlImageNum { - text-align: center; - text-decoration: none; - margin-bottom: 8px; - color: rgba(18, 19, 22, 0.80); -} - -.odl_selected { - & > .odlImageNum { - color: var(--thumbnail-selected-color); - } -} - -#odlScale { - font-size: 14px; - margin: 2px 8px 0; - user-select: none; -} - -#toolbarViewerLeft { - display: flex; - align-items: center; -} - -#sidebarToggle { - width: 20px; - height: 20px; - margin-left: 16px; - cursor: pointer; -} - -#sidebarToggle::before,.toggled::before { - width: 18px !important; - height: 18px !important; -} - -#sidebarToggle { - margin-right: 8px; - &:active { - background-color: #F4F5F9 !important; - } -} - -#sidebarToggle.toggled { - background-color: #F4F5F9; - border-radius: 2px; - width: 20px !important; - height: 20px !important; -} - -#sidebarToggle.toggled::before { - -webkit-mask-image:var(--toolbarButton-sidebarToggle-icon) !important; - mask-image:var(--toolbarButton-sidebarToggle-icon) !important; - width: 18px !important; - height: 18px !important; - margin-left: 1px; - margin-top: 1px; - -} - -#sidebarToggle:is(:hover, :focus-visible) { - border-radius: 2px; -} - -#odl-pdf-title { - margin-left: 8px; - margin-top: 1px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: calc(100%) -} - - -@media all and (max-width: 690px){ - #odl-pdf-title { - max-width: 160px; - - } -} diff --git a/projects/web/public/pdfjs-dist/web/viewer.html b/projects/web/public/pdfjs-dist/web/viewer.html deleted file mode 100644 index aef3ff2fba2a09fa2eda126c3ee8f7910a01bc1b..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/viewer.html +++ /dev/null @@ -1,557 +0,0 @@ - - - - - - - - PDF.js viewer - - - - - - - - - - - - - - -
    -
    - -
    -
    -
    - - - -
    -
    -
    - -
    - - - - - - - - - - - - -
    -
    -
    -
    - - -
    - - - -
    -
    - - - - - - -
    -
    - - - - - - - - -
    -
    -
    - - - -
    - - -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - -
    - -
    - -
    -
    - -
    -
    - - -
    -
    - -
    - File name: -

    -

    -
    -
    - File size: -

    -

    -
    -
    -
    - Title: -

    -

    -
    -
    - Author: -

    -

    -
    -
    - Subject: -

    -

    -
    -
    - Keywords: -

    -

    -
    -
    - Creation Date: -

    -

    -
    -
    - Modification Date: -

    -

    -
    -
    - Creator: -

    -

    -
    -
    -
    - PDF Producer: -

    -

    -
    -
    - PDF Version: -

    -

    -
    -
    - Page Count: -

    -

    -
    -
    - Page Size: -

    -

    -
    -
    -
    - Fast Web View: -

    -

    -
    -
    - -
    -
    - -
    -
    - Choose an option - - Alt text (alternative text) helps when people can’t see the image or when it doesn’t load. - -
    -
    -
    -
    - - -
    -
    - - Aim for 1-2 sentences that describe the subject, setting, or actions. - -
    -
    -
    - -
    -
    -
    -
    -
    - - -
    -
    - - This is used for ornamental images, like borders or watermarks. - -
    -
    -
    -
    - - -
    -
    -
    - -
    - Preparing document for printing… -
    -
    - - 0% -
    -
    - -
    -
    -
    - -
    -
    - - diff --git a/projects/web/public/pdfjs-dist/web/viewer.mjs b/projects/web/public/pdfjs-dist/web/viewer.mjs deleted file mode 100644 index 1e8e13342149354f276bb77156360c83189231cd..0000000000000000000000000000000000000000 --- a/projects/web/public/pdfjs-dist/web/viewer.mjs +++ /dev/null @@ -1,15477 +0,0 @@ -/** - * @licstart The following is the entire license notice for the - * JavaScript code in this page - * - * Copyright 2023 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @licend The above is the entire license notice for the - * JavaScript code in this page - */ - -/******/ var __webpack_modules__ = ({ - -/***/ 588: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - - -// EXPORTS -__webpack_require__.d(__webpack_exports__, { - FluentBundle: () => (/* reexport */ FluentBundle), - FluentResource: () => (/* reexport */ FluentResource) -}); - -// UNUSED EXPORTS: FluentDateTime, FluentNone, FluentNumber, FluentType - -;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/types.js -class FluentType { - constructor(value) { - this.value = value; - } - valueOf() { - return this.value; - } -} -class FluentNone extends FluentType { - constructor(value = "???") { - super(value); - } - toString(scope) { - return `{${this.value}}`; - } -} -class FluentNumber extends FluentType { - constructor(value, opts = {}) { - super(value); - this.opts = opts; - } - toString(scope) { - try { - const nf = scope.memoizeIntlObject(Intl.NumberFormat, this.opts); - return nf.format(this.value); - } catch (err) { - scope.reportError(err); - return this.value.toString(10); - } - } -} -class FluentDateTime extends FluentType { - constructor(value, opts = {}) { - super(value); - this.opts = opts; - } - toString(scope) { - try { - const dtf = scope.memoizeIntlObject(Intl.DateTimeFormat, this.opts); - return dtf.format(this.value); - } catch (err) { - scope.reportError(err); - return new Date(this.value).toISOString(); - } - } -} -;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/resolver.js - -const MAX_PLACEABLES = 100; -const FSI = "\u2068"; -const PDI = "\u2069"; -function match(scope, selector, key) { - if (key === selector) { - return true; - } - if (key instanceof FluentNumber && selector instanceof FluentNumber && key.value === selector.value) { - return true; - } - if (selector instanceof FluentNumber && typeof key === "string") { - let category = scope.memoizeIntlObject(Intl.PluralRules, selector.opts).select(selector.value); - if (key === category) { - return true; - } - } - return false; -} -function getDefault(scope, variants, star) { - if (variants[star]) { - return resolvePattern(scope, variants[star].value); - } - scope.reportError(new RangeError("No default")); - return new FluentNone(); -} -function getArguments(scope, args) { - const positional = []; - const named = Object.create(null); - for (const arg of args) { - if (arg.type === "narg") { - named[arg.name] = resolveExpression(scope, arg.value); - } else { - positional.push(resolveExpression(scope, arg)); - } - } - return { - positional, - named - }; -} -function resolveExpression(scope, expr) { - switch (expr.type) { - case "str": - return expr.value; - case "num": - return new FluentNumber(expr.value, { - minimumFractionDigits: expr.precision - }); - case "var": - return resolveVariableReference(scope, expr); - case "mesg": - return resolveMessageReference(scope, expr); - case "term": - return resolveTermReference(scope, expr); - case "func": - return resolveFunctionReference(scope, expr); - case "select": - return resolveSelectExpression(scope, expr); - default: - return new FluentNone(); - } -} -function resolveVariableReference(scope, { - name -}) { - let arg; - if (scope.params) { - if (Object.prototype.hasOwnProperty.call(scope.params, name)) { - arg = scope.params[name]; - } else { - return new FluentNone(`$${name}`); - } - } else if (scope.args && Object.prototype.hasOwnProperty.call(scope.args, name)) { - arg = scope.args[name]; - } else { - scope.reportError(new ReferenceError(`Unknown variable: $${name}`)); - return new FluentNone(`$${name}`); - } - if (arg instanceof FluentType) { - return arg; - } - switch (typeof arg) { - case "string": - return arg; - case "number": - return new FluentNumber(arg); - case "object": - if (arg instanceof Date) { - return new FluentDateTime(arg.getTime()); - } - default: - scope.reportError(new TypeError(`Variable type not supported: $${name}, ${typeof arg}`)); - return new FluentNone(`$${name}`); - } -} -function resolveMessageReference(scope, { - name, - attr -}) { - const message = scope.bundle._messages.get(name); - if (!message) { - scope.reportError(new ReferenceError(`Unknown message: ${name}`)); - return new FluentNone(name); - } - if (attr) { - const attribute = message.attributes[attr]; - if (attribute) { - return resolvePattern(scope, attribute); - } - scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`)); - return new FluentNone(`${name}.${attr}`); - } - if (message.value) { - return resolvePattern(scope, message.value); - } - scope.reportError(new ReferenceError(`No value: ${name}`)); - return new FluentNone(name); -} -function resolveTermReference(scope, { - name, - attr, - args -}) { - const id = `-${name}`; - const term = scope.bundle._terms.get(id); - if (!term) { - scope.reportError(new ReferenceError(`Unknown term: ${id}`)); - return new FluentNone(id); - } - if (attr) { - const attribute = term.attributes[attr]; - if (attribute) { - scope.params = getArguments(scope, args).named; - const resolved = resolvePattern(scope, attribute); - scope.params = null; - return resolved; - } - scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`)); - return new FluentNone(`${id}.${attr}`); - } - scope.params = getArguments(scope, args).named; - const resolved = resolvePattern(scope, term.value); - scope.params = null; - return resolved; -} -function resolveFunctionReference(scope, { - name, - args -}) { - let func = scope.bundle._functions[name]; - if (!func) { - scope.reportError(new ReferenceError(`Unknown function: ${name}()`)); - return new FluentNone(`${name}()`); - } - if (typeof func !== "function") { - scope.reportError(new TypeError(`Function ${name}() is not callable`)); - return new FluentNone(`${name}()`); - } - try { - let resolved = getArguments(scope, args); - return func(resolved.positional, resolved.named); - } catch (err) { - scope.reportError(err); - return new FluentNone(`${name}()`); - } -} -function resolveSelectExpression(scope, { - selector, - variants, - star -}) { - let sel = resolveExpression(scope, selector); - if (sel instanceof FluentNone) { - return getDefault(scope, variants, star); - } - for (const variant of variants) { - const key = resolveExpression(scope, variant.key); - if (match(scope, sel, key)) { - return resolvePattern(scope, variant.value); - } - } - return getDefault(scope, variants, star); -} -function resolveComplexPattern(scope, ptn) { - if (scope.dirty.has(ptn)) { - scope.reportError(new RangeError("Cyclic reference")); - return new FluentNone(); - } - scope.dirty.add(ptn); - const result = []; - const useIsolating = scope.bundle._useIsolating && ptn.length > 1; - for (const elem of ptn) { - if (typeof elem === "string") { - result.push(scope.bundle._transform(elem)); - continue; - } - scope.placeables++; - if (scope.placeables > MAX_PLACEABLES) { - scope.dirty.delete(ptn); - throw new RangeError(`Too many placeables expanded: ${scope.placeables}, ` + `max allowed is ${MAX_PLACEABLES}`); - } - if (useIsolating) { - result.push(FSI); - } - result.push(resolveExpression(scope, elem).toString(scope)); - if (useIsolating) { - result.push(PDI); - } - } - scope.dirty.delete(ptn); - return result.join(""); -} -function resolvePattern(scope, value) { - if (typeof value === "string") { - return scope.bundle._transform(value); - } - return resolveComplexPattern(scope, value); -} -;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/scope.js -class Scope { - constructor(bundle, errors, args) { - this.dirty = new WeakSet(); - this.params = null; - this.placeables = 0; - this.bundle = bundle; - this.errors = errors; - this.args = args; - } - reportError(error) { - if (!this.errors || !(error instanceof Error)) { - throw error; - } - this.errors.push(error); - } - memoizeIntlObject(ctor, opts) { - let cache = this.bundle._intls.get(ctor); - if (!cache) { - cache = {}; - this.bundle._intls.set(ctor, cache); - } - let id = JSON.stringify(opts); - if (!cache[id]) { - cache[id] = new ctor(this.bundle.locales, opts); - } - return cache[id]; - } -} -;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/builtins.js - -function values(opts, allowed) { - const unwrapped = Object.create(null); - for (const [name, opt] of Object.entries(opts)) { - if (allowed.includes(name)) { - unwrapped[name] = opt.valueOf(); - } - } - return unwrapped; -} -const NUMBER_ALLOWED = ["unitDisplay", "currencyDisplay", "useGrouping", "minimumIntegerDigits", "minimumFractionDigits", "maximumFractionDigits", "minimumSignificantDigits", "maximumSignificantDigits"]; -function NUMBER(args, opts) { - let arg = args[0]; - if (arg instanceof FluentNone) { - return new FluentNone(`NUMBER(${arg.valueOf()})`); - } - if (arg instanceof FluentNumber) { - return new FluentNumber(arg.valueOf(), { - ...arg.opts, - ...values(opts, NUMBER_ALLOWED) - }); - } - if (arg instanceof FluentDateTime) { - return new FluentNumber(arg.valueOf(), { - ...values(opts, NUMBER_ALLOWED) - }); - } - throw new TypeError("Invalid argument to NUMBER"); -} -const DATETIME_ALLOWED = ["dateStyle", "timeStyle", "fractionalSecondDigits", "dayPeriod", "hour12", "weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName"]; -function DATETIME(args, opts) { - let arg = args[0]; - if (arg instanceof FluentNone) { - return new FluentNone(`DATETIME(${arg.valueOf()})`); - } - if (arg instanceof FluentDateTime) { - return new FluentDateTime(arg.valueOf(), { - ...arg.opts, - ...values(opts, DATETIME_ALLOWED) - }); - } - if (arg instanceof FluentNumber) { - return new FluentDateTime(arg.valueOf(), { - ...values(opts, DATETIME_ALLOWED) - }); - } - throw new TypeError("Invalid argument to DATETIME"); -} -;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/memoizer.js -const cache = new Map(); -function getMemoizerForLocale(locales) { - const stringLocale = Array.isArray(locales) ? locales.join(" ") : locales; - let memoizer = cache.get(stringLocale); - if (memoizer === undefined) { - memoizer = new Map(); - cache.set(stringLocale, memoizer); - } - return memoizer; -} -;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/bundle.js - - - - - -class FluentBundle { - constructor(locales, { - functions, - useIsolating = true, - transform = v => v - } = {}) { - this._terms = new Map(); - this._messages = new Map(); - this.locales = Array.isArray(locales) ? locales : [locales]; - this._functions = { - NUMBER: NUMBER, - DATETIME: DATETIME, - ...functions - }; - this._useIsolating = useIsolating; - this._transform = transform; - this._intls = getMemoizerForLocale(locales); - } - hasMessage(id) { - return this._messages.has(id); - } - getMessage(id) { - return this._messages.get(id); - } - addResource(res, { - allowOverrides = false - } = {}) { - const errors = []; - for (let i = 0; i < res.body.length; i++) { - let entry = res.body[i]; - if (entry.id.startsWith("-")) { - if (allowOverrides === false && this._terms.has(entry.id)) { - errors.push(new Error(`Attempt to override an existing term: "${entry.id}"`)); - continue; - } - this._terms.set(entry.id, entry); - } else { - if (allowOverrides === false && this._messages.has(entry.id)) { - errors.push(new Error(`Attempt to override an existing message: "${entry.id}"`)); - continue; - } - this._messages.set(entry.id, entry); - } - } - return errors; - } - formatPattern(pattern, args = null, errors = null) { - if (typeof pattern === "string") { - return this._transform(pattern); - } - let scope = new Scope(this, errors, args); - try { - let value = resolveComplexPattern(scope, pattern); - return value.toString(scope); - } catch (err) { - if (scope.errors && err instanceof Error) { - scope.errors.push(err); - return new FluentNone().toString(scope); - } - throw err; - } - } -} -;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/resource.js -const RE_MESSAGE_START = /^(-?[a-zA-Z][\w-]*) *= */gm; -const RE_ATTRIBUTE_START = /\.([a-zA-Z][\w-]*) *= */y; -const RE_VARIANT_START = /\*?\[/y; -const RE_NUMBER_LITERAL = /(-?[0-9]+(?:\.([0-9]+))?)/y; -const RE_IDENTIFIER = /([a-zA-Z][\w-]*)/y; -const RE_REFERENCE = /([$-])?([a-zA-Z][\w-]*)(?:\.([a-zA-Z][\w-]*))?/y; -const RE_FUNCTION_NAME = /^[A-Z][A-Z0-9_-]*$/; -const RE_TEXT_RUN = /([^{}\n\r]+)/y; -const RE_STRING_RUN = /([^\\"\n\r]*)/y; -const RE_STRING_ESCAPE = /\\([\\"])/y; -const RE_UNICODE_ESCAPE = /\\u([a-fA-F0-9]{4})|\\U([a-fA-F0-9]{6})/y; -const RE_LEADING_NEWLINES = /^\n+/; -const RE_TRAILING_SPACES = / +$/; -const RE_BLANK_LINES = / *\r?\n/g; -const RE_INDENT = /( *)$/; -const TOKEN_BRACE_OPEN = /{\s*/y; -const TOKEN_BRACE_CLOSE = /\s*}/y; -const TOKEN_BRACKET_OPEN = /\[\s*/y; -const TOKEN_BRACKET_CLOSE = /\s*] */y; -const TOKEN_PAREN_OPEN = /\s*\(\s*/y; -const TOKEN_ARROW = /\s*->\s*/y; -const TOKEN_COLON = /\s*:\s*/y; -const TOKEN_COMMA = /\s*,?\s*/y; -const TOKEN_BLANK = /\s+/y; -class FluentResource { - constructor(source) { - this.body = []; - RE_MESSAGE_START.lastIndex = 0; - let cursor = 0; - while (true) { - let next = RE_MESSAGE_START.exec(source); - if (next === null) { - break; - } - cursor = RE_MESSAGE_START.lastIndex; - try { - this.body.push(parseMessage(next[1])); - } catch (err) { - if (err instanceof SyntaxError) { - continue; - } - throw err; - } - } - function test(re) { - re.lastIndex = cursor; - return re.test(source); - } - function consumeChar(char, errorClass) { - if (source[cursor] === char) { - cursor++; - return true; - } - if (errorClass) { - throw new errorClass(`Expected ${char}`); - } - return false; - } - function consumeToken(re, errorClass) { - if (test(re)) { - cursor = re.lastIndex; - return true; - } - if (errorClass) { - throw new errorClass(`Expected ${re.toString()}`); - } - return false; - } - function match(re) { - re.lastIndex = cursor; - let result = re.exec(source); - if (result === null) { - throw new SyntaxError(`Expected ${re.toString()}`); - } - cursor = re.lastIndex; - return result; - } - function match1(re) { - return match(re)[1]; - } - function parseMessage(id) { - let value = parsePattern(); - let attributes = parseAttributes(); - if (value === null && Object.keys(attributes).length === 0) { - throw new SyntaxError("Expected message value or attributes"); - } - return { - id, - value, - attributes - }; - } - function parseAttributes() { - let attrs = Object.create(null); - while (test(RE_ATTRIBUTE_START)) { - let name = match1(RE_ATTRIBUTE_START); - let value = parsePattern(); - if (value === null) { - throw new SyntaxError("Expected attribute value"); - } - attrs[name] = value; - } - return attrs; - } - function parsePattern() { - let first; - if (test(RE_TEXT_RUN)) { - first = match1(RE_TEXT_RUN); - } - if (source[cursor] === "{" || source[cursor] === "}") { - return parsePatternElements(first ? [first] : [], Infinity); - } - let indent = parseIndent(); - if (indent) { - if (first) { - return parsePatternElements([first, indent], indent.length); - } - indent.value = trim(indent.value, RE_LEADING_NEWLINES); - return parsePatternElements([indent], indent.length); - } - if (first) { - return trim(first, RE_TRAILING_SPACES); - } - return null; - } - function parsePatternElements(elements = [], commonIndent) { - while (true) { - if (test(RE_TEXT_RUN)) { - elements.push(match1(RE_TEXT_RUN)); - continue; - } - if (source[cursor] === "{") { - elements.push(parsePlaceable()); - continue; - } - if (source[cursor] === "}") { - throw new SyntaxError("Unbalanced closing brace"); - } - let indent = parseIndent(); - if (indent) { - elements.push(indent); - commonIndent = Math.min(commonIndent, indent.length); - continue; - } - break; - } - let lastIndex = elements.length - 1; - let lastElement = elements[lastIndex]; - if (typeof lastElement === "string") { - elements[lastIndex] = trim(lastElement, RE_TRAILING_SPACES); - } - let baked = []; - for (let element of elements) { - if (element instanceof Indent) { - element = element.value.slice(0, element.value.length - commonIndent); - } - if (element) { - baked.push(element); - } - } - return baked; - } - function parsePlaceable() { - consumeToken(TOKEN_BRACE_OPEN, SyntaxError); - let selector = parseInlineExpression(); - if (consumeToken(TOKEN_BRACE_CLOSE)) { - return selector; - } - if (consumeToken(TOKEN_ARROW)) { - let variants = parseVariants(); - consumeToken(TOKEN_BRACE_CLOSE, SyntaxError); - return { - type: "select", - selector, - ...variants - }; - } - throw new SyntaxError("Unclosed placeable"); - } - function parseInlineExpression() { - if (source[cursor] === "{") { - return parsePlaceable(); - } - if (test(RE_REFERENCE)) { - let [, sigil, name, attr = null] = match(RE_REFERENCE); - if (sigil === "$") { - return { - type: "var", - name - }; - } - if (consumeToken(TOKEN_PAREN_OPEN)) { - let args = parseArguments(); - if (sigil === "-") { - return { - type: "term", - name, - attr, - args - }; - } - if (RE_FUNCTION_NAME.test(name)) { - return { - type: "func", - name, - args - }; - } - throw new SyntaxError("Function names must be all upper-case"); - } - if (sigil === "-") { - return { - type: "term", - name, - attr, - args: [] - }; - } - return { - type: "mesg", - name, - attr - }; - } - return parseLiteral(); - } - function parseArguments() { - let args = []; - while (true) { - switch (source[cursor]) { - case ")": - cursor++; - return args; - case undefined: - throw new SyntaxError("Unclosed argument list"); - } - args.push(parseArgument()); - consumeToken(TOKEN_COMMA); - } - } - function parseArgument() { - let expr = parseInlineExpression(); - if (expr.type !== "mesg") { - return expr; - } - if (consumeToken(TOKEN_COLON)) { - return { - type: "narg", - name: expr.name, - value: parseLiteral() - }; - } - return expr; - } - function parseVariants() { - let variants = []; - let count = 0; - let star; - while (test(RE_VARIANT_START)) { - if (consumeChar("*")) { - star = count; - } - let key = parseVariantKey(); - let value = parsePattern(); - if (value === null) { - throw new SyntaxError("Expected variant value"); - } - variants[count++] = { - key, - value - }; - } - if (count === 0) { - return null; - } - if (star === undefined) { - throw new SyntaxError("Expected default variant"); - } - return { - variants, - star - }; - } - function parseVariantKey() { - consumeToken(TOKEN_BRACKET_OPEN, SyntaxError); - let key; - if (test(RE_NUMBER_LITERAL)) { - key = parseNumberLiteral(); - } else { - key = { - type: "str", - value: match1(RE_IDENTIFIER) - }; - } - consumeToken(TOKEN_BRACKET_CLOSE, SyntaxError); - return key; - } - function parseLiteral() { - if (test(RE_NUMBER_LITERAL)) { - return parseNumberLiteral(); - } - if (source[cursor] === '"') { - return parseStringLiteral(); - } - throw new SyntaxError("Invalid expression"); - } - function parseNumberLiteral() { - let [, value, fraction = ""] = match(RE_NUMBER_LITERAL); - let precision = fraction.length; - return { - type: "num", - value: parseFloat(value), - precision - }; - } - function parseStringLiteral() { - consumeChar('"', SyntaxError); - let value = ""; - while (true) { - value += match1(RE_STRING_RUN); - if (source[cursor] === "\\") { - value += parseEscapeSequence(); - continue; - } - if (consumeChar('"')) { - return { - type: "str", - value - }; - } - throw new SyntaxError("Unclosed string literal"); - } - } - function parseEscapeSequence() { - if (test(RE_STRING_ESCAPE)) { - return match1(RE_STRING_ESCAPE); - } - if (test(RE_UNICODE_ESCAPE)) { - let [, codepoint4, codepoint6] = match(RE_UNICODE_ESCAPE); - let codepoint = parseInt(codepoint4 || codepoint6, 16); - return codepoint <= 0xd7ff || 0xe000 <= codepoint ? String.fromCodePoint(codepoint) : "锟�"; - } - throw new SyntaxError("Unknown escape sequence"); - } - function parseIndent() { - let start = cursor; - consumeToken(TOKEN_BLANK); - switch (source[cursor]) { - case ".": - case "[": - case "*": - case "}": - case undefined: - return false; - case "{": - return makeIndent(source.slice(start, cursor)); - } - if (source[cursor - 1] === " ") { - return makeIndent(source.slice(start, cursor)); - } - return false; - } - function trim(text, re) { - return text.replace(re, ""); - } - function makeIndent(blank) { - let value = blank.replace(RE_BLANK_LINES, "\n"); - let length = RE_INDENT.exec(blank)[1].length; - return new Indent(value, length); - } - } -} -class Indent { - constructor(value, length) { - this.value = value; - this.length = length; - } -} -;// CONCATENATED MODULE: ./node_modules/@fluent/bundle/esm/index.js - - - - -/***/ }), - -/***/ 5273: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - - -// EXPORTS -__webpack_require__.d(__webpack_exports__, { - DOMLocalization: () => (/* reexport */ DOMLocalization) -}); - -// UNUSED EXPORTS: Localization - -;// CONCATENATED MODULE: ./node_modules/@fluent/dom/esm/overlay.js -const reOverlay = /<|&#?\w+;/; -const TEXT_LEVEL_ELEMENTS = { - "http://www.w3.org/1999/xhtml": ["em", "strong", "small", "s", "cite", "q", "dfn", "abbr", "data", "time", "code", "var", "samp", "kbd", "sub", "sup", "i", "b", "u", "mark", "bdi", "bdo", "span", "br", "wbr"] -}; -const LOCALIZABLE_ATTRIBUTES = { - "http://www.w3.org/1999/xhtml": { - global: ["title", "aria-label", "aria-valuetext"], - a: ["download"], - area: ["download", "alt"], - input: ["alt", "placeholder"], - menuitem: ["label"], - menu: ["label"], - optgroup: ["label"], - option: ["label"], - track: ["label"], - img: ["alt"], - textarea: ["placeholder"], - th: ["abbr"] - }, - "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul": { - global: ["accesskey", "aria-label", "aria-valuetext", "label", "title", "tooltiptext"], - description: ["value"], - key: ["key", "keycode"], - label: ["value"], - textbox: ["placeholder", "value"] - } -}; -function translateElement(element, translation) { - const { - value - } = translation; - if (typeof value === "string") { - if (element.localName === "title" && element.namespaceURI === "http://www.w3.org/1999/xhtml") { - element.textContent = value; - } else if (!reOverlay.test(value)) { - element.textContent = value; - } else { - const templateElement = element.ownerDocument.createElementNS("http://www.w3.org/1999/xhtml", "template"); - templateElement.innerHTML = value; - overlayChildNodes(templateElement.content, element); - } - } - overlayAttributes(translation, element); -} -function overlayChildNodes(fromFragment, toElement) { - for (const childNode of fromFragment.childNodes) { - if (childNode.nodeType === childNode.TEXT_NODE) { - continue; - } - if (childNode.hasAttribute("data-l10n-name")) { - const sanitized = getNodeForNamedElement(toElement, childNode); - fromFragment.replaceChild(sanitized, childNode); - continue; - } - if (isElementAllowed(childNode)) { - const sanitized = createSanitizedElement(childNode); - fromFragment.replaceChild(sanitized, childNode); - continue; - } - console.warn(`An element of forbidden type "${childNode.localName}" was found in ` + "the translation. Only safe text-level elements and elements with " + "data-l10n-name are allowed."); - fromFragment.replaceChild(createTextNodeFromTextContent(childNode), childNode); - } - toElement.textContent = ""; - toElement.appendChild(fromFragment); -} -function hasAttribute(attributes, name) { - if (!attributes) { - return false; - } - for (let attr of attributes) { - if (attr.name === name) { - return true; - } - } - return false; -} -function overlayAttributes(fromElement, toElement) { - const explicitlyAllowed = toElement.hasAttribute("data-l10n-attrs") ? toElement.getAttribute("data-l10n-attrs").split(",").map(i => i.trim()) : null; - for (const attr of Array.from(toElement.attributes)) { - if (isAttrNameLocalizable(attr.name, toElement, explicitlyAllowed) && !hasAttribute(fromElement.attributes, attr.name)) { - toElement.removeAttribute(attr.name); - } - } - if (!fromElement.attributes) { - return; - } - for (const attr of Array.from(fromElement.attributes)) { - if (isAttrNameLocalizable(attr.name, toElement, explicitlyAllowed) && toElement.getAttribute(attr.name) !== attr.value) { - toElement.setAttribute(attr.name, attr.value); - } - } -} -function getNodeForNamedElement(sourceElement, translatedChild) { - const childName = translatedChild.getAttribute("data-l10n-name"); - const sourceChild = sourceElement.querySelector(`[data-l10n-name="${childName}"]`); - if (!sourceChild) { - console.warn(`An element named "${childName}" wasn't found in the source.`); - return createTextNodeFromTextContent(translatedChild); - } - if (sourceChild.localName !== translatedChild.localName) { - console.warn(`An element named "${childName}" was found in the translation ` + `but its type ${translatedChild.localName} didn't match the ` + `element found in the source (${sourceChild.localName}).`); - return createTextNodeFromTextContent(translatedChild); - } - sourceElement.removeChild(sourceChild); - const clone = sourceChild.cloneNode(false); - return shallowPopulateUsing(translatedChild, clone); -} -function createSanitizedElement(element) { - const clone = element.ownerDocument.createElement(element.localName); - return shallowPopulateUsing(element, clone); -} -function createTextNodeFromTextContent(element) { - return element.ownerDocument.createTextNode(element.textContent); -} -function isElementAllowed(element) { - const allowed = TEXT_LEVEL_ELEMENTS[element.namespaceURI]; - return allowed && allowed.includes(element.localName); -} -function isAttrNameLocalizable(name, element, explicitlyAllowed = null) { - if (explicitlyAllowed && explicitlyAllowed.includes(name)) { - return true; - } - const allowed = LOCALIZABLE_ATTRIBUTES[element.namespaceURI]; - if (!allowed) { - return false; - } - const attrName = name.toLowerCase(); - const elemName = element.localName; - if (allowed.global.includes(attrName)) { - return true; - } - if (!allowed[elemName]) { - return false; - } - if (allowed[elemName].includes(attrName)) { - return true; - } - if (element.namespaceURI === "http://www.w3.org/1999/xhtml" && elemName === "input" && attrName === "value") { - const type = element.type.toLowerCase(); - if (type === "submit" || type === "button" || type === "reset") { - return true; - } - } - return false; -} -function shallowPopulateUsing(fromElement, toElement) { - toElement.textContent = fromElement.textContent; - overlayAttributes(fromElement, toElement); - return toElement; -} -;// CONCATENATED MODULE: ./node_modules/cached-iterable/src/cached_iterable.mjs -class CachedIterable extends Array { - static from(iterable) { - if (iterable instanceof this) { - return iterable; - } - return new this(iterable); - } -} -;// CONCATENATED MODULE: ./node_modules/cached-iterable/src/cached_sync_iterable.mjs - -class CachedSyncIterable extends CachedIterable { - constructor(iterable) { - super(); - if (Symbol.iterator in Object(iterable)) { - this.iterator = iterable[Symbol.iterator](); - } else { - throw new TypeError("Argument must implement the iteration protocol."); - } - } - [Symbol.iterator]() { - const cached = this; - let cur = 0; - return { - next() { - if (cached.length <= cur) { - cached.push(cached.iterator.next()); - } - return cached[cur++]; - } - }; - } - touchNext(count = 1) { - let idx = 0; - while (idx++ < count) { - const last = this[this.length - 1]; - if (last && last.done) { - break; - } - this.push(this.iterator.next()); - } - return this[this.length - 1]; - } -} -;// CONCATENATED MODULE: ./node_modules/cached-iterable/src/cached_async_iterable.mjs - -class CachedAsyncIterable extends CachedIterable { - constructor(iterable) { - super(); - if (Symbol.asyncIterator in Object(iterable)) { - this.iterator = iterable[Symbol.asyncIterator](); - } else if (Symbol.iterator in Object(iterable)) { - this.iterator = iterable[Symbol.iterator](); - } else { - throw new TypeError("Argument must implement the iteration protocol."); - } - } - [Symbol.asyncIterator]() { - const cached = this; - let cur = 0; - return { - async next() { - if (cached.length <= cur) { - cached.push(cached.iterator.next()); - } - return cached[cur++]; - } - }; - } - async touchNext(count = 1) { - let idx = 0; - while (idx++ < count) { - const last = this[this.length - 1]; - if (last && (await last).done) { - break; - } - this.push(this.iterator.next()); - } - return this[this.length - 1]; - } -} -;// CONCATENATED MODULE: ./node_modules/cached-iterable/src/index.mjs - - -;// CONCATENATED MODULE: ./node_modules/@fluent/dom/esm/localization.js - -class Localization { - constructor(resourceIds = [], generateBundles) { - this.resourceIds = resourceIds; - this.generateBundles = generateBundles; - this.onChange(true); - } - addResourceIds(resourceIds, eager = false) { - this.resourceIds.push(...resourceIds); - this.onChange(eager); - return this.resourceIds.length; - } - removeResourceIds(resourceIds) { - this.resourceIds = this.resourceIds.filter(r => !resourceIds.includes(r)); - this.onChange(); - return this.resourceIds.length; - } - async formatWithFallback(keys, method) { - const translations = []; - let hasAtLeastOneBundle = false; - for await (const bundle of this.bundles) { - hasAtLeastOneBundle = true; - const missingIds = keysFromBundle(method, bundle, keys, translations); - if (missingIds.size === 0) { - break; - } - if (typeof console !== "undefined") { - const locale = bundle.locales[0]; - const ids = Array.from(missingIds).join(", "); - console.warn(`[fluent] Missing translations in ${locale}: ${ids}`); - } - } - if (!hasAtLeastOneBundle && typeof console !== "undefined") { - console.warn(`[fluent] Request for keys failed because no resource bundles got generated. - keys: ${JSON.stringify(keys)}. - resourceIds: ${JSON.stringify(this.resourceIds)}.`); - } - return translations; - } - formatMessages(keys) { - return this.formatWithFallback(keys, messageFromBundle); - } - formatValues(keys) { - return this.formatWithFallback(keys, valueFromBundle); - } - async formatValue(id, args) { - const [val] = await this.formatValues([{ - id, - args - }]); - return val; - } - handleEvent() { - this.onChange(); - } - onChange(eager = false) { - this.bundles = CachedAsyncIterable.from(this.generateBundles(this.resourceIds)); - if (eager) { - this.bundles.touchNext(2); - } - } -} -function valueFromBundle(bundle, errors, message, args) { - if (message.value) { - return bundle.formatPattern(message.value, args, errors); - } - return null; -} -function messageFromBundle(bundle, errors, message, args) { - const formatted = { - value: null, - attributes: null - }; - if (message.value) { - formatted.value = bundle.formatPattern(message.value, args, errors); - } - let attrNames = Object.keys(message.attributes); - if (attrNames.length > 0) { - formatted.attributes = new Array(attrNames.length); - for (let [i, name] of attrNames.entries()) { - let value = bundle.formatPattern(message.attributes[name], args, errors); - formatted.attributes[i] = { - name, - value - }; - } - } - return formatted; -} -function keysFromBundle(method, bundle, keys, translations) { - const messageErrors = []; - const missingIds = new Set(); - keys.forEach(({ - id, - args - }, i) => { - if (translations[i] !== undefined) { - return; - } - let message = bundle.getMessage(id); - if (message) { - messageErrors.length = 0; - translations[i] = method(bundle, messageErrors, message, args); - if (messageErrors.length > 0 && typeof console !== "undefined") { - const locale = bundle.locales[0]; - const errors = messageErrors.join(", "); - console.warn(`[fluent][resolver] errors in ${locale}/${id}: ${errors}.`); - } - } else { - missingIds.add(id); - } - }); - return missingIds; -} -;// CONCATENATED MODULE: ./node_modules/@fluent/dom/esm/dom_localization.js - - -const L10NID_ATTR_NAME = "data-l10n-id"; -const L10NARGS_ATTR_NAME = "data-l10n-args"; -const L10N_ELEMENT_QUERY = `[${L10NID_ATTR_NAME}]`; -class DOMLocalization extends Localization { - constructor(resourceIds, generateBundles) { - super(resourceIds, generateBundles); - this.roots = new Set(); - this.pendingrAF = null; - this.pendingElements = new Set(); - this.windowElement = null; - this.mutationObserver = null; - this.observerConfig = { - attributes: true, - characterData: false, - childList: true, - subtree: true, - attributeFilter: [L10NID_ATTR_NAME, L10NARGS_ATTR_NAME] - }; - } - onChange(eager = false) { - super.onChange(eager); - if (this.roots) { - this.translateRoots(); - } - } - setAttributes(element, id, args) { - element.setAttribute(L10NID_ATTR_NAME, id); - if (args) { - element.setAttribute(L10NARGS_ATTR_NAME, JSON.stringify(args)); - } else { - element.removeAttribute(L10NARGS_ATTR_NAME); - } - return element; - } - getAttributes(element) { - return { - id: element.getAttribute(L10NID_ATTR_NAME), - args: JSON.parse(element.getAttribute(L10NARGS_ATTR_NAME) || null) - }; - } - connectRoot(newRoot) { - for (const root of this.roots) { - if (root === newRoot || root.contains(newRoot) || newRoot.contains(root)) { - throw new Error("Cannot add a root that overlaps with existing root."); - } - } - if (this.windowElement) { - if (this.windowElement !== newRoot.ownerDocument.defaultView) { - throw new Error(`Cannot connect a root: - DOMLocalization already has a root from a different window.`); - } - } else { - this.windowElement = newRoot.ownerDocument.defaultView; - this.mutationObserver = new this.windowElement.MutationObserver(mutations => this.translateMutations(mutations)); - } - this.roots.add(newRoot); - this.mutationObserver.observe(newRoot, this.observerConfig); - } - disconnectRoot(root) { - this.roots.delete(root); - this.pauseObserving(); - if (this.roots.size === 0) { - this.mutationObserver = null; - this.windowElement = null; - this.pendingrAF = null; - this.pendingElements.clear(); - return true; - } - this.resumeObserving(); - return false; - } - translateRoots() { - const roots = Array.from(this.roots); - return Promise.all(roots.map(root => this.translateFragment(root))); - } - pauseObserving() { - if (!this.mutationObserver) { - return; - } - this.translateMutations(this.mutationObserver.takeRecords()); - this.mutationObserver.disconnect(); - } - resumeObserving() { - if (!this.mutationObserver) { - return; - } - for (const root of this.roots) { - this.mutationObserver.observe(root, this.observerConfig); - } - } - translateMutations(mutations) { - for (const mutation of mutations) { - switch (mutation.type) { - case "attributes": - if (mutation.target.hasAttribute("data-l10n-id")) { - this.pendingElements.add(mutation.target); - } - break; - case "childList": - for (const addedNode of mutation.addedNodes) { - if (addedNode.nodeType === addedNode.ELEMENT_NODE) { - if (addedNode.childElementCount) { - for (const element of this.getTranslatables(addedNode)) { - this.pendingElements.add(element); - } - } else if (addedNode.hasAttribute(L10NID_ATTR_NAME)) { - this.pendingElements.add(addedNode); - } - } - } - break; - } - } - if (this.pendingElements.size > 0) { - if (this.pendingrAF === null) { - this.pendingrAF = this.windowElement.requestAnimationFrame(() => { - this.translateElements(Array.from(this.pendingElements)); - this.pendingElements.clear(); - this.pendingrAF = null; - }); - } - } - } - translateFragment(frag) { - return this.translateElements(this.getTranslatables(frag)); - } - async translateElements(elements) { - if (!elements.length) { - return undefined; - } - const keys = elements.map(this.getKeysForElement); - const translations = await this.formatMessages(keys); - return this.applyTranslations(elements, translations); - } - applyTranslations(elements, translations) { - this.pauseObserving(); - for (let i = 0; i < elements.length; i++) { - if (translations[i] !== undefined) { - translateElement(elements[i], translations[i]); - } - } - this.resumeObserving(); - } - getTranslatables(element) { - const nodes = Array.from(element.querySelectorAll(L10N_ELEMENT_QUERY)); - if (typeof element.hasAttribute === "function" && element.hasAttribute(L10NID_ATTR_NAME)) { - nodes.push(element); - } - return nodes; - } - getKeysForElement(element) { - return { - id: element.getAttribute(L10NID_ATTR_NAME), - args: JSON.parse(element.getAttribute(L10NARGS_ATTR_NAME) || null) - }; - } -} -;// CONCATENATED MODULE: ./node_modules/@fluent/dom/esm/index.js - - - -/***/ }), - -/***/ 259: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AltTextManager: () => (/* binding */ AltTextManager) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - -class AltTextManager { - #boundUpdateUIState = this.#updateUIState.bind(this); - #boundSetPosition = this.#setPosition.bind(this); - #boundOnClick = this.#onClick.bind(this); - #currentEditor = null; - #cancelButton; - #dialog; - #eventBus; - #hasUsedPointer = false; - #optionDescription; - #optionDecorative; - #overlayManager; - #saveButton; - #textarea; - #uiManager; - #previousAltText = null; - #svgElement = null; - #rectElement = null; - #container; - #telemetryData = null; - constructor({ - dialog, - optionDescription, - optionDecorative, - textarea, - cancelButton, - saveButton - }, container, overlayManager, eventBus) { - this.#dialog = dialog; - this.#optionDescription = optionDescription; - this.#optionDecorative = optionDecorative; - this.#textarea = textarea; - this.#cancelButton = cancelButton; - this.#saveButton = saveButton; - this.#overlayManager = overlayManager; - this.#eventBus = eventBus; - this.#container = container; - dialog.addEventListener("close", this.#close.bind(this)); - dialog.addEventListener("contextmenu", event => { - if (event.target !== this.#textarea) { - event.preventDefault(); - } - }); - cancelButton.addEventListener("click", this.#finish.bind(this)); - saveButton.addEventListener("click", this.#save.bind(this)); - optionDescription.addEventListener("change", this.#boundUpdateUIState); - optionDecorative.addEventListener("change", this.#boundUpdateUIState); - this.#overlayManager.register(dialog); - } - get _elements() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "_elements", [this.#optionDescription, this.#optionDecorative, this.#textarea, this.#saveButton, this.#cancelButton]); - } - #createSVGElement() { - if (this.#svgElement) { - return; - } - const svgFactory = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.DOMSVGFactory(); - const svg = this.#svgElement = svgFactory.createElement("svg"); - svg.setAttribute("width", "0"); - svg.setAttribute("height", "0"); - const defs = svgFactory.createElement("defs"); - svg.append(defs); - const mask = svgFactory.createElement("mask"); - defs.append(mask); - mask.setAttribute("id", "alttext-manager-mask"); - mask.setAttribute("maskContentUnits", "objectBoundingBox"); - let rect = svgFactory.createElement("rect"); - mask.append(rect); - rect.setAttribute("fill", "white"); - rect.setAttribute("width", "1"); - rect.setAttribute("height", "1"); - rect.setAttribute("x", "0"); - rect.setAttribute("y", "0"); - rect = this.#rectElement = svgFactory.createElement("rect"); - mask.append(rect); - rect.setAttribute("fill", "black"); - this.#dialog.append(svg); - } - async editAltText(uiManager, editor) { - if (this.#currentEditor || !editor) { - return; - } - this.#createSVGElement(); - this.#hasUsedPointer = false; - for (const element of this._elements) { - element.addEventListener("click", this.#boundOnClick); - } - const { - altText, - decorative - } = editor.altTextData; - if (decorative === true) { - this.#optionDecorative.checked = true; - this.#optionDescription.checked = false; - } else { - this.#optionDecorative.checked = false; - this.#optionDescription.checked = true; - } - this.#previousAltText = this.#textarea.value = altText?.trim() || ""; - this.#updateUIState(); - this.#currentEditor = editor; - this.#uiManager = uiManager; - this.#uiManager.removeEditListeners(); - this.#eventBus._on("resize", this.#boundSetPosition); - try { - await this.#overlayManager.open(this.#dialog); - this.#setPosition(); - } catch (ex) { - this.#close(); - throw ex; - } - } - #setPosition() { - if (!this.#currentEditor) { - return; - } - const dialog = this.#dialog; - const { - style - } = dialog; - const { - x: containerX, - y: containerY, - width: containerW, - height: containerH - } = this.#container.getBoundingClientRect(); - const { - innerWidth: windowW, - innerHeight: windowH - } = window; - const { - width: dialogW, - height: dialogH - } = dialog.getBoundingClientRect(); - const { - x, - y, - width, - height - } = this.#currentEditor.getClientDimensions(); - const MARGIN = 10; - const isLTR = this.#uiManager.direction === "ltr"; - const xs = Math.max(x, containerX); - const xe = Math.min(x + width, containerX + containerW); - const ys = Math.max(y, containerY); - const ye = Math.min(y + height, containerY + containerH); - this.#rectElement.setAttribute("width", `${(xe - xs) / windowW}`); - this.#rectElement.setAttribute("height", `${(ye - ys) / windowH}`); - this.#rectElement.setAttribute("x", `${xs / windowW}`); - this.#rectElement.setAttribute("y", `${ys / windowH}`); - let left = null; - let top = Math.max(y, 0); - top += Math.min(windowH - (top + dialogH), 0); - if (isLTR) { - if (x + width + MARGIN + dialogW < windowW) { - left = x + width + MARGIN; - } else if (x > dialogW + MARGIN) { - left = x - dialogW - MARGIN; - } - } else if (x > dialogW + MARGIN) { - left = x - dialogW - MARGIN; - } else if (x + width + MARGIN + dialogW < windowW) { - left = x + width + MARGIN; - } - if (left === null) { - top = null; - left = Math.max(x, 0); - left += Math.min(windowW - (left + dialogW), 0); - if (y > dialogH + MARGIN) { - top = y - dialogH - MARGIN; - } else if (y + height + MARGIN + dialogH < windowH) { - top = y + height + MARGIN; - } - } - if (top !== null) { - dialog.classList.add("positioned"); - if (isLTR) { - style.left = `${left}px`; - } else { - style.right = `${windowW - left - dialogW}px`; - } - style.top = `${top}px`; - } else { - dialog.classList.remove("positioned"); - style.left = ""; - style.top = ""; - } - } - #finish() { - if (this.#overlayManager.active === this.#dialog) { - this.#overlayManager.close(this.#dialog); - } - } - #close() { - this.#currentEditor._reportTelemetry(this.#telemetryData || { - action: "alt_text_cancel", - alt_text_keyboard: !this.#hasUsedPointer - }); - this.#telemetryData = null; - this.#removeOnClickListeners(); - this.#uiManager?.addEditListeners(); - this.#eventBus._off("resize", this.#boundSetPosition); - this.#currentEditor.altTextFinish(); - this.#currentEditor = null; - this.#uiManager = null; - } - #updateUIState() { - this.#textarea.disabled = this.#optionDecorative.checked; - } - #save() { - const altText = this.#textarea.value.trim(); - const decorative = this.#optionDecorative.checked; - this.#currentEditor.altTextData = { - altText, - decorative - }; - this.#telemetryData = { - action: "alt_text_save", - alt_text_description: !!altText, - alt_text_edit: !!this.#previousAltText && this.#previousAltText !== altText, - alt_text_decorative: decorative, - alt_text_keyboard: !this.#hasUsedPointer - }; - this.#finish(); - } - #onClick(evt) { - if (evt.detail === 0) { - return; - } - this.#hasUsedPointer = true; - this.#removeOnClickListeners(); - } - #removeOnClickListeners() { - for (const element of this._elements) { - element.removeEventListener("click", this.#boundOnClick); - } - } - destroy() { - this.#uiManager = null; - this.#finish(); - this.#svgElement?.remove(); - this.#svgElement = this.#rectElement = null; - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 283: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AnnotationEditorLayerBuilder: () => (/* binding */ AnnotationEditorLayerBuilder) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -/* harmony import */ var web_null_l10n__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(410); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, web_null_l10n__WEBPACK_IMPORTED_MODULE_1__]); -([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, web_null_l10n__WEBPACK_IMPORTED_MODULE_1__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__); - - -class AnnotationEditorLayerBuilder { - #annotationLayer = null; - #drawLayer = null; - #onAppend = null; - #textLayer = null; - #uiManager; - constructor(options) { - this.pdfPage = options.pdfPage; - this.accessibilityManager = options.accessibilityManager; - this.l10n = options.l10n; - this.l10n ||= new web_null_l10n__WEBPACK_IMPORTED_MODULE_1__.GenericL10n(); - this.annotationEditorLayer = null; - this.div = null; - this._cancelled = false; - this.#uiManager = options.uiManager; - this.#annotationLayer = options.annotationLayer || null; - this.#textLayer = options.textLayer || null; - this.#drawLayer = options.drawLayer || null; - this.#onAppend = options.onAppend || null; - } - async render(viewport, intent = "display") { - if (intent !== "display") { - return; - } - if (this._cancelled) { - return; - } - const clonedViewport = viewport.clone({ - dontFlip: true - }); - if (this.div) { - this.annotationEditorLayer.update({ - viewport: clonedViewport - }); - this.show(); - return; - } - const div = this.div = document.createElement("div"); - div.className = "annotationEditorLayer"; - div.hidden = true; - div.dir = this.#uiManager.direction; - this.#onAppend?.(div); - this.annotationEditorLayer = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorLayer({ - uiManager: this.#uiManager, - div, - accessibilityManager: this.accessibilityManager, - pageIndex: this.pdfPage.pageNumber - 1, - l10n: this.l10n, - viewport: clonedViewport, - annotationLayer: this.#annotationLayer, - textLayer: this.#textLayer, - drawLayer: this.#drawLayer - }); - const parameters = { - viewport: clonedViewport, - div, - annotations: null, - intent - }; - this.annotationEditorLayer.render(parameters); - this.show(); - } - cancel() { - this._cancelled = true; - if (!this.div) { - return; - } - this.annotationEditorLayer.destroy(); - } - hide() { - if (!this.div) { - return; - } - this.div.hidden = true; - } - show() { - if (!this.div || this.annotationEditorLayer.isInvisible) { - return; - } - this.div.hidden = false; - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 226: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AnnotationEditorParams: () => (/* binding */ AnnotationEditorParams) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - -class AnnotationEditorParams { - constructor(options, eventBus) { - this.eventBus = eventBus; - this.#bindListeners(options); - } - #bindListeners({ - editorFreeTextFontSize, - editorFreeTextColor, - editorInkColor, - editorInkThickness, - editorInkOpacity, - editorStampAddImage, - editorFreeHighlightThickness, - editorHighlightShowAll - }) { - const dispatchEvent = (typeStr, value) => { - this.eventBus.dispatch("switchannotationeditorparams", { - source: this, - type: pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType[typeStr], - value - }); - }; - editorFreeTextFontSize.addEventListener("input", function () { - dispatchEvent("FREETEXT_SIZE", this.valueAsNumber); - }); - editorFreeTextColor.addEventListener("input", function () { - dispatchEvent("FREETEXT_COLOR", this.value); - }); - editorInkColor.addEventListener("input", function () { - dispatchEvent("INK_COLOR", this.value); - }); - editorInkThickness.addEventListener("input", function () { - dispatchEvent("INK_THICKNESS", this.valueAsNumber); - }); - editorInkOpacity.addEventListener("input", function () { - dispatchEvent("INK_OPACITY", this.valueAsNumber); - }); - editorStampAddImage.addEventListener("click", () => { - dispatchEvent("CREATE"); - }); - editorFreeHighlightThickness.addEventListener("input", function () { - dispatchEvent("HIGHLIGHT_THICKNESS", this.valueAsNumber); - }); - editorHighlightShowAll.addEventListener("click", function () { - const checked = this.getAttribute("aria-pressed") === "true"; - this.setAttribute("aria-pressed", !checked); - dispatchEvent("HIGHLIGHT_SHOW_ALL", !checked); - }); - this.eventBus._on("annotationeditorparamschanged", evt => { - for (const [type, value] of evt.details) { - switch (type) { - case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.FREETEXT_SIZE: - editorFreeTextFontSize.value = value; - break; - case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.FREETEXT_COLOR: - editorFreeTextColor.value = value; - break; - case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.INK_COLOR: - editorInkColor.value = value; - break; - case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.INK_THICKNESS: - editorInkThickness.value = value; - break; - case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.INK_OPACITY: - editorInkOpacity.value = value; - break; - case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: - editorFreeHighlightThickness.value = value; - break; - case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_FREE: - editorFreeHighlightThickness.disabled = !value; - break; - case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL: - editorHighlightShowAll.setAttribute("aria-pressed", value); - break; - } - } - }); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 2707: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AnnotationLayerBuilder: () => (/* binding */ AnnotationLayerBuilder) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -class AnnotationLayerBuilder { - #onAppend = null; - #eventAbortController = null; - constructor({ - pdfPage, - linkService, - downloadManager, - annotationStorage = null, - imageResourcesPath = "", - renderForms = true, - enableScripting = false, - hasJSActionsPromise = null, - fieldObjectsPromise = null, - annotationCanvasMap = null, - accessibilityManager = null, - annotationEditorUIManager = null, - onAppend = null - }) { - this.pdfPage = pdfPage; - this.linkService = linkService; - this.downloadManager = downloadManager; - this.imageResourcesPath = imageResourcesPath; - this.renderForms = renderForms; - this.annotationStorage = annotationStorage; - this.enableScripting = enableScripting; - this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false); - this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null); - this._annotationCanvasMap = annotationCanvasMap; - this._accessibilityManager = accessibilityManager; - this._annotationEditorUIManager = annotationEditorUIManager; - this.#onAppend = onAppend; - this.annotationLayer = null; - this.div = null; - this._cancelled = false; - this._eventBus = linkService.eventBus; - } - async render(viewport, intent = "display") { - if (this.div) { - if (this._cancelled || !this.annotationLayer) { - return; - } - this.annotationLayer.update({ - viewport: viewport.clone({ - dontFlip: true - }) - }); - return; - } - const [annotations, hasJSActions, fieldObjects] = await Promise.all([this.pdfPage.getAnnotations({ - intent - }), this._hasJSActionsPromise, this._fieldObjectsPromise]); - if (this._cancelled) { - return; - } - const div = this.div = document.createElement("div"); - div.className = "annotationLayer"; - this.#onAppend?.(div); - window.parent.postMessage({status: 'loaded'}, '*'); - if (annotations.length === 0) { - // [Custom] always turn the annotationLayer on - // this.hide(); - return; - } - this.annotationLayer = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationLayer({ - div, - accessibilityManager: this._accessibilityManager, - annotationCanvasMap: this._annotationCanvasMap, - annotationEditorUIManager: this._annotationEditorUIManager, - page: this.pdfPage, - viewport: viewport.clone({ - dontFlip: true - }) - }); - await this.annotationLayer.render({ - annotations, - imageResourcesPath: this.imageResourcesPath, - renderForms: this.renderForms, - linkService: this.linkService, - downloadManager: this.downloadManager, - annotationStorage: this.annotationStorage, - enableScripting: this.enableScripting, - hasJSActions, - fieldObjects - }); - if (this.linkService.isInPresentationMode) { - this.#updatePresentationModeState(_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.FULLSCREEN); - } - if (!this.#eventAbortController) { - this.#eventAbortController = new AbortController(); - this._eventBus?._on("presentationmodechanged", evt => { - this.#updatePresentationModeState(evt.state); - }, { - signal: this.#eventAbortController.signal - }); - } - // [custom-annotationLayer] - // console.log('test-custom-annotationLayer', window?.PDFViewerApplication?.pdfViewer?._pages?.length) - window?.PDFViewerApplication?.pdfViewer?._pages?.forEach((i,index) => { - window.parent.postMessage({pageNum: index}, '*'); - }) - - } - cancel() { - this._cancelled = true; - this.#eventAbortController?.abort(); - this.#eventAbortController = null; - } - hide() { - if (!this.div) { - return; - } - this.div.hidden = true; - } - #updatePresentationModeState(state) { - if (!this.div) { - return; - } - let disableFormElements = false; - switch (state) { - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.FULLSCREEN: - disableFormElements = true; - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.NORMAL: - break; - default: - return; - } - for (const section of this.div.childNodes) { - if (section.hasAttribute("data-internal-link")) { - continue; - } - section.inert = disableFormElements; - } - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 1621: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFViewerApplication: () => (/* binding */ PDFViewerApplication) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603); -/* harmony import */ var _app_options_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9840); -/* harmony import */ var _event_utils_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5656); -/* harmony import */ var web_external_services__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6750); -/* harmony import */ var _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(787); -/* harmony import */ var web_alt_text_manager__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(259); -/* harmony import */ var web_annotation_editor_params__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(226); -/* harmony import */ var _caret_browsing_js__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(3973); -/* harmony import */ var web_download_manager__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(1544); -/* harmony import */ var _overlay_manager_js__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(6174); -/* harmony import */ var _password_prompt_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(2690); -/* harmony import */ var web_pdf_attachment_viewer__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(9251); -/* harmony import */ var web_pdf_cursor_tools__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(5993); -/* harmony import */ var web_pdf_document_properties__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(164); -/* harmony import */ var web_pdf_find_bar__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(2226); -/* harmony import */ var _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(9814); -/* harmony import */ var _pdf_history_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(8543); -/* harmony import */ var web_pdf_layer_viewer__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(4275); -/* harmony import */ var web_pdf_outline_viewer__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(5514); -/* harmony import */ var web_pdf_presentation_mode__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(8917); -/* harmony import */ var web_print_service__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(1144); -/* harmony import */ var _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(6615); -/* harmony import */ var _pdf_scripting_manager_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(5942); -/* harmony import */ var web_pdf_sidebar__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(2275); -/* harmony import */ var web_pdf_thumbnail_viewer__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(8280); -/* harmony import */ var _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(6285); -/* harmony import */ var web_secondary_toolbar__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(1900); -/* harmony import */ var web_toolbar__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(6297); -/* harmony import */ var _view_history_js__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(9226); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__, web_external_services__WEBPACK_IMPORTED_MODULE_4__, web_alt_text_manager__WEBPACK_IMPORTED_MODULE_6__, web_annotation_editor_params__WEBPACK_IMPORTED_MODULE_7__, web_download_manager__WEBPACK_IMPORTED_MODULE_8__, _password_prompt_js__WEBPACK_IMPORTED_MODULE_9__, web_pdf_attachment_viewer__WEBPACK_IMPORTED_MODULE_10__, web_pdf_cursor_tools__WEBPACK_IMPORTED_MODULE_11__, web_pdf_document_properties__WEBPACK_IMPORTED_MODULE_12__, web_pdf_presentation_mode__WEBPACK_IMPORTED_MODULE_18__, web_print_service__WEBPACK_IMPORTED_MODULE_19__, _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_20__, _pdf_scripting_manager_js__WEBPACK_IMPORTED_MODULE_21__, web_pdf_thumbnail_viewer__WEBPACK_IMPORTED_MODULE_23__, _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_24__, web_secondary_toolbar__WEBPACK_IMPORTED_MODULE_25__, web_toolbar__WEBPACK_IMPORTED_MODULE_26__]); -([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__, web_external_services__WEBPACK_IMPORTED_MODULE_4__, web_alt_text_manager__WEBPACK_IMPORTED_MODULE_6__, web_annotation_editor_params__WEBPACK_IMPORTED_MODULE_7__, web_download_manager__WEBPACK_IMPORTED_MODULE_8__, _password_prompt_js__WEBPACK_IMPORTED_MODULE_9__, web_pdf_attachment_viewer__WEBPACK_IMPORTED_MODULE_10__, web_pdf_cursor_tools__WEBPACK_IMPORTED_MODULE_11__, web_pdf_document_properties__WEBPACK_IMPORTED_MODULE_12__, web_pdf_presentation_mode__WEBPACK_IMPORTED_MODULE_18__, web_print_service__WEBPACK_IMPORTED_MODULE_19__, _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_20__, _pdf_scripting_manager_js__WEBPACK_IMPORTED_MODULE_21__, web_pdf_thumbnail_viewer__WEBPACK_IMPORTED_MODULE_23__, _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_24__, web_secondary_toolbar__WEBPACK_IMPORTED_MODULE_25__, web_toolbar__WEBPACK_IMPORTED_MODULE_26__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const FORCE_PAGES_LOADED_TIMEOUT = 10000; -const WHEEL_ZOOM_DISABLED_TIMEOUT = 1000; -const ViewOnLoad = { - UNKNOWN: -1, - PREVIOUS: 0, - INITIAL: 1 -}; - -const PDFViewerApplication = { - initialBookmark: document.location.hash.substring(1), - _initializedCapability: { - ...Promise.withResolvers(), - settled: false - }, - appConfig: null, - pdfDocument: null, - pdfLoadingTask: null, - printService: null, - pdfViewer: null, - pdfThumbnailViewer: null, - pdfRenderingQueue: null, - pdfPresentationMode: null, - pdfDocumentProperties: null, - pdfLinkService: null, - pdfHistory: null, - pdfSidebar: null, - pdfOutlineViewer: null, - pdfAttachmentViewer: null, - pdfLayerViewer: null, - pdfCursorTools: null, - pdfScriptingManager: null, - store: null, - downloadManager: null, - overlayManager: null, - preferences: null, - toolbar: null, - secondaryToolbar: null, - eventBus: null, - l10n: null, - annotationEditorParams: null, - isInitialViewSet: false, - downloadComplete: false, - isViewerEmbedded: window.parent !== window, - url: "", - baseUrl: "", - _downloadUrl: "", - _eventBusAbortController: null, - _windowAbortController: null, - documentInfo: null, - metadata: null, - _contentDispositionFilename: null, - _contentLength: null, - _saveInProgress: false, - _wheelUnusedTicks: 0, - _wheelUnusedFactor: 1, - _touchUnusedTicks: 0, - _touchUnusedFactor: 1, - _PDFBug: null, - _hasAnnotationEditors: false, - _title: document.title, - _printAnnotationStoragePromise: null, - _touchInfo: null, - _isCtrlKeyDown: false, - _nimbusDataPromise: null, - _caretBrowsing: null, - _isScrolling: false, - async initialize(appConfig) { - let l10nPromise; - this.appConfig = appConfig; - try { - await this.preferences.initializedPromise; - } catch (ex) { - console.error(`initialize: "${ex.message}".`); - } - if (_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("pdfBugEnabled")) { - await this._parseHashParams(); - } - let mode; - switch (_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("viewerCssTheme")) { - case 1: - mode = "is-light"; - break; - case 2: - mode = "is-dark"; - break; - } - if (mode) { - document.documentElement.classList.add(mode); - } - l10nPromise = this.externalServices.createL10n(); - this.l10n = await l10nPromise; - document.getElementsByTagName("html")[0].dir = this.l10n.getDirection(); - this.l10n.translate(appConfig.appContainer || document.documentElement); - if (this.isViewerEmbedded && _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("externalLinkTarget") === _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__.LinkTarget.NONE) { - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("externalLinkTarget", _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__.LinkTarget.TOP); - } - - await this._initializeViewerComponents(); - this.bindEvents(); - this.bindWindowEvents(); - this._initializedCapability.settled = true; - this._initializedCapability.resolve(); - }, - async _parseHashParams() { - const hash = document.location.hash.substring(1); - if (!hash) { - return; - } - const { - mainContainer, - viewerContainer - } = this.appConfig, - params = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.parseQueryString)(hash); - if (params.get("disableworker") === "true") { - try { - await loadFakeWorker(); - } catch (ex) { - console.error(`_parseHashParams: "${ex.message}".`); - } - } - if (params.has("disablerange")) { - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("disableRange", params.get("disablerange") === "true"); - } - if (params.has("disablestream")) { - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("disableStream", params.get("disablestream") === "true"); - } - if (params.has("disableautofetch")) { - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("disableAutoFetch", params.get("disableautofetch") === "true"); - } - if (params.has("disablefontface")) { - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("disableFontFace", params.get("disablefontface") === "true"); - } - if (params.has("disablehistory")) { - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("disableHistory", params.get("disablehistory") === "true"); - } - if (params.has("verbosity")) { - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("verbosity", params.get("verbosity") | 0); - } - if (params.has("textlayer")) { - switch (params.get("textlayer")) { - case "off": - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("textLayerMode", _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.TextLayerMode.DISABLE); - break; - case "visible": - case "shadow": - case "hover": - viewerContainer.classList.add(`textLayer-${params.get("textlayer")}`); - try { - await loadPDFBug(this); - this._PDFBug.loadCSS(); - } catch (ex) { - console.error(`_parseHashParams: "${ex.message}".`); - } - break; - } - } - if (params.has("pdfbug")) { - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("pdfBug", true); - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("fontExtraProperties", true); - const enabled = params.get("pdfbug").split(","); - try { - await loadPDFBug(this); - this._PDFBug.init(mainContainer, enabled); - } catch (ex) { - console.error(`_parseHashParams: "${ex.message}".`); - } - } - if (params.has("locale")) { - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("locale", params.get("locale")); - } - }, - async _initializeViewerComponents() { - const { - appConfig, - externalServices, - l10n - } = this; - const eventBus = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("isInAutomation") ? new _event_utils_js__WEBPACK_IMPORTED_MODULE_3__.AutomationEventBus() : new _event_utils_js__WEBPACK_IMPORTED_MODULE_3__.EventBus(); - this.eventBus = eventBus; - this.overlayManager = new _overlay_manager_js__WEBPACK_IMPORTED_MODULE_27__.OverlayManager(); - const pdfRenderingQueue = new _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_20__.PDFRenderingQueue(); - pdfRenderingQueue.onIdle = this._cleanup.bind(this); - this.pdfRenderingQueue = pdfRenderingQueue; - const pdfLinkService = new _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__.PDFLinkService({ - eventBus, - externalLinkTarget: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("externalLinkTarget"), - externalLinkRel: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("externalLinkRel"), - ignoreDestinationZoom: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("ignoreDestinationZoom") - }); - this.pdfLinkService = pdfLinkService; - const downloadManager = this.downloadManager = new web_download_manager__WEBPACK_IMPORTED_MODULE_8__.DownloadManager(); - const findController = new _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_14__.PDFFindController({ - linkService: pdfLinkService, - eventBus, - updateMatchesCountOnProgress: true - }); - this.findController = findController; - const pdfScriptingManager = new _pdf_scripting_manager_js__WEBPACK_IMPORTED_MODULE_21__.PDFScriptingManager({ - eventBus, - externalServices, - docProperties: this._scriptingDocProperties.bind(this) - }); - this.pdfScriptingManager = pdfScriptingManager; - - const container = appConfig.mainContainer, - viewer = appConfig.viewerContainer; - const annotationEditorMode = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("annotationEditorMode"); - const pageColors = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("forcePageColors") || window.matchMedia("(forced-colors: active)").matches ? { - background: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("pageColorsBackground"), - foreground: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("pageColorsForeground") - } : null; - const altTextManager = appConfig.altTextDialog ? new web_alt_text_manager__WEBPACK_IMPORTED_MODULE_6__.AltTextManager(appConfig.altTextDialog, container, this.overlayManager, eventBus) : null; - // pdf的dom初始化配置的在这里 - - const pdfViewer = new _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_24__.PDFViewer({ - container, - viewer, - eventBus, - renderingQueue: pdfRenderingQueue, - linkService: pdfLinkService, - downloadManager, - altTextManager, - findController, - scriptingManager: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("enableScripting") && pdfScriptingManager, - l10n, - textLayerMode: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("textLayerMode"), - annotationMode: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("annotationMode"), - annotationEditorMode, - annotationEditorHighlightColors: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("highlightEditorColors"), - enableHighlightFloatingButton: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("enableHighlightFloatingButton"), - imageResourcesPath: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("imageResourcesPath"), - enablePrintAutoRotate: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("enablePrintAutoRotate"), - maxCanvasPixels: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("maxCanvasPixels"), - enablePermissions: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("enablePermissions"), - pageColors, - mlManager: this.mlManager - }); - this.pdfViewer = pdfViewer; - pdfRenderingQueue.setViewer(pdfViewer); - pdfLinkService.setViewer(pdfViewer); - pdfScriptingManager.setViewer(pdfViewer); - if (appConfig.sidebar?.thumbnailView) { - this.pdfThumbnailViewer = new web_pdf_thumbnail_viewer__WEBPACK_IMPORTED_MODULE_23__.PDFThumbnailViewer({ - container: appConfig.sidebar.thumbnailView, - eventBus, - renderingQueue: pdfRenderingQueue, - linkService: pdfLinkService, - pageColors - }); - pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer); - } - if (!this.isViewerEmbedded && !_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("disableHistory")) { - this.pdfHistory = new _pdf_history_js__WEBPACK_IMPORTED_MODULE_15__.PDFHistory({ - linkService: pdfLinkService, - eventBus - }); - pdfLinkService.setHistory(this.pdfHistory); - } - if (!this.supportsIntegratedFind && appConfig.findBar) { - this.findBar = new web_pdf_find_bar__WEBPACK_IMPORTED_MODULE_13__.PDFFindBar(appConfig.findBar, eventBus); - } - - if (appConfig.annotationEditorParams) { - if (annotationEditorMode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditorType.DISABLE) { - if (_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("enableStampEditor")) { - // 需要隐藏添加hidden即可 - appConfig.toolbar?.editorStampButton?.classList.remove("hidden"); - } - const editorHighlightButton = appConfig.toolbar?.editorHighlightButton; - if (editorHighlightButton && _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("enableHighlightEditor")) { - editorHighlightButton.hidden = false; - } - this.annotationEditorParams = new web_annotation_editor_params__WEBPACK_IMPORTED_MODULE_7__.AnnotationEditorParams(appConfig.annotationEditorParams, eventBus); - } else { - for (const id of ["editorModeButtons", "editorModeSeparator"]) { - document.getElementById(id)?.classList.add("hidden"); - } - } - } - if (appConfig.documentProperties) { - // [custom] 初始化的时候给odl-dom添加title - this.pdfDocumentProperties = new web_pdf_document_properties__WEBPACK_IMPORTED_MODULE_12__.PDFDocumentProperties(appConfig.documentProperties, this.overlayManager, eventBus, l10n, () => this._docFilename); - } - if (appConfig.secondaryToolbar?.cursorHandToolButton) { - this.pdfCursorTools = new web_pdf_cursor_tools__WEBPACK_IMPORTED_MODULE_11__.PDFCursorTools({ - container, - eventBus, - cursorToolOnLoad: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("cursorToolOnLoad") - }); - } - if (appConfig.toolbar) { - this.toolbar = new web_toolbar__WEBPACK_IMPORTED_MODULE_26__.Toolbar(appConfig.toolbar, eventBus); - } - if (appConfig.secondaryToolbar) { - this.secondaryToolbar = new web_secondary_toolbar__WEBPACK_IMPORTED_MODULE_25__.SecondaryToolbar(appConfig.secondaryToolbar, eventBus); - } - if (this.supportsFullscreen && appConfig.secondaryToolbar?.presentationModeButton) { - this.pdfPresentationMode = new web_pdf_presentation_mode__WEBPACK_IMPORTED_MODULE_18__.PDFPresentationMode({ - container, - pdfViewer, - eventBus - }); - } - if (appConfig.passwordOverlay) { - this.passwordPrompt = new _password_prompt_js__WEBPACK_IMPORTED_MODULE_9__.PasswordPrompt(appConfig.passwordOverlay, this.overlayManager, this.isViewerEmbedded); - } - // console.log('test-appConfig.sidebar', appConfig.sidebar) - if (appConfig.sidebar?.outlineView) { - this.pdfOutlineViewer = new web_pdf_outline_viewer__WEBPACK_IMPORTED_MODULE_17__.PDFOutlineViewer({ - container: appConfig.sidebar.outlineView, - eventBus, - l10n, - linkService: pdfLinkService, - downloadManager - }); - } - if (appConfig.sidebar?.attachmentsView) { - this.pdfAttachmentViewer = new web_pdf_attachment_viewer__WEBPACK_IMPORTED_MODULE_10__.PDFAttachmentViewer({ - container: appConfig.sidebar.attachmentsView, - eventBus, - l10n, - downloadManager - }); - } - if (appConfig.sidebar?.layersView) { - this.pdfLayerViewer = new web_pdf_layer_viewer__WEBPACK_IMPORTED_MODULE_16__.PDFLayerViewer({ - container: appConfig.sidebar.layersView, - eventBus, - l10n - }); - } - if (appConfig.sidebar) { - this.pdfSidebar = new web_pdf_sidebar__WEBPACK_IMPORTED_MODULE_22__.PDFSidebar({ - elements: appConfig.sidebar, - eventBus, - l10n - }); - this.pdfSidebar.onToggled = this.forceRendering.bind(this); - this.pdfSidebar.onUpdateThumbnails = () => { - for (const pageView of pdfViewer.getCachedPageViews()) { - if (pageView.renderingState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED) { - this.pdfThumbnailViewer.getThumbnail(pageView.id - 1)?.setImage(pageView); - } - } - this.pdfThumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber); - }; - } - }, - async run(config) { - this.preferences = new web_external_services__WEBPACK_IMPORTED_MODULE_4__.Preferences(); - - await this.initialize(config); - const { - appConfig, - eventBus - } = this; - let file; - const queryString = document.location.search.substring(1); - const params = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.parseQueryString)(queryString); - // TODO这里添加url - file = params.get("file") ?? _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("defaultUrl"); - validateFileURL(file); - const fileInput = this._openFileInput = document.createElement("input"); - fileInput.id = "fileInput"; - fileInput.hidden = true; - fileInput.type = "file"; - fileInput.value = null; - document.body.append(fileInput); - fileInput.addEventListener("change", function (evt) { - const { - files - } = evt.target; - if (!files || files.length === 0) { - return; - } - console.log('test-file-open',files) - eventBus.dispatch("fileinputchange", { - source: this, - fileInput: evt.target - }); - }); - - appConfig.mainContainer.addEventListener("dragover", function (evt) { - evt.preventDefault(); - evt.dataTransfer.dropEffect = evt.dataTransfer.effectAllowed === "copy" ? "copy" : "move"; - }); - appConfig.mainContainer.addEventListener("drop", function (evt) { - evt.preventDefault(); - const { - files - } = evt.dataTransfer; - if (!files || files.length === 0) { - return; - } - eventBus.dispatch("fileinputchange", { - source: this, - fileInput: evt.dataTransfer - }); - }); - if (!_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("supportsDocumentFonts")) { - _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.set("disableFontFace", true); - this.l10n.get("pdfjs-web-fonts-disabled").then(msg => { - console.warn(msg); - }); - } - if (!this.supportsPrinting) { - appConfig.toolbar?.print?.classList.add("hidden"); - appConfig.secondaryToolbar?.printButton.classList.add("hidden"); - } - if (!this.supportsFullscreen) { - appConfig.secondaryToolbar?.presentationModeButton.classList.add("hidden"); - } - if (this.supportsIntegratedFind) { - appConfig.toolbar?.viewFind?.classList.add("hidden"); - } - if (file) { - this.open({ - url: file - }); - } else { - this._hideViewBookmark(); - } - }, - get externalServices() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "externalServices", new web_external_services__WEBPACK_IMPORTED_MODULE_4__.ExternalServices()); - }, - get mlManager() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "mlManager", _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("enableML") === true ? new web_external_services__WEBPACK_IMPORTED_MODULE_4__.MLManager() : null); - }, - get initialized() { - return this._initializedCapability.settled; - }, - get initializedPromise() { - return this._initializedCapability.promise; - }, - zoomIn(steps, scaleFactor) { - if (this.pdfViewer.isInPresentationMode) { - return; - } - this.pdfViewer.increaseScale({ - drawingDelay: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("defaultZoomDelay"), - steps, - scaleFactor - }); - }, - zoomOut(steps, scaleFactor) { - if (this.pdfViewer.isInPresentationMode) { - return; - } - this.pdfViewer.decreaseScale({ - drawingDelay: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("defaultZoomDelay"), - steps, - scaleFactor - }); - }, - zoomReset() { - if (this.pdfViewer.isInPresentationMode) { - return; - } - this.pdfViewer.currentScaleValue = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_SCALE_VALUE; - }, - get pagesCount() { - return this.pdfDocument ? this.pdfDocument.numPages : 0; - }, - get page() { - return this.pdfViewer.currentPageNumber; - }, - set page(val) { - this.pdfViewer.currentPageNumber = val; - }, - get supportsPrinting() { - return web_print_service__WEBPACK_IMPORTED_MODULE_19__.PDFPrintServiceFactory.supportsPrinting; - }, - get supportsFullscreen() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "supportsFullscreen", document.fullscreenEnabled); - }, - get supportsPinchToZoom() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "supportsPinchToZoom", _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("supportsPinchToZoom")); - }, - get supportsIntegratedFind() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "supportsIntegratedFind", _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("supportsIntegratedFind")); - }, - get loadingBar() { - const barElement = document.getElementById("loadingBar"); - const bar = barElement ? new _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ProgressBar(barElement) : null; - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "loadingBar", bar); - }, - get supportsMouseWheelZoomCtrlKey() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "supportsMouseWheelZoomCtrlKey", _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("supportsMouseWheelZoomCtrlKey")); - }, - get supportsMouseWheelZoomMetaKey() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "supportsMouseWheelZoomMetaKey", _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("supportsMouseWheelZoomMetaKey")); - }, - get supportsCaretBrowsingMode() { - return _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("supportsCaretBrowsingMode"); - }, - moveCaret(isUp, select) { - this._caretBrowsing ||= new _caret_browsing_js__WEBPACK_IMPORTED_MODULE_28__.CaretBrowsingMode(this.appConfig.mainContainer, this.appConfig.viewerContainer, this.appConfig.toolbar?.container); - this._caretBrowsing.moveCaret(isUp, select); - }, - setTitleUsingUrl(url = "", downloadUrl = null) { - this.url = url; - this.baseUrl = url.split("#", 1)[0]; - if (downloadUrl) { - this._downloadUrl = downloadUrl === url ? this.baseUrl : downloadUrl.split("#", 1)[0]; - } - if ((0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.isDataScheme)(url)) { - this._hideViewBookmark(); - } - let title = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.getPdfFilenameFromUrl)(url, ""); - if (!title) { - try { - title = decodeURIComponent((0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.getFilenameFromUrl)(url)) || url; - } catch { - title = url; - } - } - this.setTitle(title); - }, - setTitle(title = this._title) { - this._title = title; - if (this.isViewerEmbedded) { - return; - } - const editorIndicator = this._hasAnnotationEditors && !this.pdfRenderingQueue.printing; - document.title = `${editorIndicator ? "* " : ""}${title}`; - }, - get _docFilename() { - return this._contentDispositionFilename || (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.getPdfFilenameFromUrl)(this.url); - }, - _hideViewBookmark() { - const { - secondaryToolbar - } = this.appConfig; - secondaryToolbar?.viewBookmarkButton.classList.add("hidden"); - if (secondaryToolbar?.presentationModeButton.classList.contains("hidden")) { - document.getElementById("viewBookmarkSeparator")?.classList.add("hidden"); - } - }, - async close() { - this._unblockDocumentLoadEvent(); - this._hideViewBookmark(); - if (!this.pdfLoadingTask) { - return; - } - if (this.pdfDocument?.annotationStorage.size > 0 && this._annotationStorageModified) { - try { - await this.save(); - } catch {} - } - const promises = []; - promises.push(this.pdfLoadingTask.destroy()); - this.pdfLoadingTask = null; - if (this.pdfDocument) { - this.pdfDocument = null; - this.pdfThumbnailViewer?.setDocument(null); - this.pdfViewer.setDocument(null); - this.pdfLinkService.setDocument(null); - this.pdfDocumentProperties?.setDocument(null); - } - this.pdfLinkService.externalLinkEnabled = true; - this.store = null; - this.isInitialViewSet = false; - this.downloadComplete = false; - this.url = ""; - this.baseUrl = ""; - this._downloadUrl = ""; - this.documentInfo = null; - this.metadata = null; - this._contentDispositionFilename = null; - this._contentLength = null; - this._saveInProgress = false; - this._hasAnnotationEditors = false; - promises.push(this.pdfScriptingManager.destroyPromise, this.passwordPrompt.close()); - this.setTitle(); - this.pdfSidebar?.reset(); - this.pdfOutlineViewer?.reset(); - this.pdfAttachmentViewer?.reset(); - this.pdfLayerViewer?.reset(); - this.pdfHistory?.reset(); - this.findBar?.reset(); - this.toolbar?.reset(); - this.secondaryToolbar?.reset(); - this._PDFBug?.cleanup(); - await Promise.all(promises); - }, - async open(args) { - // TIP: 打开pdf并且进行解析的逻辑 - if (this.pdfLoadingTask) { - await this.close(); - } - // console.log('test-pdf', this) - - const workerParams = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.getAll(_app_options_js__WEBPACK_IMPORTED_MODULE_2__.OptionKind.WORKER); - Object.assign(pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.GlobalWorkerOptions, workerParams); - if (args.url) { - this.setTitleUsingUrl(args.originalUrl || args.url, args.url); - } - const apiParams = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.getAll(_app_options_js__WEBPACK_IMPORTED_MODULE_2__.OptionKind.API); - const loadingTask = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.getDocument)({ - ...apiParams, - ...args - }); - this.pdfLoadingTask = loadingTask; - loadingTask.onPassword = (updateCallback, reason) => { - if (this.isViewerEmbedded) { - this._unblockDocumentLoadEvent(); - } - this.pdfLinkService.externalLinkEnabled = false; - this.passwordPrompt.setUpdateCallback(updateCallback, reason); - this.passwordPrompt.open(); - }; - loadingTask.onProgress = ({ - loaded, - total - }) => { - this.progress(loaded / total); - }; - - return loadingTask.promise.then(pdfDocument => { - // [Custom] desc: aƒdd loaded listen - // console.log('test-loaded') - this.load(pdfDocument); - }, reason => { - if (loadingTask !== this.pdfLoadingTask) { - return undefined; - } - let key = "pdfjs-loading-error"; - if (reason instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.InvalidPDFException) { - key = "pdfjs-invalid-file-error"; - } else if (reason instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.MissingPDFException) { - key = "pdfjs-missing-file-error"; - } else if (reason instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.UnexpectedResponseException) { - key = "pdfjs-unexpected-response-error"; - } - return this._documentError(key, { - message: reason.message - }).then(() => { - throw reason; - }); - }); - }, - _ensureDownloadComplete() { - if (this.pdfDocument && this.downloadComplete) { - return; - } - throw new Error("PDF document not downloaded."); - }, - async download(options = {}) { - const url = this._downloadUrl, - filename = this._docFilename; - try { - this._ensureDownloadComplete(); - const data = await this.pdfDocument.getData(); - const blob = new Blob([data], { - type: "application/pdf" - }); - await this.downloadManager.download(blob, url, filename, options); - } catch { - await this.downloadManager.downloadUrl(url, filename, options); - } - }, - async save(options = {}) { - if (this._saveInProgress) { - return; - } - this._saveInProgress = true; - await this.pdfScriptingManager.dispatchWillSave(); - const url = this._downloadUrl, - filename = this._docFilename; - try { - this._ensureDownloadComplete(); - const data = await this.pdfDocument.saveDocument(); - const blob = new Blob([data], { - type: "application/pdf" - }); - await this.downloadManager.download(blob, url, filename, options); - } catch (reason) { - console.error(`Error when saving the document: ${reason.message}`); - await this.download(options); - } finally { - await this.pdfScriptingManager.dispatchDidSave(); - this._saveInProgress = false; - } - if (this._hasAnnotationEditors) { - this.externalServices.reportTelemetry({ - type: "editing", - data: { - type: "save", - stats: this.pdfDocument?.annotationStorage.editorStats - } - }); - } - }, - downloadOrSave(options = {}) { - if (this.pdfDocument?.annotationStorage.size > 0) { - this.save(options); - } else { - this.download(options); - } - }, - async _documentError(key, moreInfo = null) { - this._unblockDocumentLoadEvent(); - const message = await this._otherError(key || "pdfjs-loading-error", moreInfo); - this.eventBus.dispatch("documenterror", { - source: this, - message, - reason: moreInfo?.message ?? null - }); - }, - async _otherError(key, moreInfo = null) { - const message = await this.l10n.get(key); - const moreInfoText = [`PDF.js v${pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.version || "?"} (build: ${pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.build || "?"})`]; - if (moreInfo) { - moreInfoText.push(`Message: ${moreInfo.message}`); - if (moreInfo.stack) { - moreInfoText.push(`Stack: ${moreInfo.stack}`); - } else { - if (moreInfo.filename) { - moreInfoText.push(`File: ${moreInfo.filename}`); - } - if (moreInfo.lineNumber) { - moreInfoText.push(`Line: ${moreInfo.lineNumber}`); - } - } - } - console.error(`${message}\n\n${moreInfoText.join("\n")}`); - return message; - }, - progress(level) { - if (!this.loadingBar || this.downloadComplete) { - return; - } - const percent = Math.round(level * 100); - if (percent <= this.loadingBar.percent) { - return; - } - this.loadingBar.percent = percent; - if (this.pdfDocument?.loadingParams.disableAutoFetch ?? _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("disableAutoFetch")) { - this.loadingBar.setDisableAutoFetch(); - } - }, - load(pdfDocument) { - this.pdfDocument = pdfDocument; - pdfDocument.getDownloadInfo().then(({ - length - }) => { - this._contentLength = length; - this.downloadComplete = true; - this.loadingBar?.hide(); - firstPagePromise.then(() => { - this.eventBus.dispatch("documentloaded", { - source: this - }); - }); - }); - const pageLayoutPromise = pdfDocument.getPageLayout().catch(() => {}); - const pageModePromise = pdfDocument.getPageMode().catch(() => {}); - const openActionPromise = pdfDocument.getOpenAction().catch(() => {}); - this.toolbar?.setPagesCount(pdfDocument.numPages, false); - this.secondaryToolbar?.setPagesCount(pdfDocument.numPages); - this.pdfLinkService.setDocument(pdfDocument); - this.pdfDocumentProperties?.setDocument(pdfDocument); - const pdfViewer = this.pdfViewer; - pdfViewer.setDocument(pdfDocument); - const { - firstPagePromise, - onePageRendered, - pagesPromise - } = pdfViewer; - this.pdfThumbnailViewer?.setDocument(pdfDocument); - const storedPromise = (this.store = new _view_history_js__WEBPACK_IMPORTED_MODULE_29__.ViewHistory(pdfDocument.fingerprints[0])).getMultiple({ - page: null, - zoom: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_SCALE_VALUE, - scrollLeft: "0", - scrollTop: "0", - rotation: null, - sidebarView: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.UNKNOWN, - scrollMode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.UNKNOWN, - spreadMode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.UNKNOWN - }).catch(() => {}); - firstPagePromise.then(pdfPage => { - this.loadingBar?.setWidth(this.appConfig.viewerContainer); - this._initializeAnnotationStorageCallbacks(pdfDocument); - Promise.all([_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.animationStarted, storedPromise, pageLayoutPromise, pageModePromise, openActionPromise]).then(async ([timeStamp, stored, pageLayout, pageMode, openAction]) => { - const viewOnLoad = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("viewOnLoad"); - this._initializePdfHistory({ - fingerprint: pdfDocument.fingerprints[0], - viewOnLoad, - initialDest: openAction?.dest - }); - const initialBookmark = this.initialBookmark; - const zoom = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("defaultZoomValue"); - let hash = zoom ? `zoom=${zoom}` : null; - let rotation = null; - let sidebarView = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("sidebarViewOnLoad"); - let scrollMode = 3 || _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("scrollModeOnLoad"); - let spreadMode = _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("spreadModeOnLoad"); - console.log('test-page-mode', sidebarView, scrollMode, spreadMode, stored.page) - if (stored?.page && viewOnLoad !== ViewOnLoad.INITIAL) { - // [custom] - // hash = `page=${stored.page}&zoom=${zoom || stored.zoom},` + `${stored.scrollLeft},${stored.scrollTop}`; - hash = `page=${0}&zoom=${zoom || stored.zoom},` + `${stored.scrollLeft},${stored.scrollTop}`; - rotation = parseInt(stored.rotation, 10); - if (sidebarView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.UNKNOWN) { - sidebarView = stored.sidebarView | 0; - } - if (scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.UNKNOWN) { - scrollMode = stored.scrollMode | 0; - } - if (spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.UNKNOWN) { - spreadMode = stored.spreadMode | 0; - } - } - if (pageMode && sidebarView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.UNKNOWN) { - sidebarView = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.apiPageModeToSidebarView)(pageMode); - } - if (pageLayout && scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.UNKNOWN && spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.UNKNOWN) { - const modes = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.apiPageLayoutToViewerModes)(pageLayout); - spreadMode = modes.spreadMode; - } - // TIP: 屏蔽上述scrollMode逻辑强制设置scrollMode 为3 - // custom scrollMode - // console.log('test-dd', evt.pageNumber) - scrollMode = 2 - spreadMode = 0 - this.setInitialView(hash, { - rotation, - sidebarView, - scrollMode, - spreadMode - }); - this.eventBus.dispatch("documentinit", { - source: this - }); - if (!this.isViewerEmbedded) { - pdfViewer.focus(); - } - await Promise.race([pagesPromise, new Promise(resolve => { - setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT); - })]); - if (!initialBookmark && !hash) { - return; - } - if (pdfViewer.hasEqualPageSizes) { - return; - } - this.initialBookmark = initialBookmark; - pdfViewer.currentScaleValue = pdfViewer.currentScaleValue; - this.setInitialView(hash); - }).catch(() => { - this.setInitialView(); - }).then(function () { - pdfViewer.update(); - }); - }); - pagesPromise.then(() => { - this._unblockDocumentLoadEvent(); - this._initializeAutoPrint(pdfDocument, openActionPromise); - }, reason => { - this._documentError("pdfjs-loading-error", { - message: reason.message - }); - }); - onePageRendered.then(data => { - this.externalServices.reportTelemetry({ - type: "pageInfo", - timestamp: data.timestamp - }); - if (this.pdfOutlineViewer) { - pdfDocument.getOutline().then(outline => { - if (pdfDocument !== this.pdfDocument) { - return; - } - this.pdfOutlineViewer.render({ - outline, - pdfDocument - }); - }); - } - if (this.pdfAttachmentViewer) { - pdfDocument.getAttachments().then(attachments => { - if (pdfDocument !== this.pdfDocument) { - return; - } - this.pdfAttachmentViewer.render({ - attachments - }); - }); - } - if (this.pdfLayerViewer) { - pdfViewer.optionalContentConfigPromise.then(optionalContentConfig => { - if (pdfDocument !== this.pdfDocument) { - return; - } - this.pdfLayerViewer.render({ - optionalContentConfig, - pdfDocument - }); - }); - } - }); - this._initializePageLabels(pdfDocument); - this._initializeMetadata(pdfDocument); - }, - async _scriptingDocProperties(pdfDocument) { - if (!this.documentInfo) { - await new Promise(resolve => { - this.eventBus._on("metadataloaded", resolve, { - once: true - }); - }); - if (pdfDocument !== this.pdfDocument) { - return null; - } - } - if (!this._contentLength) { - await new Promise(resolve => { - this.eventBus._on("documentloaded", resolve, { - once: true - }); - }); - if (pdfDocument !== this.pdfDocument) { - return null; - } - } - return { - ...this.documentInfo, - baseURL: this.baseUrl, - filesize: this._contentLength, - filename: this._docFilename, - metadata: this.metadata?.getRaw(), - authors: this.metadata?.get("dc:creator"), - numPages: this.pagesCount, - URL: this.url - }; - }, - async _initializeAutoPrint(pdfDocument, openActionPromise) { - const [openAction, jsActions] = await Promise.all([openActionPromise, this.pdfViewer.enableScripting ? null : pdfDocument.getJSActions()]); - if (pdfDocument !== this.pdfDocument) { - return; - } - let triggerAutoPrint = openAction?.action === "Print"; - if (jsActions) { - console.warn("Warning: JavaScript support is not enabled"); - for (const name in jsActions) { - if (triggerAutoPrint) { - break; - } - switch (name) { - case "WillClose": - case "WillSave": - case "DidSave": - case "WillPrint": - case "DidPrint": - continue; - } - triggerAutoPrint = jsActions[name].some(js => _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.AutoPrintRegExp.test(js)); - } - } - if (triggerAutoPrint) { - this.triggerPrinting(); - } - }, - async _initializeMetadata(pdfDocument) { - const { - info, - metadata, - contentDispositionFilename, - contentLength - } = await pdfDocument.getMetadata(); - if (pdfDocument !== this.pdfDocument) { - return; - } - this.documentInfo = info; - this.metadata = metadata; - this._contentDispositionFilename ??= contentDispositionFilename; - this._contentLength ??= contentLength; - // TIP:赋予title的逻辑 - // console.log(`PDF ${pdfDocument.fingerprints[0]} [${info.PDFFormatVersion} ` + `${(info.Producer || "-").trim()} / ${(info.Creator || "-").trim()}] ` + `(PDF.js: ${pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.version || "?"} [${pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.build || "?"}])`); - let pdfTitle = info.Title; - - const metadataTitle = metadata?.get("dc:title"); - if (metadataTitle) { - if (metadataTitle !== "Untitled" && !/[\uFFF0-\uFFFF]/g.test(metadataTitle)) { - pdfTitle = metadataTitle; - } - } - - if (pdfTitle) { - this.setTitle(`${pdfTitle} - ${this._contentDispositionFilename || this._title}`); - } else if (this._contentDispositionFilename) { - this.setTitle(this._contentDispositionFilename); - } - // [Custom] desc: use title from postMessage - // const odlPdfTitle = document.getElementById("odl-pdf-title"); - // odlPdfTitle.innerText = this._contentDispositionFilename || this._title; - // odlPdfTitle.setAttribute('title', this._contentDispositionFilename || this._title); - if (info.IsXFAPresent && !info.IsAcroFormPresent && !pdfDocument.isPureXfa) { - if (pdfDocument.loadingParams.enableXfa) { - console.warn("Warning: XFA Foreground documents are not supported"); - } else { - console.warn("Warning: XFA support is not enabled"); - } - } else if ((info.IsAcroFormPresent || info.IsXFAPresent) && !this.pdfViewer.renderForms) { - console.warn("Warning: Interactive form support is not enabled"); - } - if (info.IsSignaturesPresent) { - console.warn("Warning: Digital signatures validation is not supported"); - } - this.eventBus.dispatch("metadataloaded", { - source: this - }); - }, - async _initializePageLabels(pdfDocument) { - const labels = await pdfDocument.getPageLabels(); - if (pdfDocument !== this.pdfDocument) { - return; - } - if (!labels || _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("disablePageLabels")) { - return; - } - const numLabels = labels.length; - let standardLabels = 0, - emptyLabels = 0; - for (let i = 0; i < numLabels; i++) { - const label = labels[i]; - if (label === (i + 1).toString()) { - standardLabels++; - } else if (label === "") { - emptyLabels++; - } else { - break; - } - } - if (standardLabels >= numLabels || emptyLabels >= numLabels) { - return; - } - const { - pdfViewer, - pdfThumbnailViewer, - toolbar - } = this; - pdfViewer.setPageLabels(labels); - pdfThumbnailViewer?.setPageLabels(labels); - toolbar?.setPagesCount(numLabels, true); - toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel); - }, - _initializePdfHistory({ - fingerprint, - viewOnLoad, - initialDest = null - }) { - if (!this.pdfHistory) { - return; - } - this.pdfHistory.initialize({ - fingerprint, - resetHistory: viewOnLoad === ViewOnLoad.INITIAL, - updateUrl: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("historyUpdateUrl") - }); - if (this.pdfHistory.initialBookmark) { - this.initialBookmark = this.pdfHistory.initialBookmark; - this.initialRotation = this.pdfHistory.initialRotation; - } - if (initialDest && !this.initialBookmark && viewOnLoad === ViewOnLoad.UNKNOWN) { - this.initialBookmark = JSON.stringify(initialDest); - this.pdfHistory.push({ - explicitDest: initialDest, - pageNumber: null - }); - } - }, - _initializeAnnotationStorageCallbacks(pdfDocument) { - if (pdfDocument !== this.pdfDocument) { - return; - } - const { - annotationStorage - } = pdfDocument; - annotationStorage.onSetModified = () => { - window.addEventListener("beforeunload", beforeUnload); - this._annotationStorageModified = true; - }; - annotationStorage.onResetModified = () => { - window.removeEventListener("beforeunload", beforeUnload); - delete this._annotationStorageModified; - }; - annotationStorage.onAnnotationEditor = typeStr => { - this._hasAnnotationEditors = !!typeStr; - this.setTitle(); - }; - }, - setInitialView(storedHash, { - rotation, - sidebarView, - scrollMode, - spreadMode - } = {}) { - const setRotation = angle => { - if ((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isValidRotation)(angle)) { - this.pdfViewer.pagesRotation = angle; - } - }; - const setViewerModes = (scroll, spread) => { - if ((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isValidScrollMode)(scroll)) { - this.pdfViewer.scrollMode = scroll; - } - if ((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isValidSpreadMode)(spread)) { - this.pdfViewer.spreadMode = spread; - } - }; - this.isInitialViewSet = true; - this.pdfSidebar?.setInitialView(sidebarView); - setViewerModes(scrollMode, spreadMode); - if (this.initialBookmark) { - setRotation(this.initialRotation); - delete this.initialRotation; - this.pdfLinkService.setHash(this.initialBookmark); - this.initialBookmark = null; - } else if (storedHash) { - setRotation(rotation); - this.pdfLinkService.setHash(storedHash); - } - this.toolbar?.setPageNumber(this.pdfViewer.currentPageNumber, this.pdfViewer.currentPageLabel); - this.secondaryToolbar?.setPageNumber(this.pdfViewer.currentPageNumber); - if (!this.pdfViewer.currentScaleValue) { - this.pdfViewer.currentScaleValue = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_SCALE_VALUE; - } - }, - _cleanup() { - if (!this.pdfDocument) { - return; - } - this.pdfViewer.cleanup(); - this.pdfThumbnailViewer?.cleanup(); - this.pdfDocument.cleanup(_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("fontExtraProperties")); - }, - forceRendering() { - this.pdfRenderingQueue.printing = !!this.printService; - this.pdfRenderingQueue.isThumbnailViewEnabled = this.pdfSidebar?.visibleView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS; - this.pdfRenderingQueue.renderHighestPriority(); - }, - beforePrint() { - this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => this.pdfDocument?.annotationStorage.print); - if (this.printService) { - return; - } - if (!this.supportsPrinting) { - this._otherError("pdfjs-printing-not-supported"); - return; - } - if (!this.pdfViewer.pageViewsReady) { - this.l10n.get("pdfjs-printing-not-ready").then(msg => { - window.alert(msg); - }); - return; - } - this.printService = web_print_service__WEBPACK_IMPORTED_MODULE_19__.PDFPrintServiceFactory.createPrintService({ - pdfDocument: this.pdfDocument, - pagesOverview: this.pdfViewer.getPagesOverview(), - printContainer: this.appConfig.printContainer, - printResolution: _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("printResolution"), - printAnnotationStoragePromise: this._printAnnotationStoragePromise - }); - this.forceRendering(); - this.setTitle(); - this.printService.layout(); - if (this._hasAnnotationEditors) { - this.externalServices.reportTelemetry({ - type: "editing", - data: { - type: "print", - stats: this.pdfDocument?.annotationStorage.editorStats - } - }); - } - }, - afterPrint() { - if (this._printAnnotationStoragePromise) { - this._printAnnotationStoragePromise.then(() => { - this.pdfScriptingManager.dispatchDidPrint(); - }); - this._printAnnotationStoragePromise = null; - } - if (this.printService) { - this.printService.destroy(); - this.printService = null; - this.pdfDocument?.annotationStorage.resetModified(); - } - this.forceRendering(); - this.setTitle(); - }, - rotatePages(delta) { - this.pdfViewer.pagesRotation += delta; - }, - requestPresentationMode() { - this.pdfPresentationMode?.request(); - }, - triggerPrinting() { - if (!this.supportsPrinting) { - return; - } - window.print(); - }, - bindEvents() { - if (this._eventBusAbortController) { - return; - } - this._eventBusAbortController = new AbortController(); - const { - eventBus, - _eventBusAbortController: { - signal - } - } = this; - eventBus._on("resize", webViewerResize, { - signal - }); - eventBus._on("hashchange", webViewerHashchange, { - signal - }); - eventBus._on("beforeprint", this.beforePrint.bind(this), { - signal - }); - eventBus._on("afterprint", this.afterPrint.bind(this), { - signal - }); - eventBus._on("pagerender", webViewerPageRender, { - signal - }); - eventBus._on("pagerendered", webViewerPageRendered, { - signal - }); - eventBus._on("updateviewarea", webViewerUpdateViewarea, { - signal - }); - eventBus._on("pagechanging", webViewerPageChanging, { - signal - }); - eventBus._on("scalechanging", webViewerScaleChanging, { - signal - }); - eventBus._on("rotationchanging", webViewerRotationChanging, { - signal - }); - eventBus._on("sidebarviewchanged", webViewerSidebarViewChanged, { - signal - }); - eventBus._on("pagemode", webViewerPageMode, { - signal - }); - eventBus._on("namedaction", webViewerNamedAction, { - signal - }); - eventBus._on("presentationmodechanged", webViewerPresentationModeChanged, { - signal - }); - eventBus._on("presentationmode", webViewerPresentationMode, { - signal - }); - eventBus._on("switchannotationeditormode", webViewerSwitchAnnotationEditorMode, { - signal - }); - eventBus._on("switchannotationeditorparams", webViewerSwitchAnnotationEditorParams, { - signal - }); - eventBus._on("print", webViewerPrint, { - signal - }); - eventBus._on("download", webViewerDownload, { - signal - }); - eventBus._on("firstpage", webViewerFirstPage, { - signal - }); - eventBus._on("lastpage", webViewerLastPage, { - signal - }); - eventBus._on("nextpage", webViewerNextPage, { - signal - }); - eventBus._on("previouspage", webViewerPreviousPage, { - signal - }); - eventBus._on("zoomin", webViewerZoomIn, { - signal - }); - eventBus._on("zoomout", webViewerZoomOut, { - signal - }); - eventBus._on("zoomreset", webViewerZoomReset, { - signal - }); - eventBus._on("pagenumberchanged", webViewerPageNumberChanged, { - signal - }); - eventBus._on("scalechanged", webViewerScaleChanged, { - signal - }); - eventBus._on("rotatecw", webViewerRotateCw, { - signal - }); - eventBus._on("rotateccw", webViewerRotateCcw, { - signal - }); - eventBus._on("optionalcontentconfig", webViewerOptionalContentConfig, { - signal - }); - eventBus._on("switchscrollmode", webViewerSwitchScrollMode, { - signal - }); - eventBus._on("scrollmodechanged", webViewerScrollModeChanged, { - signal - }); - eventBus._on("switchspreadmode", webViewerSwitchSpreadMode, { - signal - }); - eventBus._on("spreadmodechanged", webViewerSpreadModeChanged, { - signal - }); - eventBus._on("documentproperties", webViewerDocumentProperties, { - signal - }); - eventBus._on("findfromurlhash", webViewerFindFromUrlHash, { - signal - }); - eventBus._on("updatefindmatchescount", webViewerUpdateFindMatchesCount, { - signal - }); - eventBus._on("updatefindcontrolstate", webViewerUpdateFindControlState, { - signal - }); - if (_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("pdfBug")) { - eventBus._on("pagerendered", reportPageStatsPDFBug, { - signal - }); - eventBus._on("pagechanging", reportPageStatsPDFBug, { - signal - }); - } - eventBus._on("fileinputchange", webViewerFileInputChange, { - signal - }); - eventBus._on("openfile", webViewerOpenFile, { - signal - }); - }, - bindWindowEvents() { - if (this._windowAbortController) { - return; - } - this._windowAbortController = new AbortController(); - const { - eventBus, - appConfig: { - mainContainer - }, - _windowAbortController: { - signal - } - } = this; - function addWindowResolutionChange(evt = null) { - if (evt) { - webViewerResolutionChange(evt); - } - const mediaQueryList = window.matchMedia(`(resolution: ${window.devicePixelRatio || 1}dppx)`); - mediaQueryList.addEventListener("change", addWindowResolutionChange, { - once: true, - signal - }); - } - addWindowResolutionChange(); - window.addEventListener("visibilitychange", webViewerVisibilityChange, { - signal - }); - window.addEventListener("wheel", webViewerWheel, { - passive: false, - signal - }); - window.addEventListener("touchstart", webViewerTouchStart, { - passive: false, - signal - }); - window.addEventListener("touchmove", webViewerTouchMove, { - passive: false, - signal - }); - window.addEventListener("touchend", webViewerTouchEnd, { - passive: false, - signal - }); - window.addEventListener("click", webViewerClick, { - signal - }); - window.addEventListener("keydown", webViewerKeyDown, { - signal - }); - window.addEventListener("keyup", webViewerKeyUp, { - signal - }); - window.addEventListener("resize", () => { - eventBus.dispatch("resize", { - source: window - }); - }, { - signal - }); - window.addEventListener("hashchange", () => { - eventBus.dispatch("hashchange", { - source: window, - hash: document.location.hash.substring(1) - }); - }, { - signal - }); - window.addEventListener("beforeprint", () => { - eventBus.dispatch("beforeprint", { - source: window - }); - }, { - signal - }); - window.addEventListener("afterprint", () => { - eventBus.dispatch("afterprint", { - source: window - }); - }, { - signal - }); - window.addEventListener("updatefromsandbox", event => { - eventBus.dispatch("updatefromsandbox", { - source: window, - detail: event.detail - }); - }, { - signal - }); - if (!("onscrollend" in document.documentElement)) { - return; - } - ({ - scrollTop: this._lastScrollTop, - scrollLeft: this._lastScrollLeft - } = mainContainer); - const scrollend = () => { - ({ - scrollTop: this._lastScrollTop, - scrollLeft: this._lastScrollLeft - } = mainContainer); - this._isScrolling = false; - mainContainer.addEventListener("scroll", scroll, { - passive: true, - signal - }); - mainContainer.removeEventListener("scrollend", scrollend, { - signal - }); - mainContainer.removeEventListener("blur", scrollend, { - signal - }); - }; - const scroll = () => { - if (this._isCtrlKeyDown) { - return; - } - if (this._lastScrollTop === mainContainer.scrollTop && this._lastScrollLeft === mainContainer.scrollLeft) { - return; - } - mainContainer.removeEventListener("scroll", scroll, { - passive: true, - signal - }); - this._isScrolling = true; - mainContainer.addEventListener("scrollend", scrollend, { - signal - }); - mainContainer.addEventListener("blur", scrollend, { - signal - }); - }; - mainContainer.addEventListener("scroll", scroll, { - passive: true, - signal - }); - }, - unbindEvents() { - this._eventBusAbortController?.abort(); - this._eventBusAbortController = null; - }, - unbindWindowEvents() { - this._windowAbortController?.abort(); - this._windowAbortController = null; - }, - _accumulateTicks(ticks, prop) { - if (this[prop] > 0 && ticks < 0 || this[prop] < 0 && ticks > 0) { - this[prop] = 0; - } - this[prop] += ticks; - const wholeTicks = Math.trunc(this[prop]); - this[prop] -= wholeTicks; - return wholeTicks; - }, - _accumulateFactor(previousScale, factor, prop) { - if (factor === 1) { - return 1; - } - if (this[prop] > 1 && factor < 1 || this[prop] < 1 && factor > 1) { - this[prop] = 1; - } - const newFactor = Math.floor(previousScale * factor * this[prop] * 100) / (100 * previousScale); - this[prop] = factor / newFactor; - return newFactor; - }, - _centerAtPos(previousScale, x, y) { - const { - pdfViewer - } = this; - const scaleDiff = pdfViewer.currentScale / previousScale - 1; - if (scaleDiff !== 0) { - const [top, left] = pdfViewer.containerTopLeft; - pdfViewer.container.scrollLeft += (x - left) * scaleDiff; - pdfViewer.container.scrollTop += (y - top) * scaleDiff; - } - }, - _unblockDocumentLoadEvent() { - document.blockUnblockOnload?.(false); - this._unblockDocumentLoadEvent = () => {}; - }, - get scriptingReady() { - return this.pdfScriptingManager.ready; - } -}; -(0,web_external_services__WEBPACK_IMPORTED_MODULE_4__.initCom)(PDFViewerApplication); -{ - web_print_service__WEBPACK_IMPORTED_MODULE_19__.PDFPrintServiceFactory.initGlobals(PDFViewerApplication); -} -{ - const HOSTED_VIEWER_ORIGINS = ["null", "http://mozilla.github.io", "https://mozilla.github.io"]; - var validateFileURL = function (file) { - if (!file) { - return; - } - try { - const viewerOrigin = new URL(window.location.href).origin || "null"; - if (HOSTED_VIEWER_ORIGINS.includes(viewerOrigin)) { - return; - } - const fileOrigin = new URL(file, window.location.href).origin; - if (fileOrigin !== viewerOrigin) { - // throw new Error("file origin does not match viewer's"); - } - } catch (ex) { - PDFViewerApplication._documentError("pdfjs-loading-error", { - message: ex.message - }); - throw ex; - } - }; -} -async function loadFakeWorker() { - pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.GlobalWorkerOptions.workerSrc ||= _app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("workerSrc"); - await import( /*webpackIgnore: true*/pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.PDFWorker.workerSrc); -} -async function loadPDFBug(self) { - const { - PDFBug - } = await import( /*webpackIgnore: true*/_app_options_js__WEBPACK_IMPORTED_MODULE_2__.AppOptions.get("debuggerSrc")); - self._PDFBug = PDFBug; -} -function reportPageStatsPDFBug({ - pageNumber -}) { - if (!globalThis.Stats?.enabled) { - return; - } - const pageView = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1); - globalThis.Stats.add(pageNumber, pageView?.pdfPage?.stats); -} -function webViewerPageRender({ - pageNumber -}) { - if (pageNumber === PDFViewerApplication.page) { - PDFViewerApplication.toolbar?.updateLoadingIndicatorState(true); - } - - // console.log('test-loaded-page') -} -function webViewerPageRendered({ - pageNumber, - error -}) { - if (pageNumber === PDFViewerApplication.page) { - PDFViewerApplication.toolbar?.updateLoadingIndicatorState(false); - } - if (PDFViewerApplication.pdfSidebar?.visibleView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS) { - const pageView = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1); - const thumbnailView = PDFViewerApplication.pdfThumbnailViewer?.getThumbnail(pageNumber - 1); - if (pageView) { - thumbnailView?.setImage(pageView); - } - } - if (error) { - PDFViewerApplication._otherError("pdfjs-rendering-error", error); - } -} -function webViewerPageMode({ - mode -}) { - let view; - switch (mode) { - case "thumbs": - view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS; - break; - case "bookmarks": - case "outline": - view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.OUTLINE; - break; - case "attachments": - view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.ATTACHMENTS; - break; - case "layers": - view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.LAYERS; - break; - case "none": - view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.NONE; - break; - default: - console.error('Invalid "pagemode" hash parameter: ' + mode); - return; - } - PDFViewerApplication.pdfSidebar?.switchView(view, true); -} -function webViewerNamedAction(evt) { - switch (evt.action) { - case "GoToPage": - PDFViewerApplication.appConfig.toolbar?.pageNumber.select(); - break; - case "Find": - if (!PDFViewerApplication.supportsIntegratedFind) { - PDFViewerApplication.findBar?.toggle(); - } - break; - case "Print": - PDFViewerApplication.triggerPrinting(); - break; - case "SaveAs": - PDFViewerApplication.downloadOrSave(); - break; - } -} -function webViewerPresentationModeChanged(evt) { - PDFViewerApplication.pdfViewer.presentationModeState = evt.state; -} -function webViewerSidebarViewChanged({ - view -}) { - PDFViewerApplication.pdfRenderingQueue.isThumbnailViewEnabled = view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS; - if (PDFViewerApplication.isInitialViewSet) { - PDFViewerApplication.store?.set("sidebarView", view).catch(() => {}); - } -} -function webViewerUpdateViewarea({ - location -}) { - if (PDFViewerApplication.isInitialViewSet) { - PDFViewerApplication.store?.setMultiple({ - page: location.pageNumber, - zoom: location.scale, - scrollLeft: location.left, - scrollTop: location.top, - rotation: location.rotation - }).catch(() => {}); - } - if (PDFViewerApplication.appConfig.secondaryToolbar) { - const href = PDFViewerApplication.pdfLinkService.getAnchorUrl(location.pdfOpenParams); - PDFViewerApplication.appConfig.secondaryToolbar.viewBookmarkButton.href = href; - } -} -function webViewerScrollModeChanged(evt) { - if (PDFViewerApplication.isInitialViewSet && !PDFViewerApplication.pdfViewer.isInPresentationMode) { - PDFViewerApplication.store?.set("scrollMode", evt.mode).catch(() => {}); - } -} -function webViewerSpreadModeChanged(evt) { - if (PDFViewerApplication.isInitialViewSet && !PDFViewerApplication.pdfViewer.isInPresentationMode) { - PDFViewerApplication.store?.set("spreadMode", evt.mode).catch(() => {}); - } -} -function webViewerResize() { - const { - pdfDocument, - pdfViewer, - pdfRenderingQueue - } = PDFViewerApplication; - if (pdfRenderingQueue.printing && window.matchMedia("print").matches) { - return; - } - if (!pdfDocument) { - return; - } - const currentScaleValue = pdfViewer.currentScaleValue; - if (currentScaleValue === "auto" || currentScaleValue === "page-fit" || currentScaleValue === "page-width") { - pdfViewer.currentScaleValue = currentScaleValue; - } - pdfViewer.update(); -} -function webViewerHashchange(evt) { - const hash = evt.hash; - if (!hash) { - return; - } - if (!PDFViewerApplication.isInitialViewSet) { - PDFViewerApplication.initialBookmark = hash; - } else if (!PDFViewerApplication.pdfHistory?.popStateInProgress) { - PDFViewerApplication.pdfLinkService.setHash(hash); - } -} -{ - var webViewerFileInputChange = function (evt) { - if (PDFViewerApplication.pdfViewer?.isInPresentationMode) { - return; - } - const file = evt.fileInput.files[0]; - PDFViewerApplication.open({ - url: URL.createObjectURL(file), - originalUrl: file.name - }); - }; - var webViewerOpenFile = function (evt) { - PDFViewerApplication._openFileInput?.click(); - }; -} -function webViewerPresentationMode() { - PDFViewerApplication.requestPresentationMode(); -} -function webViewerSwitchAnnotationEditorMode(evt) { - PDFViewerApplication.pdfViewer.annotationEditorMode = evt; -} -function webViewerSwitchAnnotationEditorParams(evt) { - PDFViewerApplication.pdfViewer.annotationEditorParams = evt; -} -function webViewerPrint() { - PDFViewerApplication.triggerPrinting(); -} -function webViewerDownload() { - PDFViewerApplication.downloadOrSave(); -} -function webViewerFirstPage() { - PDFViewerApplication.page = 1; -} -function webViewerLastPage() { - PDFViewerApplication.page = PDFViewerApplication.pagesCount; -} -function webViewerNextPage() { - PDFViewerApplication.pdfViewer.nextPage(); -} -function webViewerPreviousPage() { - PDFViewerApplication.pdfViewer.previousPage(); -} -function webViewerZoomIn() { - PDFViewerApplication.zoomIn(); -} -function webViewerZoomOut() { - PDFViewerApplication.zoomOut(); -} -function webViewerZoomReset() { - PDFViewerApplication.zoomReset(); -} -function webViewerPageNumberChanged(evt) { - const pdfViewer = PDFViewerApplication.pdfViewer; - if (evt.value !== "") { - PDFViewerApplication.pdfLinkService.goToPage(evt.value); - } - if (evt.value !== pdfViewer.currentPageNumber.toString() && evt.value !== pdfViewer.currentPageLabel) { - PDFViewerApplication.toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel); - } -} -function webViewerScaleChanged(evt) { - PDFViewerApplication.pdfViewer.currentScaleValue = evt.value; -} -function webViewerRotateCw() { - PDFViewerApplication.rotatePages(90); -} -function webViewerRotateCcw() { - PDFViewerApplication.rotatePages(-90); -} -function webViewerOptionalContentConfig(evt) { - PDFViewerApplication.pdfViewer.optionalContentConfigPromise = evt.promise; -} -function webViewerSwitchScrollMode(evt) { - PDFViewerApplication.pdfViewer.scrollMode = evt.mode; -} -function webViewerSwitchSpreadMode(evt) { - PDFViewerApplication.pdfViewer.spreadMode = evt.mode; -} -function webViewerDocumentProperties() { - PDFViewerApplication.pdfDocumentProperties?.open(); -} -function webViewerFindFromUrlHash(evt) { - PDFViewerApplication.eventBus.dispatch("find", { - source: evt.source, - type: "", - query: evt.query, - caseSensitive: false, - entireWord: false, - highlightAll: true, - findPrevious: false, - matchDiacritics: true - }); -} -function webViewerUpdateFindMatchesCount({ - matchesCount -}) { - if (PDFViewerApplication.supportsIntegratedFind) { - PDFViewerApplication.externalServices.updateFindMatchesCount(matchesCount); - } else { - PDFViewerApplication.findBar?.updateResultsCount(matchesCount); - } -} -function webViewerUpdateFindControlState({ - state, - previous, - matchesCount, - rawQuery -}) { - if (PDFViewerApplication.supportsIntegratedFind) { - PDFViewerApplication.externalServices.updateFindControlState({ - result: state, - findPrevious: previous, - matchesCount, - rawQuery - }); - } else { - PDFViewerApplication.findBar?.updateUIState(state, previous, matchesCount); - } -} -function webViewerScaleChanging(evt) { - PDFViewerApplication.toolbar?.setPageScale(evt.presetValue, evt.scale); - PDFViewerApplication.pdfViewer.update(); -} -function webViewerRotationChanging(evt) { - if (PDFViewerApplication.pdfThumbnailViewer) { - PDFViewerApplication.pdfThumbnailViewer.pagesRotation = evt.pagesRotation; - } - PDFViewerApplication.forceRendering(); - PDFViewerApplication.pdfViewer.currentPageNumber = evt.pageNumber; -} -function webViewerPageChanging({ - pageNumber, - pageLabel -}) { - PDFViewerApplication.toolbar?.setPageNumber(pageNumber, pageLabel); - PDFViewerApplication.secondaryToolbar?.setPageNumber(pageNumber); - if (PDFViewerApplication.pdfSidebar?.visibleView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS) { - PDFViewerApplication.pdfThumbnailViewer?.scrollThumbnailIntoView(pageNumber); - } - const currentPage = PDFViewerApplication.pdfViewer.getPageView(pageNumber - 1); - PDFViewerApplication.toolbar?.updateLoadingIndicatorState(currentPage?.renderingState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.RUNNING); -} -function webViewerResolutionChange(evt) { - PDFViewerApplication.pdfViewer.refresh(); -} -function webViewerVisibilityChange(evt) { - if (document.visibilityState === "visible") { - setZoomDisabledTimeout(); - } -} -let zoomDisabledTimeout = null; -function setZoomDisabledTimeout() { - if (zoomDisabledTimeout) { - clearTimeout(zoomDisabledTimeout); - } - zoomDisabledTimeout = setTimeout(function () { - zoomDisabledTimeout = null; - }, WHEEL_ZOOM_DISABLED_TIMEOUT); -} -function webViewerWheel(evt) { - const { - pdfViewer, - supportsMouseWheelZoomCtrlKey, - supportsMouseWheelZoomMetaKey, - supportsPinchToZoom - } = PDFViewerApplication; - if (pdfViewer.isInPresentationMode) { - return; - } - const deltaMode = evt.deltaMode; - let scaleFactor = Math.exp(-evt.deltaY / 100); - const isBuiltInMac = false; - const isPinchToZoom = evt.ctrlKey && !PDFViewerApplication._isCtrlKeyDown && deltaMode === WheelEvent.DOM_DELTA_PIXEL && evt.deltaX === 0 && (Math.abs(scaleFactor - 1) < 0.05 || isBuiltInMac) && evt.deltaZ === 0; - if (isPinchToZoom || evt.ctrlKey && supportsMouseWheelZoomCtrlKey || evt.metaKey && supportsMouseWheelZoomMetaKey) { - evt.preventDefault(); - if (PDFViewerApplication._isScrolling || zoomDisabledTimeout || document.visibilityState === "hidden" || PDFViewerApplication.overlayManager.active) { - return; - } - const previousScale = pdfViewer.currentScale; - if (isPinchToZoom && supportsPinchToZoom) { - scaleFactor = PDFViewerApplication._accumulateFactor(previousScale, scaleFactor, "_wheelUnusedFactor"); - if (scaleFactor < 1) { - PDFViewerApplication.zoomOut(null, scaleFactor); - } else if (scaleFactor > 1) { - PDFViewerApplication.zoomIn(null, scaleFactor); - } else { - return; - } - } else { - const delta = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.normalizeWheelEventDirection)(evt); - let ticks = 0; - if (deltaMode === WheelEvent.DOM_DELTA_LINE || deltaMode === WheelEvent.DOM_DELTA_PAGE) { - if (Math.abs(delta) >= 1) { - ticks = Math.sign(delta); - } else { - ticks = PDFViewerApplication._accumulateTicks(delta, "_wheelUnusedTicks"); - } - } else { - const PIXELS_PER_LINE_SCALE = 30; - ticks = PDFViewerApplication._accumulateTicks(delta / PIXELS_PER_LINE_SCALE, "_wheelUnusedTicks"); - } - if (ticks < 0) { - PDFViewerApplication.zoomOut(-ticks); - } else if (ticks > 0) { - PDFViewerApplication.zoomIn(ticks); - } else { - return; - } - } - PDFViewerApplication._centerAtPos(previousScale, evt.clientX, evt.clientY); - } -} -function webViewerTouchStart(evt) { - if (PDFViewerApplication.pdfViewer.isInPresentationMode || evt.touches.length < 2) { - return; - } - evt.preventDefault(); - if (evt.touches.length !== 2 || PDFViewerApplication.overlayManager.active) { - PDFViewerApplication._touchInfo = null; - return; - } - let [touch0, touch1] = evt.touches; - if (touch0.identifier > touch1.identifier) { - [touch0, touch1] = [touch1, touch0]; - } - PDFViewerApplication._touchInfo = { - touch0X: touch0.pageX, - touch0Y: touch0.pageY, - touch1X: touch1.pageX, - touch1Y: touch1.pageY - }; -} -function webViewerTouchMove(evt) { - if (!PDFViewerApplication._touchInfo || evt.touches.length !== 2) { - return; - } - const { - pdfViewer, - _touchInfo, - supportsPinchToZoom - } = PDFViewerApplication; - let [touch0, touch1] = evt.touches; - if (touch0.identifier > touch1.identifier) { - [touch0, touch1] = [touch1, touch0]; - } - const { - pageX: page0X, - pageY: page0Y - } = touch0; - const { - pageX: page1X, - pageY: page1Y - } = touch1; - const { - touch0X: pTouch0X, - touch0Y: pTouch0Y, - touch1X: pTouch1X, - touch1Y: pTouch1Y - } = _touchInfo; - if (Math.abs(pTouch0X - page0X) <= 1 && Math.abs(pTouch0Y - page0Y) <= 1 && Math.abs(pTouch1X - page1X) <= 1 && Math.abs(pTouch1Y - page1Y) <= 1) { - return; - } - _touchInfo.touch0X = page0X; - _touchInfo.touch0Y = page0Y; - _touchInfo.touch1X = page1X; - _touchInfo.touch1Y = page1Y; - if (pTouch0X === page0X && pTouch0Y === page0Y) { - const v1X = pTouch1X - page0X; - const v1Y = pTouch1Y - page0Y; - const v2X = page1X - page0X; - const v2Y = page1Y - page0Y; - const det = v1X * v2Y - v1Y * v2X; - if (Math.abs(det) > 0.02 * Math.hypot(v1X, v1Y) * Math.hypot(v2X, v2Y)) { - return; - } - } else if (pTouch1X === page1X && pTouch1Y === page1Y) { - const v1X = pTouch0X - page1X; - const v1Y = pTouch0Y - page1Y; - const v2X = page0X - page1X; - const v2Y = page0Y - page1Y; - const det = v1X * v2Y - v1Y * v2X; - if (Math.abs(det) > 0.02 * Math.hypot(v1X, v1Y) * Math.hypot(v2X, v2Y)) { - return; - } - } else { - const diff0X = page0X - pTouch0X; - const diff1X = page1X - pTouch1X; - const diff0Y = page0Y - pTouch0Y; - const diff1Y = page1Y - pTouch1Y; - const dotProduct = diff0X * diff1X + diff0Y * diff1Y; - if (dotProduct >= 0) { - return; - } - } - evt.preventDefault(); - const distance = Math.hypot(page0X - page1X, page0Y - page1Y) || 1; - const pDistance = Math.hypot(pTouch0X - pTouch1X, pTouch0Y - pTouch1Y) || 1; - const previousScale = pdfViewer.currentScale; - if (supportsPinchToZoom) { - const newScaleFactor = PDFViewerApplication._accumulateFactor(previousScale, distance / pDistance, "_touchUnusedFactor"); - if (newScaleFactor < 1) { - PDFViewerApplication.zoomOut(null, newScaleFactor); - } else if (newScaleFactor > 1) { - PDFViewerApplication.zoomIn(null, newScaleFactor); - } else { - return; - } - } else { - const PIXELS_PER_LINE_SCALE = 30; - const ticks = PDFViewerApplication._accumulateTicks((distance - pDistance) / PIXELS_PER_LINE_SCALE, "_touchUnusedTicks"); - if (ticks < 0) { - PDFViewerApplication.zoomOut(-ticks); - } else if (ticks > 0) { - PDFViewerApplication.zoomIn(ticks); - } else { - return; - } - } - PDFViewerApplication._centerAtPos(previousScale, (page0X + page1X) / 2, (page0Y + page1Y) / 2); -} -function webViewerTouchEnd(evt) { - if (!PDFViewerApplication._touchInfo) { - return; - } - evt.preventDefault(); - PDFViewerApplication._touchInfo = null; - PDFViewerApplication._touchUnusedTicks = 0; - PDFViewerApplication._touchUnusedFactor = 1; -} -function webViewerClick(evt) { - if (!PDFViewerApplication.secondaryToolbar?.isOpen) { - return; - } - const appConfig = PDFViewerApplication.appConfig; - if (PDFViewerApplication.pdfViewer.containsElement(evt.target) || appConfig.toolbar?.container.contains(evt.target) && evt.target !== appConfig.secondaryToolbar?.toggleButton) { - PDFViewerApplication.secondaryToolbar.close(); - } -} -function webViewerKeyUp(evt) { - if (evt.key === "Control") { - PDFViewerApplication._isCtrlKeyDown = false; - } -} -function webViewerKeyDown(evt) { - PDFViewerApplication._isCtrlKeyDown = evt.key === "Control"; - if (PDFViewerApplication.overlayManager.active) { - return; - } - const { - eventBus, - pdfViewer - } = PDFViewerApplication; - const isViewerInPresentationMode = pdfViewer.isInPresentationMode; - let handled = false, - ensureViewerFocused = false; - const cmd = (evt.ctrlKey ? 1 : 0) | (evt.altKey ? 2 : 0) | (evt.shiftKey ? 4 : 0) | (evt.metaKey ? 8 : 0); - if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) { - switch (evt.keyCode) { - case 70: - if (!PDFViewerApplication.supportsIntegratedFind && !evt.shiftKey) { - PDFViewerApplication.findBar?.open(); - handled = true; - } - break; - case 71: - if (!PDFViewerApplication.supportsIntegratedFind) { - const { - state - } = PDFViewerApplication.findController; - if (state) { - const newState = { - source: window, - type: "again", - findPrevious: cmd === 5 || cmd === 12 - }; - eventBus.dispatch("find", { - ...state, - ...newState - }); - } - handled = true; - } - break; - case 61: - case 107: - case 187: - case 171: - PDFViewerApplication.zoomIn(); - handled = true; - break; - case 173: - case 109: - case 189: - PDFViewerApplication.zoomOut(); - handled = true; - break; - case 48: - case 96: - if (!isViewerInPresentationMode) { - setTimeout(function () { - PDFViewerApplication.zoomReset(); - }); - handled = false; - } - break; - case 38: - if (isViewerInPresentationMode || PDFViewerApplication.page > 1) { - PDFViewerApplication.page = 1; - handled = true; - ensureViewerFocused = true; - } - break; - case 40: - if (isViewerInPresentationMode || PDFViewerApplication.page < PDFViewerApplication.pagesCount) { - PDFViewerApplication.page = PDFViewerApplication.pagesCount; - handled = true; - ensureViewerFocused = true; - } - break; - } - } - if (cmd === 1 || cmd === 8) { - switch (evt.keyCode) { - case 83: - eventBus.dispatch("download", { - source: window - }); - handled = true; - break; - case 79: - { - eventBus.dispatch("openfile", { - source: window - }); - handled = true; - } - break; - } - } - if (cmd === 3 || cmd === 10) { - switch (evt.keyCode) { - case 80: - PDFViewerApplication.requestPresentationMode(); - handled = true; - PDFViewerApplication.externalServices.reportTelemetry({ - type: "buttons", - data: { - id: "presentationModeKeyboard" - } - }); - break; - case 71: - if (PDFViewerApplication.appConfig.toolbar) { - PDFViewerApplication.appConfig.toolbar.pageNumber.select(); - handled = true; - } - break; - } - } - if (handled) { - if (ensureViewerFocused && !isViewerInPresentationMode) { - pdfViewer.focus(); - } - evt.preventDefault(); - return; - } - const curElement = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.getActiveOrFocusedElement)(); - const curElementTagName = curElement?.tagName.toUpperCase(); - // [custom-input] - if (curElementTagName === "INPUT" || curElementTagName === "TEXTAREA" || curElementTagName === "SELECT" || curElementTagName === "BUTTON" && (evt.keyCode === 13 || evt.keyCode === 32) || curElement?.isContentEditable) { - if (evt.keyCode !== 27) { - return; - } - } - if (cmd === 0) { - let turnPage = 0, - turnOnlyIfPageFit = false; - switch (evt.keyCode) { - case 38: - if (PDFViewerApplication.supportsCaretBrowsingMode) { - PDFViewerApplication.moveCaret(true, false); - handled = true; - break; - } - case 33: - if (pdfViewer.isVerticalScrollbarEnabled) { - turnOnlyIfPageFit = true; - } - turnPage = -1; - break; - case 8: - if (!isViewerInPresentationMode) { - turnOnlyIfPageFit = true; - } - turnPage = -1; - break; - case 37: - if (PDFViewerApplication.supportsCaretBrowsingMode) { - return; - } - if (pdfViewer.isHorizontalScrollbarEnabled) { - turnOnlyIfPageFit = true; - } - case 75: - case 80: - turnPage = -1; - break; - case 27: - if (PDFViewerApplication.secondaryToolbar?.isOpen) { - PDFViewerApplication.secondaryToolbar.close(); - handled = true; - } - if (!PDFViewerApplication.supportsIntegratedFind && PDFViewerApplication.findBar?.opened) { - PDFViewerApplication.findBar.close(); - handled = true; - } - break; - case 40: - if (PDFViewerApplication.supportsCaretBrowsingMode) { - PDFViewerApplication.moveCaret(false, false); - handled = true; - break; - } - case 34: - if (pdfViewer.isVerticalScrollbarEnabled) { - turnOnlyIfPageFit = true; - } - turnPage = 1; - break; - case 13: - case 32: - if (!isViewerInPresentationMode) { - turnOnlyIfPageFit = true; - } - turnPage = 1; - break; - case 39: - if (PDFViewerApplication.supportsCaretBrowsingMode) { - return; - } - if (pdfViewer.isHorizontalScrollbarEnabled) { - turnOnlyIfPageFit = true; - } - case 74: - case 78: - turnPage = 1; - break; - case 36: - if (isViewerInPresentationMode || PDFViewerApplication.page > 1) { - PDFViewerApplication.page = 1; - handled = true; - ensureViewerFocused = true; - } - break; - case 35: - if (isViewerInPresentationMode || PDFViewerApplication.page < PDFViewerApplication.pagesCount) { - PDFViewerApplication.page = PDFViewerApplication.pagesCount; - handled = true; - ensureViewerFocused = true; - } - break; - case 83: - PDFViewerApplication.pdfCursorTools?.switchTool(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.SELECT); - break; - case 72: - PDFViewerApplication.pdfCursorTools?.switchTool(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.HAND); - break; - case 82: - PDFViewerApplication.rotatePages(90); - break; - case 115: - PDFViewerApplication.pdfSidebar?.toggle(); - break; - } - if (turnPage !== 0 && (!turnOnlyIfPageFit || pdfViewer.currentScaleValue === "page-fit")) { - if (turnPage > 0) { - pdfViewer.nextPage(); - } else { - pdfViewer.previousPage(); - } - handled = true; - } - } - if (cmd === 4) { - switch (evt.keyCode) { - case 13: - case 32: - if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== "page-fit") { - break; - } - pdfViewer.previousPage(); - handled = true; - break; - case 38: - PDFViewerApplication.moveCaret(true, true); - handled = true; - break; - case 40: - PDFViewerApplication.moveCaret(false, true); - handled = true; - break; - case 82: - PDFViewerApplication.rotatePages(-90); - break; - } - } - if (!handled && !isViewerInPresentationMode) { - if (evt.keyCode >= 33 && evt.keyCode <= 40 || evt.keyCode === 32 && curElementTagName !== "BUTTON") { - ensureViewerFocused = true; - } - } - if (ensureViewerFocused && !pdfViewer.containsElement(curElement)) { - pdfViewer.focus(); - } - if (handled) { - evt.preventDefault(); - } -} -function beforeUnload(evt) { - evt.preventDefault(); - evt.returnValue = ""; - return false; -} -function webViewerAnnotationEditorStatesChanged(data) { - PDFViewerApplication.externalServices.updateEditorStates(data); -} -function webViewerReportTelemetry({ - details -}) { - PDFViewerApplication.externalServices.reportTelemetry(details); -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 9840: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AppOptions: () => (/* binding */ AppOptions), -/* harmony export */ OptionKind: () => (/* binding */ OptionKind) -/* harmony export */ }); -{ - var compatibilityParams = Object.create(null); - const userAgent = navigator.userAgent || ""; - const platform = navigator.platform || ""; - const maxTouchPoints = navigator.maxTouchPoints || 1; - const isAndroid = /Android/.test(userAgent); - const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent) || platform === "MacIntel" && maxTouchPoints > 1; - (function checkCanvasSizeLimitation() { - if (isIOS || isAndroid) { - compatibilityParams.maxCanvasPixels = 5242880; - } - })(); -} -const OptionKind = { - BROWSER: 0x01, - VIEWER: 0x02, - API: 0x04, - WORKER: 0x08, - PREFERENCE: 0x80 -}; -const defaultOptions = { - canvasMaxAreaInBytes: { - value: -1, - kind: OptionKind.BROWSER + OptionKind.API - }, - isInAutomation: { - value: false, - kind: OptionKind.BROWSER - }, - supportsCaretBrowsingMode: { - value: false, - kind: OptionKind.BROWSER - }, - supportsDocumentFonts: { - value: true, - kind: OptionKind.BROWSER - }, - supportsIntegratedFind: { - value: false, - kind: OptionKind.BROWSER - }, - supportsMouseWheelZoomCtrlKey: { - value: true, - kind: OptionKind.BROWSER - }, - supportsMouseWheelZoomMetaKey: { - value: true, - kind: OptionKind.BROWSER - }, - supportsPinchToZoom: { - value: true, - kind: OptionKind.BROWSER - }, - annotationEditorMode: { - value: 0, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - annotationMode: { - value: 2, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - cursorToolOnLoad: { - value: 0, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - debuggerSrc: { - value: "./debugger.mjs", - kind: OptionKind.VIEWER - }, - defaultZoomDelay: { - value: 400, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - defaultZoomValue: { - value: "", - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - disableHistory: { - value: false, - kind: OptionKind.VIEWER - }, - disablePageLabels: { - value: false, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - enableHighlightEditor: { - value: false, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - enableHighlightFloatingButton: { - value: false, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - enableML: { - value: false, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - enablePermissions: { - value: false, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - enablePrintAutoRotate: { - value: true, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - enableScripting: { - value: true, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - enableStampEditor: { - value: true, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - externalLinkRel: { - value: "noopener noreferrer nofollow", - kind: OptionKind.VIEWER - }, - externalLinkTarget: { - value: 0, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - highlightEditorColors: { - value: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F", - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - historyUpdateUrl: { - value: false, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - ignoreDestinationZoom: { - value: false, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - imageResourcesPath: { - value: "./images/", - kind: OptionKind.VIEWER - }, - maxCanvasPixels: { - value: 2 ** 25, - kind: OptionKind.VIEWER - }, - forcePageColors: { - value: false, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - pageColorsBackground: { - value: "Canvas", - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - pageColorsForeground: { - value: "CanvasText", - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - pdfBugEnabled: { - value: false, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - printResolution: { - value: 150, - kind: OptionKind.VIEWER - }, - sidebarViewOnLoad: { - value: -1, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - scrollModeOnLoad: { - value: -1, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - spreadModeOnLoad: { - value: -1, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - textLayerMode: { - value: 1, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - viewOnLoad: { - value: 0, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }, - cMapPacked: { - value: true, - kind: OptionKind.API - }, - cMapUrl: { - value: "../web/cmaps/", - kind: OptionKind.API - }, - disableAutoFetch: { - value: false, - kind: OptionKind.API + OptionKind.PREFERENCE - }, - disableFontFace: { - value: false, - kind: OptionKind.API + OptionKind.PREFERENCE - }, - disableRange: { - value: false, - kind: OptionKind.API + OptionKind.PREFERENCE - }, - disableStream: { - value: false, - kind: OptionKind.API + OptionKind.PREFERENCE - }, - docBaseUrl: { - value: "", - kind: OptionKind.API - }, - enableXfa: { - value: true, - kind: OptionKind.API + OptionKind.PREFERENCE - }, - fontExtraProperties: { - value: false, - kind: OptionKind.API - }, - isEvalSupported: { - value: true, - kind: OptionKind.API - }, - isOffscreenCanvasSupported: { - value: true, - kind: OptionKind.API - }, - maxImageSize: { - value: -1, - kind: OptionKind.API - }, - pdfBug: { - value: false, - kind: OptionKind.API - }, - standardFontDataUrl: { - value: "../web/standard_fonts/", - kind: OptionKind.API - }, - verbosity: { - value: 1, - kind: OptionKind.API - }, - workerPort: { - value: null, - kind: OptionKind.WORKER - }, - workerSrc: { - value: "../build/pdf.worker.mjs", - kind: OptionKind.WORKER - } -}; -{ - defaultOptions.defaultUrl = { - value: "", - kind: OptionKind.VIEWER - }; - defaultOptions.sandboxBundleSrc = { - value: "../build/pdf.sandbox.mjs", - kind: OptionKind.VIEWER - }; - defaultOptions.viewerCssTheme = { - value: 0, - kind: OptionKind.VIEWER + OptionKind.PREFERENCE - }; -} -{ - defaultOptions.disablePreferences = { - value: false, - kind: OptionKind.VIEWER - }; - defaultOptions.locale = { - value: navigator.language || "en-US", - kind: OptionKind.VIEWER - }; -} -const userOptions = Object.create(null); -{ - for (const name in compatibilityParams) { - userOptions[name] = compatibilityParams[name]; - } -} -class AppOptions { - constructor() { - throw new Error("Cannot initialize AppOptions."); - } - static get(name) { - return userOptions[name] ?? defaultOptions[name]?.value ?? undefined; - } - static getAll(kind = null, defaultOnly = false) { - const options = Object.create(null); - for (const name in defaultOptions) { - const defaultOption = defaultOptions[name]; - if (kind && !(kind & defaultOption.kind)) { - continue; - } - options[name] = defaultOnly ? defaultOption.value : userOptions[name] ?? defaultOption.value; - } - return options; - } - static set(name, value) { - userOptions[name] = value; - } - static setAll(options, init = false) { - if (init) { - if (this.get("disablePreferences")) { - return; - } - for (const name in userOptions) { - if (compatibilityParams[name] !== undefined) { - continue; - } - console.warn("setAll: The Preferences may override manually set AppOptions; " + 'please use the "disablePreferences"-option in order to prevent that.'); - break; - } - } - for (const name in options) { - userOptions[name] = options[name]; - } - } - static remove(name) { - delete userOptions[name]; - const val = compatibilityParams[name]; - if (val !== undefined) { - userOptions[name] = val; - } - } -} - - -/***/ }), - -/***/ 2961: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ BaseTreeViewer: () => (/* binding */ BaseTreeViewer) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); - -const TREEITEM_OFFSET_TOP = -100; -const TREEITEM_SELECTED_CLASS = "selected"; -class BaseTreeViewer { - constructor(options) { - if (this.constructor === BaseTreeViewer) { - throw new Error("Cannot initialize BaseTreeViewer."); - } - this.container = options.container; - this.eventBus = options.eventBus; - this._l10n = options.l10n; - this.reset(); - } - reset() { - this._pdfDocument = null; - this._lastToggleIsShow = true; - this._currentTreeItem = null; - this.container.textContent = ""; - this.container.classList.remove("treeWithDeepNesting"); - } - _dispatchEvent(count) { - throw new Error("Not implemented: _dispatchEvent"); - } - _bindLink(element, params) { - throw new Error("Not implemented: _bindLink"); - } - _normalizeTextContent(str) { - return (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.removeNullCharacters)(str, true) || "\u2013"; - } - _addToggleButton(div, hidden = false) { - const toggler = document.createElement("div"); - toggler.className = "treeItemToggler"; - if (hidden) { - toggler.classList.add("treeItemsHidden"); - } - toggler.onclick = evt => { - evt.stopPropagation(); - toggler.classList.toggle("treeItemsHidden"); - if (evt.shiftKey) { - const shouldShowAll = !toggler.classList.contains("treeItemsHidden"); - this._toggleTreeItem(div, shouldShowAll); - } - }; - div.prepend(toggler); - } - _toggleTreeItem(root, show = false) { - this._l10n.pause(); - this._lastToggleIsShow = show; - for (const toggler of root.querySelectorAll(".treeItemToggler")) { - toggler.classList.toggle("treeItemsHidden", !show); - } - this._l10n.resume(); - } - _toggleAllTreeItems() { - this._toggleTreeItem(this.container, !this._lastToggleIsShow); - } - _finishRendering(fragment, count, hasAnyNesting = false) { - if (hasAnyNesting) { - this.container.classList.add("treeWithDeepNesting"); - this._lastToggleIsShow = !fragment.querySelector(".treeItemsHidden"); - } - this._l10n.pause(); - this.container.append(fragment); - this._l10n.resume(); - this._dispatchEvent(count); - } - render(params) { - throw new Error("Not implemented: render"); - } - _updateCurrentTreeItem(treeItem = null) { - if (this._currentTreeItem) { - this._currentTreeItem.classList.remove(TREEITEM_SELECTED_CLASS); - this._currentTreeItem = null; - } - if (treeItem) { - treeItem.classList.add(TREEITEM_SELECTED_CLASS); - this._currentTreeItem = treeItem; - } - } - _scrollToCurrentTreeItem(treeItem) { - if (!treeItem) { - return; - } - this._l10n.pause(); - let currentNode = treeItem.parentNode; - while (currentNode && currentNode !== this.container) { - if (currentNode.classList.contains("treeItem")) { - const toggler = currentNode.firstElementChild; - toggler?.classList.remove("treeItemsHidden"); - } - currentNode = currentNode.parentNode; - } - this._l10n.resume(); - this._updateCurrentTreeItem(treeItem); - this.container.scrollTo(treeItem.offsetLeft, treeItem.offsetTop + TREEITEM_OFFSET_TOP); - } -} - - -/***/ }), - -/***/ 3973: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ CaretBrowsingMode: () => (/* binding */ CaretBrowsingMode) -/* harmony export */ }); -const PRECISION = 1e-1; -class CaretBrowsingMode { - #mainContainer; - #toolBarHeight; - #viewerContainer; - constructor(mainContainer, viewerContainer, toolbarContainer) { - this.#mainContainer = mainContainer; - this.#viewerContainer = viewerContainer; - this.#toolBarHeight = toolbarContainer?.getBoundingClientRect().height ?? 0; - } - #isOnSameLine(rect1, rect2) { - const top1 = rect1.y; - const bot1 = rect1.bottom; - const mid1 = rect1.y + rect1.height / 2; - const top2 = rect2.y; - const bot2 = rect2.bottom; - const mid2 = rect2.y + rect2.height / 2; - return top1 <= mid2 && mid2 <= bot1 || top2 <= mid1 && mid1 <= bot2; - } - #isUnderOver(rect, x, y, isUp) { - const midY = rect.y + rect.height / 2; - return (isUp ? y >= midY : y <= midY) && rect.x - PRECISION <= x && x <= rect.right + PRECISION; - } - #isVisible(rect) { - return rect.top >= this.#toolBarHeight && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth); - } - #getCaretPosition(selection, isUp) { - const { - focusNode, - focusOffset - } = selection; - const range = document.createRange(); - range.setStart(focusNode, focusOffset); - range.setEnd(focusNode, focusOffset); - const rect = range.getBoundingClientRect(); - return [rect.x, isUp ? rect.top : rect.bottom]; - } - static #caretPositionFromPoint(x, y) { - if (!document.caretPositionFromPoint) { - const { - startContainer: offsetNode, - startOffset: offset - } = document.caretRangeFromPoint(x, y); - return { - offsetNode, - offset - }; - } - return document.caretPositionFromPoint(x, y); - } - #setCaretPositionHelper(selection, caretX, select, element, rect) { - rect ||= element.getBoundingClientRect(); - if (caretX <= rect.x + PRECISION) { - if (select) { - selection.extend(element.firstChild, 0); - } else { - selection.setPosition(element.firstChild, 0); - } - return; - } - if (rect.right - PRECISION <= caretX) { - const { - lastChild - } = element; - if (select) { - selection.extend(lastChild, lastChild.length); - } else { - selection.setPosition(lastChild, lastChild.length); - } - return; - } - const midY = rect.y + rect.height / 2; - let caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY); - let parentElement = caretPosition.offsetNode?.parentElement; - if (parentElement && parentElement !== element) { - const elementsAtPoint = document.elementsFromPoint(caretX, midY); - const savedVisibilities = []; - for (const el of elementsAtPoint) { - if (el === element) { - break; - } - const { - style - } = el; - savedVisibilities.push([el, style.visibility]); - style.visibility = "hidden"; - } - caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY); - parentElement = caretPosition.offsetNode?.parentElement; - for (const [el, visibility] of savedVisibilities) { - el.style.visibility = visibility; - } - } - if (parentElement !== element) { - if (select) { - selection.extend(element.firstChild, 0); - } else { - selection.setPosition(element.firstChild, 0); - } - return; - } - if (select) { - selection.extend(caretPosition.offsetNode, caretPosition.offset); - } else { - selection.setPosition(caretPosition.offsetNode, caretPosition.offset); - } - } - #setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX) { - if (this.#isVisible(newLineElementRect)) { - this.#setCaretPositionHelper(selection, caretX, select, newLineElement, newLineElementRect); - return; - } - this.#mainContainer.addEventListener("scrollend", this.#setCaretPositionHelper.bind(this, selection, caretX, select, newLineElement, null), { - once: true - }); - newLineElement.scrollIntoView(); - } - #getNodeOnNextPage(textLayer, isUp) { - while (true) { - const page = textLayer.closest(".page"); - const pageNumber = parseInt(page.getAttribute("data-page-number")); - const nextPage = isUp ? pageNumber - 1 : pageNumber + 1; - textLayer = this.#viewerContainer.querySelector(`.page[data-page-number="${nextPage}"] .textLayer`); - if (!textLayer) { - return null; - } - const walker = document.createTreeWalker(textLayer, NodeFilter.SHOW_TEXT); - const node = isUp ? walker.lastChild() : walker.firstChild(); - if (node) { - return node; - } - } - } - moveCaret(isUp, select) { - const selection = document.getSelection(); - if (selection.rangeCount === 0) { - return; - } - const { - focusNode - } = selection; - const focusElement = focusNode.nodeType !== Node.ELEMENT_NODE ? focusNode.parentElement : focusNode; - const root = focusElement.closest(".textLayer"); - if (!root) { - return; - } - const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT); - walker.currentNode = focusNode; - const focusRect = focusElement.getBoundingClientRect(); - let newLineElement = null; - const nodeIterator = (isUp ? walker.previousSibling : walker.nextSibling).bind(walker); - while (nodeIterator()) { - const element = walker.currentNode.parentElement; - if (!this.#isOnSameLine(focusRect, element.getBoundingClientRect())) { - newLineElement = element; - break; - } - } - if (!newLineElement) { - const node = this.#getNodeOnNextPage(root, isUp); - if (!node) { - return; - } - if (select) { - const lastNode = (isUp ? walker.firstChild() : walker.lastChild()) || focusNode; - selection.extend(lastNode, isUp ? 0 : lastNode.length); - const range = document.createRange(); - range.setStart(node, isUp ? node.length : 0); - range.setEnd(node, isUp ? node.length : 0); - selection.addRange(range); - return; - } - const [caretX] = this.#getCaretPosition(selection, isUp); - const { - parentElement - } = node; - this.#setCaretPosition(select, selection, parentElement, parentElement.getBoundingClientRect(), caretX); - return; - } - const [caretX, caretY] = this.#getCaretPosition(selection, isUp); - const newLineElementRect = newLineElement.getBoundingClientRect(); - if (this.#isUnderOver(newLineElementRect, caretX, caretY, isUp)) { - this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX); - return; - } - while (nodeIterator()) { - const element = walker.currentNode.parentElement; - const elementRect = element.getBoundingClientRect(); - if (!this.#isOnSameLine(newLineElementRect, elementRect)) { - break; - } - if (this.#isUnderOver(elementRect, caretX, caretY, isUp)) { - this.#setCaretPosition(select, selection, element, elementRect, caretX); - return; - } - } - this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX); - } -} - - -/***/ }), - -/***/ 1544: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ DownloadManager: () => (/* binding */ DownloadManager) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - -function download(blobUrl, filename) { - const a = document.createElement("a"); - if (!a.click) { - throw new Error('DownloadManager: "a.click()" is not supported.'); - } - a.href = blobUrl; - a.target = "_parent"; - if ("download" in a) { - a.download = filename; - } - (document.body || document.documentElement).append(a); - a.click(); - a.remove(); -} -class DownloadManager { - #openBlobUrls = new WeakMap(); - downloadUrl(url, filename, _options) { - if (!(0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.createValidAbsoluteUrl)(url, "http://example.com")) { - console.error(`downloadUrl - not a valid URL: ${url}`); - return; - } - download(url + "#pdfjs.action=download", filename); - } - downloadData(data, filename, contentType) { - const blobUrl = URL.createObjectURL(new Blob([data], { - type: contentType - })); - download(blobUrl, filename); - } - openOrDownloadData(data, filename, dest = null) { - const isPdfData = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.isPdfFile)(filename); - const contentType = isPdfData ? "application/pdf" : ""; - if (isPdfData) { - let blobUrl = this.#openBlobUrls.get(data); - if (!blobUrl) { - blobUrl = URL.createObjectURL(new Blob([data], { - type: contentType - })); - this.#openBlobUrls.set(data, blobUrl); - } - let viewerUrl; - viewerUrl = "?file=" + encodeURIComponent(blobUrl + "#" + filename); - if (dest) { - viewerUrl += `#${escape(dest)}`; - } - try { - window.open(viewerUrl); - return true; - } catch (ex) { - console.error(`openOrDownloadData: ${ex}`); - URL.revokeObjectURL(blobUrl); - this.#openBlobUrls.delete(data); - } - } - this.downloadData(data, filename, contentType); - return false; - } - download(blob, url, filename, _options) { - const blobUrl = URL.createObjectURL(blob); - download(blobUrl, filename); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 3088: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ DrawLayerBuilder: () => (/* binding */ DrawLayerBuilder) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - -class DrawLayerBuilder { - #drawLayer = null; - constructor(options) { - this.pageIndex = options.pageIndex; - } - async render(intent = "display") { - if (intent !== "display" || this.#drawLayer || this._cancelled) { - return; - } - this.#drawLayer = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.DrawLayer({ - pageIndex: this.pageIndex - }); - } - cancel() { - this._cancelled = true; - if (!this.#drawLayer) { - return; - } - this.#drawLayer.destroy(); - this.#drawLayer = null; - } - setParent(parent) { - this.#drawLayer?.setParent(parent); - } - getDrawLayer() { - return this.#drawLayer; - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 5656: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AutomationEventBus: () => (/* binding */ AutomationEventBus), -/* harmony export */ EventBus: () => (/* binding */ EventBus), -/* harmony export */ waitOnEventOrTimeout: () => (/* binding */ waitOnEventOrTimeout) -/* harmony export */ }); -/* unused harmony export WaitOnType */ -const WaitOnType = { - EVENT: "event", - TIMEOUT: "timeout" -}; -async function waitOnEventOrTimeout({ - target, - name, - delay = 0 -}) { - if (typeof target !== "object" || !(name && typeof name === "string") || !(Number.isInteger(delay) && delay >= 0)) { - throw new Error("waitOnEventOrTimeout - invalid parameters."); - } - const { - promise, - resolve - } = Promise.withResolvers(); - const ac = new AbortController(); - function handler(type) { - ac.abort(); - clearTimeout(timeout); - resolve(type); - } - const evtMethod = target instanceof EventBus ? "_on" : "addEventListener"; - target[evtMethod](name, handler.bind(null, WaitOnType.EVENT), { - signal: ac.signal - }); - const timeout = setTimeout(handler.bind(null, WaitOnType.TIMEOUT), delay); - return promise; -} -class EventBus { - #listeners = Object.create(null); - on(eventName, listener, options = null) { - this._on(eventName, listener, { - external: true, - once: options?.once, - signal: options?.signal - }); - } - off(eventName, listener, options = null) { - this._off(eventName, listener); - } - dispatch(eventName, data) { - const eventListeners = this.#listeners[eventName]; - if (!eventListeners || eventListeners.length === 0) { - return; - } - let externalListeners; - for (const { - listener, - external, - once - } of eventListeners.slice(0)) { - if (once) { - this._off(eventName, listener); - } - if (external) { - (externalListeners ||= []).push(listener); - continue; - } - listener(data); - } - if (externalListeners) { - for (const listener of externalListeners) { - listener(data); - } - externalListeners = null; - } - } - _on(eventName, listener, options = null) { - let rmAbort = null; - if (options?.signal instanceof AbortSignal) { - const { - signal - } = options; - if (signal.aborted) { - console.error("Cannot use an `aborted` signal."); - return; - } - const onAbort = () => this._off(eventName, listener); - rmAbort = () => signal.removeEventListener("abort", onAbort); - signal.addEventListener("abort", onAbort); - } - const eventListeners = this.#listeners[eventName] ||= []; - eventListeners.push({ - listener, - external: options?.external === true, - once: options?.once === true, - rmAbort - }); - } - _off(eventName, listener, options = null) { - const eventListeners = this.#listeners[eventName]; - if (!eventListeners) { - return; - } - for (let i = 0, ii = eventListeners.length; i < ii; i++) { - const evt = eventListeners[i]; - if (evt.listener === listener) { - evt.rmAbort?.(); - eventListeners.splice(i, 1); - return; - } - } - } -} -class AutomationEventBus extends EventBus { - dispatch(eventName, data) { - throw new Error("Not implemented: AutomationEventBus.dispatch"); - } -} - - -/***/ }), - -/***/ 4290: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ BaseExternalServices: () => (/* binding */ BaseExternalServices) -/* harmony export */ }); -class BaseExternalServices { - constructor() { - if (this.constructor === BaseExternalServices) { - throw new Error("Cannot initialize BaseExternalServices."); - } - } - updateFindControlState(data) {} - updateFindMatchesCount(data) {} - initPassiveLoading() {} - reportTelemetry(data) {} - async createL10n() { - throw new Error("Not implemented: createL10n"); - } - createScripting() { - throw new Error("Not implemented: createScripting"); - } - updateEditorStates(data) { - throw new Error("Not implemented: updateEditorStates"); - } - async getNimbusExperimentData() {} -} - - -/***/ }), - -/***/ 289: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ GenericScripting: () => (/* binding */ GenericScripting) -/* harmony export */ }); -/* unused harmony export docProperties */ -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - -async function docProperties(pdfDocument) { - const url = "", - baseUrl = url.split("#", 1)[0]; - let { - info, - metadata, - contentDispositionFilename, - contentLength - } = await pdfDocument.getMetadata(); - if (!contentLength) { - const { - length - } = await pdfDocument.getDownloadInfo(); - contentLength = length; - } - return { - ...info, - baseURL: baseUrl, - filesize: contentLength, - filename: contentDispositionFilename || getPdfFilenameFromUrl(url), - metadata: metadata?.getRaw(), - authors: metadata?.get("dc:creator"), - numPages: pdfDocument.numPages, - URL: url - }; -} -class GenericScripting { - constructor(sandboxBundleSrc) { - this._ready = new Promise((resolve, reject) => { - const sandbox = import( /*webpackIgnore: true*/sandboxBundleSrc); - sandbox.then(pdfjsSandbox => { - resolve(pdfjsSandbox.QuickJSSandbox()); - }).catch(reject); - }); - } - async createSandbox(data) { - const sandbox = await this._ready; - sandbox.create(data); - } - async dispatchEventInSandbox(event) { - const sandbox = await this._ready; - setTimeout(() => sandbox.dispatchEvent(event), 0); - } - async destroySandbox() { - const sandbox = await this._ready; - sandbox.nukeSandbox(); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 6750: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ ExternalServices: () => (/* binding */ ExternalServices), -/* harmony export */ MLManager: () => (/* binding */ MLManager), -/* harmony export */ Preferences: () => (/* binding */ Preferences), -/* harmony export */ initCom: () => (/* binding */ initCom) -/* harmony export */ }); -/* harmony import */ var _app_options_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9840); -/* harmony import */ var _external_services_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4290); -/* harmony import */ var _preferences_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8224); -/* harmony import */ var _genericl10n_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(410); -/* harmony import */ var _generic_scripting_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(289); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_genericl10n_js__WEBPACK_IMPORTED_MODULE_2__, _generic_scripting_js__WEBPACK_IMPORTED_MODULE_3__]); -([_genericl10n_js__WEBPACK_IMPORTED_MODULE_2__, _generic_scripting_js__WEBPACK_IMPORTED_MODULE_3__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__); - - - - - -function initCom(app) {} -class Preferences extends _preferences_js__WEBPACK_IMPORTED_MODULE_1__.BasePreferences { - async _writeToStorage(prefObj) { - localStorage.setItem("pdfjs.preferences", JSON.stringify(prefObj)); - } - async _readFromStorage(prefObj) { - return { - prefs: JSON.parse(localStorage.getItem("pdfjs.preferences")) - }; - } -} -class ExternalServices extends _external_services_js__WEBPACK_IMPORTED_MODULE_4__.BaseExternalServices { - async createL10n() { - return new _genericl10n_js__WEBPACK_IMPORTED_MODULE_2__.GenericL10n(_app_options_js__WEBPACK_IMPORTED_MODULE_0__.AppOptions.get("locale")); - } - createScripting() { - return new _generic_scripting_js__WEBPACK_IMPORTED_MODULE_3__.GenericScripting(_app_options_js__WEBPACK_IMPORTED_MODULE_0__.AppOptions.get("sandboxBundleSrc")); - } -} -class MLManager { - async guess() { - return null; - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 410: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ GenericL10n: () => (/* binding */ GenericL10n) -/* harmony export */ }); -/* harmony import */ var fluent_bundle__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(588); -/* harmony import */ var fluent_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5273); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2603); -/* harmony import */ var _l10n_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4693); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_2__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_2__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - - - -function createBundle(lang, text) { - const resource = new fluent_bundle__WEBPACK_IMPORTED_MODULE_0__.FluentResource(text); - const bundle = new fluent_bundle__WEBPACK_IMPORTED_MODULE_0__.FluentBundle(lang); - const errors = bundle.addResource(resource); - if (errors.length) { - console.error("L10n errors", errors); - } - return bundle; -} -class GenericL10n extends _l10n_js__WEBPACK_IMPORTED_MODULE_3__.L10n { - constructor(lang) { - super({ - lang - }); - const generateBundles = !lang ? GenericL10n.#generateBundlesFallback.bind(GenericL10n, this.getLanguage()) : GenericL10n.#generateBundles.bind(GenericL10n, "en-us", this.getLanguage()); - this._setL10n(new fluent_dom__WEBPACK_IMPORTED_MODULE_1__.DOMLocalization([], generateBundles)); - } - static async *#generateBundles(defaultLang, baseLang) { - const { - baseURL, - paths - } = await this.#getPaths(); - const langs = [baseLang]; - if (defaultLang !== baseLang) { - const shortLang = baseLang.split("-", 1)[0]; - if (shortLang !== baseLang) { - langs.push(shortLang); - } - langs.push(defaultLang); - } - for (const lang of langs) { - const bundle = await this.#createBundle(lang, baseURL, paths); - if (bundle) { - yield bundle; - } - if (lang === "en-us") { - yield this.#createBundleFallback(lang); - } - } - } - static async #createBundle(lang, baseURL, paths) { - const path = paths[lang]; - if (!path) { - return null; - } - const url = new URL(path, baseURL); - const text = await (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_2__.fetchData)(url, "text"); - return createBundle(lang, text); - } - static async #getPaths() { - try { - const { - href - } = document.querySelector(`link[type="application/l10n"]`); - const paths = await (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_2__.fetchData)(href, "json"); - return { - baseURL: href.replace(/[^/]*$/, "") || "./", - paths - }; - } catch {} - return { - baseURL: "./", - paths: Object.create(null) - }; - } - static async *#generateBundlesFallback(lang) { - yield this.#createBundleFallback(lang); - } - static async #createBundleFallback(lang) { - const text = "pdfjs-previous-button =\n .title = Previous Page\npdfjs-previous-button-label = Previous\npdfjs-next-button =\n .title = Next Page\npdfjs-next-button-label = Next\npdfjs-page-input =\n .title = Page\npdfjs-of-pages = / { $pagesCount }\npdfjs-page-of-pages = ({ $pageNumber } of { $pagesCount })\npdfjs-zoom-out-button =\n .title = Zoom Out\npdfjs-zoom-out-button-label = Zoom Out\npdfjs-zoom-in-button =\n .title = Zoom In\npdfjs-zoom-in-button-label = Zoom In\npdfjs-zoom-select =\n .title = Zoom\npdfjs-presentation-mode-button =\n .title = Switch to Presentation Mode\npdfjs-presentation-mode-button-label = Presentation Mode\npdfjs-open-file-button =\n .title = Open File\npdfjs-open-file-button-label = Open\npdfjs-print-button =\n .title = Print\npdfjs-print-button-label = Print\npdfjs-save-button =\n .title = Save\npdfjs-save-button-label = Save\npdfjs-download-button =\n .title = Download\npdfjs-download-button-label = Download\npdfjs-bookmark-button =\n .title = Current Page (View URL from Current Page)\npdfjs-bookmark-button-label = Current Page\npdfjs-tools-button =\n .title = Tools\npdfjs-tools-button-label = Tools\npdfjs-first-page-button =\n .title = Go to First Page\npdfjs-first-page-button-label = Go to First Page\npdfjs-last-page-button =\n .title = Go to Last Page\npdfjs-last-page-button-label = Go to Last Page\npdfjs-page-rotate-cw-button =\n .title = Rotate Clockwise\npdfjs-page-rotate-cw-button-label = Rotate Clockwise\npdfjs-page-rotate-ccw-button =\n .title = Rotate Counterclockwise\npdfjs-page-rotate-ccw-button-label = Rotate Counterclockwise\npdfjs-cursor-text-select-tool-button =\n .title = Enable Text Selection Tool\npdfjs-cursor-text-select-tool-button-label = Text Selection Tool\npdfjs-cursor-hand-tool-button =\n .title = Enable Hand Tool\npdfjs-cursor-hand-tool-button-label = Hand Tool\npdfjs-scroll-page-button =\n .title = Use Page Scrolling\npdfjs-scroll-page-button-label = Page Scrolling\npdfjs-scroll-vertical-button =\n .title = Use Vertical Scrolling\npdfjs-scroll-vertical-button-label = Vertical Scrolling\npdfjs-scroll-horizontal-button =\n .title = Use Horizontal Scrolling\npdfjs-scroll-horizontal-button-label = Horizontal Scrolling\npdfjs-scroll-wrapped-button =\n .title = Use Wrapped Scrolling\npdfjs-scroll-wrapped-button-label = Wrapped Scrolling\npdfjs-spread-none-button =\n .title = Do not join page spreads\npdfjs-spread-none-button-label = No Spreads\npdfjs-spread-odd-button =\n .title = Join page spreads starting with odd-numbered pages\npdfjs-spread-odd-button-label = Odd Spreads\npdfjs-spread-even-button =\n .title = Join page spreads starting with even-numbered pages\npdfjs-spread-even-button-label = Even Spreads\npdfjs-document-properties-button =\n .title = Document Properties\u2026\npdfjs-document-properties-button-label = Document Properties\u2026\npdfjs-document-properties-file-name = File name:\npdfjs-document-properties-file-size = File size:\npdfjs-document-properties-kb = { $size_kb } KB ({ $size_b } bytes)\npdfjs-document-properties-mb = { $size_mb } MB ({ $size_b } bytes)\npdfjs-document-properties-title = Title:\npdfjs-document-properties-author = Author:\npdfjs-document-properties-subject = Subject:\npdfjs-document-properties-keywords = Keywords:\npdfjs-document-properties-creation-date = Creation Date:\npdfjs-document-properties-modification-date = Modification Date:\npdfjs-document-properties-date-string = { $date }, { $time }\npdfjs-document-properties-creator = Creator:\npdfjs-document-properties-producer = PDF Producer:\npdfjs-document-properties-version = PDF Version:\npdfjs-document-properties-page-count = Page Count:\npdfjs-document-properties-page-size = Page Size:\npdfjs-document-properties-page-size-unit-inches = in\npdfjs-document-properties-page-size-unit-millimeters = mm\npdfjs-document-properties-page-size-orientation-portrait = portrait\npdfjs-document-properties-page-size-orientation-landscape = landscape\npdfjs-document-properties-page-size-name-a-three = A3\npdfjs-document-properties-page-size-name-a-four = A4\npdfjs-document-properties-page-size-name-letter = Letter\npdfjs-document-properties-page-size-name-legal = Legal\npdfjs-document-properties-page-size-dimension-string = { $width } \xD7 { $height } { $unit } ({ $orientation })\npdfjs-document-properties-page-size-dimension-name-string = { $width } \xD7 { $height } { $unit } ({ $name }, { $orientation })\npdfjs-document-properties-linearized = Fast Web View:\npdfjs-document-properties-linearized-yes = Yes\npdfjs-document-properties-linearized-no = No\npdfjs-document-properties-close-button = Close\npdfjs-print-progress-message = Preparing document for printing\u2026\npdfjs-print-progress-percent = { $progress }%\npdfjs-print-progress-close-button = Cancel\npdfjs-printing-not-supported = Warning: Printing is not fully supported by this browser.\npdfjs-printing-not-ready = Warning: The PDF is not fully loaded for printing.\npdfjs-toggle-sidebar-button =\n .title = Toggle Sidebar\npdfjs-toggle-sidebar-notification-button =\n .title = Toggle Sidebar (document contains outline/attachments/layers)\npdfjs-toggle-sidebar-button-label = Toggle Sidebar\npdfjs-document-outline-button =\n .title = Show Document Outline (double-click to expand/collapse all items)\npdfjs-document-outline-button-label = Document Outline\npdfjs-attachments-button =\n .title = Show Attachments\npdfjs-attachments-button-label = Attachments\npdfjs-layers-button =\n .title = Show Layers (double-click to reset all layers to the default state)\npdfjs-layers-button-label = Layers\npdfjs-thumbs-button =\n .title = Show Thumbnails\npdfjs-thumbs-button-label = Thumbnails\npdfjs-current-outline-item-button =\n .title = Find Current Outline Item\npdfjs-current-outline-item-button-label = Current Outline Item\npdfjs-findbar-button =\n .title = Find in Document\npdfjs-findbar-button-label = Find\npdfjs-additional-layers = Additional Layers\npdfjs-thumb-page-title =\n .title = Page { $page }\npdfjs-thumb-page-canvas =\n .aria-label = Thumbnail of Page { $page }\npdfjs-find-input =\n .title = Find\n .placeholder = Find in document\u2026\npdfjs-find-previous-button =\n .title = Find the previous occurrence of the phrase\npdfjs-find-previous-button-label = Previous\npdfjs-find-next-button =\n .title = Find the next occurrence of the phrase\npdfjs-find-next-button-label = Next\npdfjs-find-highlight-checkbox = Highlight All\npdfjs-find-match-case-checkbox-label = Match Case\npdfjs-find-match-diacritics-checkbox-label = Match Diacritics\npdfjs-find-entire-word-checkbox-label = Whole Words\npdfjs-find-reached-top = Reached top of document, continued from bottom\npdfjs-find-reached-bottom = Reached end of document, continued from top\npdfjs-find-match-count =\n { $total ->\n [one] { $current } of { $total } match\n *[other] { $current } of { $total } matches\n }\npdfjs-find-match-count-limit =\n { $limit ->\n [one] More than { $limit } match\n *[other] More than { $limit } matches\n }\npdfjs-find-not-found = Phrase not found\npdfjs-page-scale-width = Page Width\npdfjs-page-scale-fit = Page Fit\npdfjs-page-scale-auto = Automatic Zoom\npdfjs-page-scale-actual = Actual Size\npdfjs-page-scale-percent = { $scale }%\npdfjs-page-landmark =\n .aria-label = Page { $page }\npdfjs-loading-error = An error occurred while loading the PDF.\npdfjs-invalid-file-error = Invalid or corrupted PDF file.\npdfjs-missing-file-error = Missing PDF file.\npdfjs-unexpected-response-error = Unexpected server response.\npdfjs-rendering-error = An error occurred while rendering the page.\npdfjs-annotation-date-string = { $date }, { $time }\npdfjs-text-annotation-type =\n .alt = [{ $type } Annotation]\npdfjs-password-label = Enter the password to open this PDF file.\npdfjs-password-invalid = Invalid password. Please try again.\npdfjs-password-ok-button = OK\npdfjs-password-cancel-button = Cancel\npdfjs-web-fonts-disabled = Web fonts are disabled: unable to use embedded PDF fonts.\npdfjs-editor-free-text-button =\n .title = Text\npdfjs-editor-free-text-button-label = Text\npdfjs-editor-ink-button =\n .title = Draw\npdfjs-editor-ink-button-label = Draw\npdfjs-editor-stamp-button =\n .title = Add or edit images\npdfjs-editor-stamp-button-label = Add or edit images\npdfjs-editor-highlight-button =\n .title = Highlight\npdfjs-editor-highlight-button-label = Highlight\npdfjs-highlight-floating-button1 =\n .title = Highlight\n .aria-label = Highlight\npdfjs-highlight-floating-button-label = Highlight\npdfjs-editor-remove-ink-button =\n .title = Remove drawing\npdfjs-editor-remove-freetext-button =\n .title = Remove text\npdfjs-editor-remove-stamp-button =\n .title = Remove image\npdfjs-editor-remove-highlight-button =\n .title = Remove highlight\npdfjs-editor-free-text-color-input = Color\npdfjs-editor-free-text-size-input = Size\npdfjs-editor-ink-color-input = Color\npdfjs-editor-ink-thickness-input = Thickness\npdfjs-editor-ink-opacity-input = Opacity\npdfjs-editor-stamp-add-image-button =\n .title = Add image\npdfjs-editor-stamp-add-image-button-label = Add image\npdfjs-editor-free-highlight-thickness-input = Thickness\npdfjs-editor-free-highlight-thickness-title =\n .title = Change thickness when highlighting items other than text\npdfjs-free-text =\n .aria-label = Text Editor\npdfjs-free-text-default-content = Start typing\u2026\npdfjs-ink =\n .aria-label = Draw Editor\npdfjs-ink-canvas =\n .aria-label = User-created image\npdfjs-editor-alt-text-button-label = Alt text\npdfjs-editor-alt-text-edit-button-label = Edit alt text\npdfjs-editor-alt-text-dialog-label = Choose an option\npdfjs-editor-alt-text-dialog-description = Alt text (alternative text) helps when people can\u2019t see the image or when it doesn\u2019t load.\npdfjs-editor-alt-text-add-description-label = Add a description\npdfjs-editor-alt-text-add-description-description = Aim for 1-2 sentences that describe the subject, setting, or actions.\npdfjs-editor-alt-text-mark-decorative-label = Mark as decorative\npdfjs-editor-alt-text-mark-decorative-description = This is used for ornamental images, like borders or watermarks.\npdfjs-editor-alt-text-cancel-button = Cancel\npdfjs-editor-alt-text-save-button = Save\npdfjs-editor-alt-text-decorative-tooltip = Marked as decorative\npdfjs-editor-alt-text-textarea =\n .placeholder = For example, \u201CA young man sits down at a table to eat a meal\u201D\npdfjs-editor-resizer-label-top-left = Top left corner \u2014 resize\npdfjs-editor-resizer-label-top-middle = Top middle \u2014 resize\npdfjs-editor-resizer-label-top-right = Top right corner \u2014 resize\npdfjs-editor-resizer-label-middle-right = Middle right \u2014 resize\npdfjs-editor-resizer-label-bottom-right = Bottom right corner \u2014 resize\npdfjs-editor-resizer-label-bottom-middle = Bottom middle \u2014 resize\npdfjs-editor-resizer-label-bottom-left = Bottom left corner \u2014 resize\npdfjs-editor-resizer-label-middle-left = Middle left \u2014 resize\npdfjs-editor-highlight-colorpicker-label = Highlight color\npdfjs-editor-colorpicker-button =\n .title = Change color\npdfjs-editor-colorpicker-dropdown =\n .aria-label = Color choices\npdfjs-editor-colorpicker-yellow =\n .title = Yellow\npdfjs-editor-colorpicker-green =\n .title = Green\npdfjs-editor-colorpicker-blue =\n .title = Blue\npdfjs-editor-colorpicker-pink =\n .title = Pink\npdfjs-editor-colorpicker-red =\n .title = Red\npdfjs-editor-highlight-show-all-button-label = Show all\npdfjs-editor-highlight-show-all-button =\n .title = Show all"; - return createBundle(lang, text); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 2640: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ GrabToPan: () => (/* binding */ GrabToPan) -/* harmony export */ }); -const CSS_CLASS_GRAB = "grab-to-pan-grab"; -class GrabToPan { - constructor({ - element - }) { - this.element = element; - this.document = element.ownerDocument; - this.activate = this.activate.bind(this); - this.deactivate = this.deactivate.bind(this); - this.toggle = this.toggle.bind(this); - this._onMouseDown = this.#onMouseDown.bind(this); - this._onMouseMove = this.#onMouseMove.bind(this); - this._endPan = this.#endPan.bind(this); - const overlay = this.overlay = document.createElement("div"); - overlay.className = "grab-to-pan-grabbing"; - } - activate() { - if (!this.active) { - this.active = true; - this.element.addEventListener("mousedown", this._onMouseDown, true); - this.element.classList.add(CSS_CLASS_GRAB); - } - } - deactivate() { - if (this.active) { - this.active = false; - this.element.removeEventListener("mousedown", this._onMouseDown, true); - this._endPan(); - this.element.classList.remove(CSS_CLASS_GRAB); - } - } - toggle() { - if (this.active) { - this.deactivate(); - } else { - this.activate(); - } - } - ignoreTarget(node) { - return node.matches("a[href], a[href] *, input, textarea, button, button *, select, option"); - } - #onMouseDown(event) { - if (event.button !== 0 || this.ignoreTarget(event.target)) { - return; - } - if (event.originalTarget) { - try { - event.originalTarget.tagName; - } catch { - return; - } - } - this.scrollLeftStart = this.element.scrollLeft; - this.scrollTopStart = this.element.scrollTop; - this.clientXStart = event.clientX; - this.clientYStart = event.clientY; - this.document.addEventListener("mousemove", this._onMouseMove, true); - this.document.addEventListener("mouseup", this._endPan, true); - this.element.addEventListener("scroll", this._endPan, true); - event.preventDefault(); - event.stopPropagation(); - const focusedElement = document.activeElement; - if (focusedElement && !focusedElement.contains(event.target)) { - focusedElement.blur(); - } - } - #onMouseMove(event) { - this.element.removeEventListener("scroll", this._endPan, true); - if (!(event.buttons & 1)) { - this._endPan(); - return; - } - const xDiff = event.clientX - this.clientXStart; - const yDiff = event.clientY - this.clientYStart; - this.element.scrollTo({ - top: this.scrollTopStart - yDiff, - left: this.scrollLeftStart - xDiff, - behavior: "instant" - }); - if (!this.overlay.parentNode) { - document.body.append(this.overlay); - } - } - #endPan() { - this.element.removeEventListener("scroll", this._endPan, true); - this.document.removeEventListener("mousemove", this._onMouseMove, true); - this.document.removeEventListener("mouseup", this._endPan, true); - this.overlay.remove(); - } -} - - -/***/ }), - -/***/ 4693: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ L10n: () => (/* binding */ L10n) -/* harmony export */ }); -/* unused harmony export GenericL10n */ -class L10n { - #dir; - #lang; - #l10n; - constructor({ - lang, - isRTL - }, l10n = null) { - this.#lang = L10n.#fixupLangCode(lang); - this.#l10n = l10n; - this.#dir = isRTL ?? L10n.#isRTL(this.#lang) ? "rtl" : "ltr"; - } - _setL10n(l10n) { - this.#l10n = l10n; - } - getLanguage() { - return this.#lang; - } - getDirection() { - return this.#dir; - } - async get(ids, args = null, fallback) { - if (Array.isArray(ids)) { - ids = ids.map(id => ({ - id - })); - const messages = await this.#l10n.formatMessages(ids); - return messages.map(message => message.value); - } - const messages = await this.#l10n.formatMessages([{ - id: ids, - args - }]); - return messages?.[0].value || fallback; - } - async translate(element) { - try { - this.#l10n.connectRoot(element); - await this.#l10n.translateRoots(); - } catch {} - } - pause() { - this.#l10n.pauseObserving(); - } - resume() { - this.#l10n.resumeObserving(); - } - static #fixupLangCode(langCode) { - langCode = langCode?.toLowerCase() || "en-us"; - const PARTIAL_LANG_CODES = { - en: "en-us", - es: "es-es", - fy: "fy-nl", - ga: "ga-ie", - gu: "gu-in", - hi: "hi-in", - hy: "hy-am", - nb: "nb-no", - ne: "ne-np", - nn: "nn-no", - pa: "pa-in", - pt: "pt-pt", - sv: "sv-se", - zh: "zh-cn" - }; - return PARTIAL_LANG_CODES[langCode] || langCode; - } - static #isRTL(lang) { - const shortCode = lang.split("-", 1)[0]; - return ["ar", "he", "fa", "ps", "ur"].includes(shortCode); - } -} -const GenericL10n = null; - - -/***/ }), - -/***/ 6174: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ OverlayManager: () => (/* binding */ OverlayManager) -/* harmony export */ }); -class OverlayManager { - #overlays = new WeakMap(); - #active = null; - get active() { - return this.#active; - } - async register(dialog, canForceClose = false) { - if (typeof dialog !== "object") { - throw new Error("Not enough parameters."); - } else if (this.#overlays.has(dialog)) { - throw new Error("The overlay is already registered."); - } - this.#overlays.set(dialog, { - canForceClose - }); - dialog.addEventListener("cancel", evt => { - this.#active = null; - }); - } - async open(dialog) { - if (!this.#overlays.has(dialog)) { - throw new Error("The overlay does not exist."); - } else if (this.#active) { - if (this.#active === dialog) { - throw new Error("The overlay is already active."); - } else if (this.#overlays.get(dialog).canForceClose) { - await this.close(); - } else { - throw new Error("Another overlay is currently active."); - } - } - this.#active = dialog; - dialog.showModal(); - } - async close(dialog = this.#active) { - if (!this.#overlays.has(dialog)) { - throw new Error("The overlay does not exist."); - } else if (!this.#active) { - throw new Error("The overlay is currently not active."); - } else if (this.#active !== dialog) { - throw new Error("Another overlay is currently active."); - } - dialog.close(); - this.#active = null; - } -} - - -/***/ }), - -/***/ 2690: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PasswordPrompt: () => (/* binding */ PasswordPrompt) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - -class PasswordPrompt { - #activeCapability = null; - #updateCallback = null; - #reason = null; - constructor(options, overlayManager, isViewerEmbedded = false) { - this.dialog = options.dialog; - this.label = options.label; - this.input = options.input; - this.submitButton = options.submitButton; - this.cancelButton = options.cancelButton; - this.overlayManager = overlayManager; - this._isViewerEmbedded = isViewerEmbedded; - this.submitButton.addEventListener("click", this.#verify.bind(this)); - this.cancelButton.addEventListener("click", this.close.bind(this)); - this.input.addEventListener("keydown", e => { - if (e.keyCode === 13) { - this.#verify(); - } - }); - this.overlayManager.register(this.dialog, true); - this.dialog.addEventListener("close", this.#cancel.bind(this)); - } - async open() { - await this.#activeCapability?.promise; - this.#activeCapability = Promise.withResolvers(); - try { - await this.overlayManager.open(this.dialog); - } catch (ex) { - this.#activeCapability.resolve(); - throw ex; - } - const passwordIncorrect = this.#reason === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PasswordResponses.INCORRECT_PASSWORD; - if (!this._isViewerEmbedded || passwordIncorrect) { - this.input.focus(); - } - this.label.setAttribute("data-l10n-id", `pdfjs-password-${passwordIncorrect ? "invalid" : "label"}`); - } - async close() { - if (this.overlayManager.active === this.dialog) { - this.overlayManager.close(this.dialog); - } - } - #verify() { - const password = this.input.value; - if (password?.length > 0) { - this.#invokeCallback(password); - } - } - #cancel() { - this.#invokeCallback(new Error("PasswordPrompt cancelled.")); - this.#activeCapability.resolve(); - } - #invokeCallback(password) { - if (!this.#updateCallback) { - return; - } - this.close(); - this.input.value = ""; - this.#updateCallback(password); - this.#updateCallback = null; - } - async setUpdateCallback(updateCallback, reason) { - if (this.#activeCapability) { - await this.#activeCapability.promise; - } - this.#updateCallback = updateCallback; - this.#reason = reason; - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 9251: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFAttachmentViewer: () => (/* binding */ PDFAttachmentViewer) -/* harmony export */ }); -/* harmony import */ var _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2961); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603); -/* harmony import */ var _event_utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5656); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - - -class PDFAttachmentViewer extends _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__.BaseTreeViewer { - constructor(options) { - super(options); - this.downloadManager = options.downloadManager; - this.eventBus._on("fileattachmentannotation", this.#appendAttachment.bind(this)); - } - reset(keepRenderedCapability = false) { - super.reset(); - this._attachments = null; - if (!keepRenderedCapability) { - this._renderedCapability = Promise.withResolvers(); - } - this._pendingDispatchEvent = false; - } - async _dispatchEvent(attachmentsCount) { - this._renderedCapability.resolve(); - if (attachmentsCount === 0 && !this._pendingDispatchEvent) { - this._pendingDispatchEvent = true; - await (0,_event_utils_js__WEBPACK_IMPORTED_MODULE_2__.waitOnEventOrTimeout)({ - target: this.eventBus, - name: "annotationlayerrendered", - delay: 1000 - }); - if (!this._pendingDispatchEvent) { - return; - } - } - this._pendingDispatchEvent = false; - this.eventBus.dispatch("attachmentsloaded", { - source: this, - attachmentsCount - }); - } - _bindLink(element, { - content, - filename - }) { - element.onclick = () => { - this.downloadManager.openOrDownloadData(content, filename); - return false; - }; - } - render({ - attachments, - keepRenderedCapability = false - }) { - if (this._attachments) { - this.reset(keepRenderedCapability); - } - this._attachments = attachments || null; - if (!attachments) { - this._dispatchEvent(0); - return; - } - const fragment = document.createDocumentFragment(); - let attachmentsCount = 0; - for (const name in attachments) { - const item = attachments[name]; - const content = item.content, - filename = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.getFilenameFromUrl)(item.filename, true); - const div = document.createElement("div"); - div.className = "treeItem"; - const element = document.createElement("a"); - this._bindLink(element, { - content, - filename - }); - element.textContent = this._normalizeTextContent(filename); - div.append(element); - fragment.append(div); - attachmentsCount++; - } - this._finishRendering(fragment, attachmentsCount); - } - #appendAttachment({ - filename, - content - }) { - const renderedPromise = this._renderedCapability.promise; - renderedPromise.then(() => { - if (renderedPromise !== this._renderedCapability.promise) { - return; - } - const attachments = this._attachments || Object.create(null); - for (const name in attachments) { - if (filename === name) { - return; - } - } - attachments[filename] = { - filename, - content - }; - this.render({ - attachments, - keepRenderedCapability: true - }); - }); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 5993: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFCursorTools: () => (/* binding */ PDFCursorTools) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256); -/* harmony import */ var _grab_to_pan_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2640); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - - -class PDFCursorTools { - #active = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.SELECT; - #prevActive = null; - constructor({ - container, - eventBus, - cursorToolOnLoad = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.SELECT - }) { - this.container = container; - this.eventBus = eventBus; - this.#addEventListeners(); - Promise.resolve().then(() => { - this.switchTool(cursorToolOnLoad); - }); - } - get activeTool() { - return this.#active; - } - switchTool(tool) { - if (this.#prevActive !== null) { - return; - } - if (tool === this.#active) { - return; - } - const disableActiveTool = () => { - switch (this.#active) { - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.SELECT: - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.HAND: - this._handTool.deactivate(); - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.ZOOM: - } - }; - switch (tool) { - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.SELECT: - disableActiveTool(); - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.HAND: - disableActiveTool(); - this._handTool.activate(); - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.ZOOM: - default: - console.error(`switchTool: "${tool}" is an unsupported value.`); - return; - } - this.#active = tool; - this.eventBus.dispatch("cursortoolchanged", { - source: this, - tool - }); - } - #addEventListeners() { - this.eventBus._on("switchcursortool", evt => { - if (!evt.reset) { - this.switchTool(evt.tool); - } else if (this.#prevActive !== null) { - annotationEditorMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE; - presentationModeState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.NORMAL; - enableActive(); - } - }); - let annotationEditorMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE, - presentationModeState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.NORMAL; - const disableActive = () => { - const prevActive = this.#active; - this.switchTool(_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.CursorTool.SELECT); - this.#prevActive ??= prevActive; - }; - const enableActive = () => { - const prevActive = this.#prevActive; - if (prevActive !== null && annotationEditorMode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE && presentationModeState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.NORMAL) { - this.#prevActive = null; - this.switchTool(prevActive); - } - }; - this.eventBus._on("annotationeditormodechanged", ({ - mode - }) => { - annotationEditorMode = mode; - if (mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) { - enableActive(); - } else { - disableActive(); - } - }); - this.eventBus._on("presentationmodechanged", ({ - state - }) => { - presentationModeState = state; - if (state === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.NORMAL) { - enableActive(); - } else if (state === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.FULLSCREEN) { - disableActive(); - } - }); - } - get _handTool() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "_handTool", new _grab_to_pan_js__WEBPACK_IMPORTED_MODULE_2__.GrabToPan({ - element: this.container - })); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 164: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFDocumentProperties: () => (/* binding */ PDFDocumentProperties) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -const DEFAULT_FIELD_CONTENT = "-"; -const NON_METRIC_LOCALES = ["en-us", "en-lr", "my"]; -const US_PAGE_NAMES = { - "8.5x11": "letter", - "8.5x14": "legal" -}; -const METRIC_PAGE_NAMES = { - "297x420": "a-three", - "210x297": "a-four" -}; -function getPageName(size, isPortrait, pageNames) { - const width = isPortrait ? size.width : size.height; - const height = isPortrait ? size.height : size.width; - return pageNames[`${width}x${height}`]; -} -class PDFDocumentProperties { - #fieldData = null; - constructor({ - dialog, - fields, - closeButton - }, overlayManager, eventBus, l10n, fileNameLookup) { - this.dialog = dialog; - this.fields = fields; - this.overlayManager = overlayManager; - this.l10n = l10n; - this._fileNameLookup = fileNameLookup; - this.#reset(); - closeButton.addEventListener("click", this.close.bind(this)); - this.overlayManager.register(this.dialog); - eventBus._on("pagechanging", evt => { - this._currentPageNumber = evt.pageNumber; - // console.log('test-number-message-send', evt.pageNumber,window.renderExtractLayer); - window.parent.postMessage({pageNum: evt.pageNumber}, '*'); - - }); - eventBus._on("rotationchanging", evt => { - this._pagesRotation = evt.pagesRotation; - }); - this._isNonMetricLocale = NON_METRIC_LOCALES.includes(l10n.getLanguage()); - - } - - - async open() { - await Promise.all([this.overlayManager.open(this.dialog), this._dataAvailableCapability.promise]); - const currentPageNumber = this._currentPageNumber; - const pagesRotation = this._pagesRotation; - if (this.#fieldData && currentPageNumber === this.#fieldData._currentPageNumber && pagesRotation === this.#fieldData._pagesRotation) { - this.#updateUI(); - return; - } - const { - info, - contentLength - } = await this.pdfDocument.getMetadata(); - const [fileName, fileSize, creationDate, modificationDate, pageSize, isLinearized] = await Promise.all([this._fileNameLookup(), this.#parseFileSize(contentLength), this.#parseDate(info.CreationDate), this.#parseDate(info.ModDate), this.pdfDocument.getPage(currentPageNumber).then(pdfPage => { - return this.#parsePageSize((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.getPageSizeInches)(pdfPage), pagesRotation); - }), this.#parseLinearization(info.IsLinearized)]); - - this.#fieldData = Object.freeze({ - fileName, - fileSize, - title: info.Title, - author: info.Author, - subject: info.Subject, - keywords: info.Keywords, - creationDate, - modificationDate, - creator: info.Creator, - producer: info.Producer, - version: info.PDFFormatVersion, - pageCount: this.pdfDocument.numPages, - pageSize, - linearized: isLinearized, - _currentPageNumber: currentPageNumber, - _pagesRotation: pagesRotation - }); - this.#updateUI(); - const { - length - } = await this.pdfDocument.getDownloadInfo(); - if (contentLength === length) { - return; - } - const data = Object.assign(Object.create(null), this.#fieldData); - data.fileSize = await this.#parseFileSize(length); - this.#fieldData = Object.freeze(data); - this.#updateUI(); - } - async close() { - this.overlayManager.close(this.dialog); - } - setDocument(pdfDocument) { - if (this.pdfDocument) { - this.#reset(); - this.#updateUI(true); - } - if (!pdfDocument) { - return; - } - this.pdfDocument = pdfDocument; - this._dataAvailableCapability.resolve(); - } - #reset() { - this.pdfDocument = null; - this.#fieldData = null; - this._dataAvailableCapability = Promise.withResolvers(); - this._currentPageNumber = 1; - this._pagesRotation = 0; - } - #updateUI(reset = false) { - if (reset || !this.#fieldData) { - for (const id in this.fields) { - this.fields[id].textContent = DEFAULT_FIELD_CONTENT; - } - return; - } - if (this.overlayManager.active !== this.dialog) { - return; - } - for (const id in this.fields) { - const content = this.#fieldData[id]; - this.fields[id].textContent = content || content === 0 ? content : DEFAULT_FIELD_CONTENT; - } - } - async #parseFileSize(fileSize = 0) { - const kb = fileSize / 1024, - mb = kb / 1024; - if (!kb) { - return undefined; - } - return this.l10n.get(`pdfjs-document-properties-${mb >= 1 ? "mb" : "kb"}`, { - size_mb: mb >= 1 && (+mb.toPrecision(3)).toLocaleString(), - size_kb: mb < 1 && (+kb.toPrecision(3)).toLocaleString(), - size_b: fileSize.toLocaleString() - }); - } - async #parsePageSize(pageSizeInches, pagesRotation) { - if (!pageSizeInches) { - return undefined; - } - if (pagesRotation % 180 !== 0) { - pageSizeInches = { - width: pageSizeInches.height, - height: pageSizeInches.width - }; - } - const isPortrait = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isPortraitOrientation)(pageSizeInches); - let sizeInches = { - width: Math.round(pageSizeInches.width * 100) / 100, - height: Math.round(pageSizeInches.height * 100) / 100 - }; - let sizeMillimeters = { - width: Math.round(pageSizeInches.width * 25.4 * 10) / 10, - height: Math.round(pageSizeInches.height * 25.4 * 10) / 10 - }; - let rawName = getPageName(sizeInches, isPortrait, US_PAGE_NAMES) || getPageName(sizeMillimeters, isPortrait, METRIC_PAGE_NAMES); - if (!rawName && !(Number.isInteger(sizeMillimeters.width) && Number.isInteger(sizeMillimeters.height))) { - const exactMillimeters = { - width: pageSizeInches.width * 25.4, - height: pageSizeInches.height * 25.4 - }; - const intMillimeters = { - width: Math.round(sizeMillimeters.width), - height: Math.round(sizeMillimeters.height) - }; - if (Math.abs(exactMillimeters.width - intMillimeters.width) < 0.1 && Math.abs(exactMillimeters.height - intMillimeters.height) < 0.1) { - rawName = getPageName(intMillimeters, isPortrait, METRIC_PAGE_NAMES); - if (rawName) { - sizeInches = { - width: Math.round(intMillimeters.width / 25.4 * 100) / 100, - height: Math.round(intMillimeters.height / 25.4 * 100) / 100 - }; - sizeMillimeters = intMillimeters; - } - } - } - const [{ - width, - height - }, unit, name, orientation] = await Promise.all([this._isNonMetricLocale ? sizeInches : sizeMillimeters, this.l10n.get(`pdfjs-document-properties-page-size-unit-${this._isNonMetricLocale ? "inches" : "millimeters"}`), rawName && this.l10n.get(`pdfjs-document-properties-page-size-name-${rawName}`), this.l10n.get(`pdfjs-document-properties-page-size-orientation-${isPortrait ? "portrait" : "landscape"}`)]); - return this.l10n.get(`pdfjs-document-properties-page-size-dimension-${name ? "name-" : ""}string`, { - width: width.toLocaleString(), - height: height.toLocaleString(), - unit, - name, - orientation - }); - } - async #parseDate(inputDate) { - const dateObject = pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.PDFDateString.toDateObject(inputDate); - if (!dateObject) { - return undefined; - } - return this.l10n.get("pdfjs-document-properties-date-string", { - date: dateObject.toLocaleDateString(), - time: dateObject.toLocaleTimeString() - }); - } - #parseLinearization(isLinearized) { - return this.l10n.get(`pdfjs-document-properties-linearized-${isLinearized ? "yes" : "no"}`); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 2226: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFFindBar: () => (/* binding */ PDFFindBar) -/* harmony export */ }); -/* harmony import */ var _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9814); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256); - - -const MATCHES_COUNT_LIMIT = 1000; -class PDFFindBar { - #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this)); - constructor(options, eventBus) { - this.opened = false; - this.bar = options.bar; - this.toggleButton = options.toggleButton; - this.findField = options.findField; - this.highlightAll = options.highlightAllCheckbox; - this.caseSensitive = options.caseSensitiveCheckbox; - this.matchDiacritics = options.matchDiacriticsCheckbox; - this.entireWord = options.entireWordCheckbox; - this.findMsg = options.findMsg; - this.findResultsCount = options.findResultsCount; - this.findPreviousButton = options.findPreviousButton; - this.findNextButton = options.findNextButton; - this.eventBus = eventBus; - this.toggleButton.addEventListener("click", () => { - this.toggle(); - }); - this.findField.addEventListener("input", () => { - this.dispatchEvent(""); - }); - this.bar.addEventListener("keydown", e => { - switch (e.keyCode) { - case 13: - if (e.target === this.findField) { - this.dispatchEvent("again", e.shiftKey); - } - break; - case 27: - this.close(); - break; - } - }); - this.findPreviousButton.addEventListener("click", () => { - this.dispatchEvent("again", true); - }); - this.findNextButton.addEventListener("click", () => { - this.dispatchEvent("again", false); - }); - this.highlightAll.addEventListener("click", () => { - this.dispatchEvent("highlightallchange"); - }); - this.caseSensitive.addEventListener("click", () => { - this.dispatchEvent("casesensitivitychange"); - }); - this.entireWord.addEventListener("click", () => { - this.dispatchEvent("entirewordchange"); - }); - this.matchDiacritics.addEventListener("click", () => { - this.dispatchEvent("diacriticmatchingchange"); - }); - } - reset() { - this.updateUIState(); - } - dispatchEvent(type, findPrev = false) { - this.eventBus.dispatch("find", { - source: this, - type, - query: this.findField.value, - caseSensitive: this.caseSensitive.checked, - entireWord: this.entireWord.checked, - highlightAll: this.highlightAll.checked, - findPrevious: findPrev, - matchDiacritics: this.matchDiacritics.checked - }); - } - updateUIState(state, previous, matchesCount) { - const { - findField, - findMsg - } = this; - let findMsgId = "", - status = ""; - switch (state) { - case _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__.FindState.FOUND: - break; - case _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__.FindState.PENDING: - status = "pending"; - break; - case _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__.FindState.NOT_FOUND: - findMsgId = "pdfjs-find-not-found"; - status = "notFound"; - break; - case _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__.FindState.WRAPPED: - findMsgId = `pdfjs-find-reached-${previous ? "top" : "bottom"}`; - break; - } - findField.setAttribute("data-status", status); - findField.setAttribute("aria-invalid", state === _pdf_find_controller_js__WEBPACK_IMPORTED_MODULE_0__.FindState.NOT_FOUND); - findMsg.setAttribute("data-status", status); - if (findMsgId) { - findMsg.setAttribute("data-l10n-id", findMsgId); - } else { - findMsg.removeAttribute("data-l10n-id"); - findMsg.textContent = ""; - } - this.updateResultsCount(matchesCount); - } - updateResultsCount({ - current = 0, - total = 0 - } = {}) { - const { - findResultsCount - } = this; - if (total > 0) { - const limit = MATCHES_COUNT_LIMIT; - findResultsCount.setAttribute("data-l10n-id", `pdfjs-find-match-count${total > limit ? "-limit" : ""}`); - findResultsCount.setAttribute("data-l10n-args", JSON.stringify({ - limit, - current, - total - })); - } else { - findResultsCount.removeAttribute("data-l10n-id"); - findResultsCount.textContent = ""; - } - } - open() { - if (!this.opened) { - this.#resizeObserver.observe(this.bar.parentNode); - this.#resizeObserver.observe(this.bar); - this.opened = true; - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleExpandedBtn)(this.toggleButton, true, this.bar); - } - this.findField.select(); - this.findField.focus(); - } - close() { - if (!this.opened) { - return; - } - this.#resizeObserver.disconnect(); - this.opened = false; - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleExpandedBtn)(this.toggleButton, false, this.bar); - this.eventBus.dispatch("findbarclose", { - source: this - }); - } - toggle() { - if (this.opened) { - this.close(); - } else { - this.open(); - } - } - #resizeObserverCallback(entries) { - const { - bar - } = this; - bar.classList.remove("wrapContainers"); - const findbarHeight = bar.clientHeight; - const inputContainerHeight = bar.firstElementChild.clientHeight; - if (findbarHeight > inputContainerHeight) { - bar.classList.add("wrapContainers"); - } - } -} - - -/***/ }), - -/***/ 9814: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - - -// EXPORTS -__webpack_require__.d(__webpack_exports__, { - FindState: () => (/* binding */ FindState), - PDFFindController: () => (/* binding */ PDFFindController) -}); - -// EXTERNAL MODULE: ./web/ui_utils.js -var ui_utils = __webpack_require__(7256); -;// CONCATENATED MODULE: ./web/pdf_find_utils.js -const CharacterType = { - SPACE: 0, - ALPHA_LETTER: 1, - PUNCT: 2, - HAN_LETTER: 3, - KATAKANA_LETTER: 4, - HIRAGANA_LETTER: 5, - HALFWIDTH_KATAKANA_LETTER: 6, - THAI_LETTER: 7 -}; -function isAlphabeticalScript(charCode) { - return charCode < 0x2e80; -} -function isAscii(charCode) { - return (charCode & 0xff80) === 0; -} -function isAsciiAlpha(charCode) { - return charCode >= 0x61 && charCode <= 0x7a || charCode >= 0x41 && charCode <= 0x5a; -} -function isAsciiDigit(charCode) { - return charCode >= 0x30 && charCode <= 0x39; -} -function isAsciiSpace(charCode) { - return charCode === 0x20 || charCode === 0x09 || charCode === 0x0d || charCode === 0x0a; -} -function isHan(charCode) { - return charCode >= 0x3400 && charCode <= 0x9fff || charCode >= 0xf900 && charCode <= 0xfaff; -} -function isKatakana(charCode) { - return charCode >= 0x30a0 && charCode <= 0x30ff; -} -function isHiragana(charCode) { - return charCode >= 0x3040 && charCode <= 0x309f; -} -function isHalfwidthKatakana(charCode) { - return charCode >= 0xff60 && charCode <= 0xff9f; -} -function isThai(charCode) { - return (charCode & 0xff80) === 0x0e00; -} -function getCharacterType(charCode) { - if (isAlphabeticalScript(charCode)) { - if (isAscii(charCode)) { - if (isAsciiSpace(charCode)) { - return CharacterType.SPACE; - } else if (isAsciiAlpha(charCode) || isAsciiDigit(charCode) || charCode === 0x5f) { - return CharacterType.ALPHA_LETTER; - } - return CharacterType.PUNCT; - } else if (isThai(charCode)) { - return CharacterType.THAI_LETTER; - } else if (charCode === 0xa0) { - return CharacterType.SPACE; - } - return CharacterType.ALPHA_LETTER; - } - if (isHan(charCode)) { - return CharacterType.HAN_LETTER; - } else if (isKatakana(charCode)) { - return CharacterType.KATAKANA_LETTER; - } else if (isHiragana(charCode)) { - return CharacterType.HIRAGANA_LETTER; - } else if (isHalfwidthKatakana(charCode)) { - return CharacterType.HALFWIDTH_KATAKANA_LETTER; - } - return CharacterType.ALPHA_LETTER; -} -let NormalizeWithNFKC; -function getNormalizeWithNFKC() { - NormalizeWithNFKC ||= `聽篓陋炉虏-碌赂-潞录-戮牟-某目-艀艍趴莿-菍潜-浅拾-矢藰-藵藸-摔痛秃途蝿-螀螄蠍-蠔习-喜洗-系瞎謬俚-俑啷�-啷熰-唰澿啜赤ǘ喋�-喋涏喹�-喹澿赋嗪赤粶-嗷澿紝嘟冟綅嘟掄綏嘟溹僵醿坚船-岽窗-岽横醇-岬嶀祻-岬蹈岫�-岫酷簹-岷涐奖峤翅降峤丰焦峤会浇峋会窘-峥佱繅峥嬦繊-峥忈繐峥涐繚-峥熱浚峥凯-峥抗峥会拷-峥锯€€-鈥娾€戔€椻€�-鈥︹€€�-鈥粹€�-鈥封€尖€锯亣-鈦夆仐鈦熲伆-鈦扁伌-鈧庘倫-鈧溾偍鈩€-鈩冣剠-鈩団剦-鈩撯剷-鈩栤剻-鈩濃劆-鈩⑩劋鈩︹劏鈩�-鈩劘-鈩扁劤-鈩光劵-鈪€鈪�-鈪夆厫-鈪库唹鈭�-鈭埊-鈭扳尒-鈱憼-鈸▽猢�-猢垛珳獗�-獗解弹夂熲怀饧€-饪曘€€銆躲€�-銆恒倹-銈溿偀銉裤劚-銌庛啋-銌熴垁-銏炪垹-銐囥墣-銐俱妧-銖筷殰-隁濌澃隉�-隉搓煾-隉龟瓬-戥熽铯€-铷嶏◥铷掞〞-铷烇铷ē-铷︼í-铹┌-铽欙瑎-铿嗭瑩-铿楋瑵铿�-铿讹-铿硷锃€-锃侊瓋-锃勶瓎-锂憋瘬-锎斤祼-锒忥稈-锓囷钒-锓硷笎-锔欙赴-锕勶箛-锕掞箶-锕︼龚-锕拱-锕诧勾锕�-锘硷紒-锞撅總-锟囷繆-锟忥繏-锟楋繗-锟滐繝-锟`; - return NormalizeWithNFKC; -} - -;// CONCATENATED MODULE: ./web/pdf_find_controller.js - - -const FindState = { - FOUND: 0, - NOT_FOUND: 1, - WRAPPED: 2, - PENDING: 3 -}; -const FIND_TIMEOUT = 250; -const MATCH_SCROLL_OFFSET_TOP = -50; -const MATCH_SCROLL_OFFSET_LEFT = -400; -const CHARACTERS_TO_NORMALIZE = { - "\u2010": "-", - "\u2018": "'", - "\u2019": "'", - "\u201A": "'", - "\u201B": "'", - "\u201C": '"', - "\u201D": '"', - "\u201E": '"', - "\u201F": '"', - "\u00BC": "1/4", - "\u00BD": "1/2", - "\u00BE": "3/4" -}; -const DIACRITICS_EXCEPTION = new Set([0x3099, 0x309a, 0x094d, 0x09cd, 0x0a4d, 0x0acd, 0x0b4d, 0x0bcd, 0x0c4d, 0x0ccd, 0x0d3b, 0x0d3c, 0x0d4d, 0x0dca, 0x0e3a, 0x0eba, 0x0f84, 0x1039, 0x103a, 0x1714, 0x1734, 0x17d2, 0x1a60, 0x1b44, 0x1baa, 0x1bab, 0x1bf2, 0x1bf3, 0x2d7f, 0xa806, 0xa82c, 0xa8c4, 0xa953, 0xa9c0, 0xaaf6, 0xabed, 0x0c56, 0x0f71, 0x0f72, 0x0f7a, 0x0f7b, 0x0f7c, 0x0f7d, 0x0f80, 0x0f74]); -let DIACRITICS_EXCEPTION_STR; -const DIACRITICS_REG_EXP = /\p{M}+/gu; -const SPECIAL_CHARS_REG_EXP = /([.*+?^${}()|[\]\\])|(\p{P})|(\s+)|(\p{M})|(\p{L})/gu; -const NOT_DIACRITIC_FROM_END_REG_EXP = /([^\p{M}])\p{M}*$/u; -const NOT_DIACRITIC_FROM_START_REG_EXP = /^\p{M}*([^\p{M}])/u; -const SYLLABLES_REG_EXP = /[\uAC00-\uD7AF\uFA6C\uFACF-\uFAD1\uFAD5-\uFAD7]+/g; -const SYLLABLES_LENGTHS = new Map(); -const FIRST_CHAR_SYLLABLES_REG_EXP = "[\\u1100-\\u1112\\ud7a4-\\ud7af\\ud84a\\ud84c\\ud850\\ud854\\ud857\\ud85f]"; -const NFKC_CHARS_TO_NORMALIZE = new Map(); -let noSyllablesRegExp = null; -let withSyllablesRegExp = null; -function normalize(text) { - const syllablePositions = []; - let m; - while ((m = SYLLABLES_REG_EXP.exec(text)) !== null) { - let { - index - } = m; - for (const char of m[0]) { - let len = SYLLABLES_LENGTHS.get(char); - if (!len) { - len = char.normalize("NFD").length; - SYLLABLES_LENGTHS.set(char, len); - } - syllablePositions.push([len, index++]); - } - } - let normalizationRegex; - if (syllablePositions.length === 0 && noSyllablesRegExp) { - normalizationRegex = noSyllablesRegExp; - } else if (syllablePositions.length > 0 && withSyllablesRegExp) { - normalizationRegex = withSyllablesRegExp; - } else { - const replace = Object.keys(CHARACTERS_TO_NORMALIZE).join(""); - const toNormalizeWithNFKC = getNormalizeWithNFKC(); - const CJK = "(?:\\p{Ideographic}|[\u3040-\u30FF])"; - const HKDiacritics = "(?:\u3099|\u309A)"; - const regexp = `([${replace}])|([${toNormalizeWithNFKC}])|(${HKDiacritics}\\n)|(\\p{M}+(?:-\\n)?)|(\\S-\\n)|(${CJK}\\n)|(\\n)`; - if (syllablePositions.length === 0) { - normalizationRegex = noSyllablesRegExp = new RegExp(regexp + "|(\\u0000)", "gum"); - } else { - normalizationRegex = withSyllablesRegExp = new RegExp(regexp + `|(${FIRST_CHAR_SYLLABLES_REG_EXP})`, "gum"); - } - } - const rawDiacriticsPositions = []; - while ((m = DIACRITICS_REG_EXP.exec(text)) !== null) { - rawDiacriticsPositions.push([m[0].length, m.index]); - } - let normalized = text.normalize("NFD"); - const positions = [[0, 0]]; - let rawDiacriticsIndex = 0; - let syllableIndex = 0; - let shift = 0; - let shiftOrigin = 0; - let eol = 0; - let hasDiacritics = false; - normalized = normalized.replace(normalizationRegex, (match, p1, p2, p3, p4, p5, p6, p7, p8, i) => { - i -= shiftOrigin; - if (p1) { - const replacement = CHARACTERS_TO_NORMALIZE[p1]; - const jj = replacement.length; - for (let j = 1; j < jj; j++) { - positions.push([i - shift + j, shift - j]); - } - shift -= jj - 1; - return replacement; - } - if (p2) { - let replacement = NFKC_CHARS_TO_NORMALIZE.get(p2); - if (!replacement) { - replacement = p2.normalize("NFKC"); - NFKC_CHARS_TO_NORMALIZE.set(p2, replacement); - } - const jj = replacement.length; - for (let j = 1; j < jj; j++) { - positions.push([i - shift + j, shift - j]); - } - shift -= jj - 1; - return replacement; - } - if (p3) { - hasDiacritics = true; - if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) { - ++rawDiacriticsIndex; - } else { - positions.push([i - 1 - shift + 1, shift - 1]); - shift -= 1; - shiftOrigin += 1; - } - positions.push([i - shift + 1, shift]); - shiftOrigin += 1; - eol += 1; - return p3.charAt(0); - } - if (p4) { - const hasTrailingDashEOL = p4.endsWith("\n"); - const len = hasTrailingDashEOL ? p4.length - 2 : p4.length; - hasDiacritics = true; - let jj = len; - if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) { - jj -= rawDiacriticsPositions[rawDiacriticsIndex][0]; - ++rawDiacriticsIndex; - } - for (let j = 1; j <= jj; j++) { - positions.push([i - 1 - shift + j, shift - j]); - } - shift -= jj; - shiftOrigin += jj; - if (hasTrailingDashEOL) { - i += len - 1; - positions.push([i - shift + 1, 1 + shift]); - shift += 1; - shiftOrigin += 1; - eol += 1; - return p4.slice(0, len); - } - return p4; - } - if (p5) { - const len = p5.length - 2; - positions.push([i - shift + len, 1 + shift]); - shift += 1; - shiftOrigin += 1; - eol += 1; - return p5.slice(0, -2); - } - if (p6) { - const len = p6.length - 1; - positions.push([i - shift + len, shift]); - shiftOrigin += 1; - eol += 1; - return p6.slice(0, -1); - } - if (p7) { - positions.push([i - shift + 1, shift - 1]); - shift -= 1; - shiftOrigin += 1; - eol += 1; - return " "; - } - if (i + eol === syllablePositions[syllableIndex]?.[1]) { - const newCharLen = syllablePositions[syllableIndex][0] - 1; - ++syllableIndex; - for (let j = 1; j <= newCharLen; j++) { - positions.push([i - (shift - j), shift - j]); - } - shift -= newCharLen; - shiftOrigin += newCharLen; - } - return p8; - }); - positions.push([normalized.length, shift]); - return [normalized, positions, hasDiacritics]; -} -function getOriginalIndex(diffs, pos, len) { - if (!diffs) { - return [pos, len]; - } - const start = pos; - const end = pos + len - 1; - let i = (0,ui_utils.binarySearchFirstItem)(diffs, x => x[0] >= start); - if (diffs[i][0] > start) { - --i; - } - let j = (0,ui_utils.binarySearchFirstItem)(diffs, x => x[0] >= end, i); - if (diffs[j][0] > end) { - --j; - } - const oldStart = start + diffs[i][1]; - const oldEnd = end + diffs[j][1]; - const oldLen = oldEnd + 1 - oldStart; - return [oldStart, oldLen]; -} -class PDFFindController { - #state = null; - #updateMatchesCountOnProgress = true; - #visitedPagesCount = 0; - constructor({ - linkService, - eventBus, - updateMatchesCountOnProgress = true - }) { - this._linkService = linkService; - this._eventBus = eventBus; - this.#updateMatchesCountOnProgress = updateMatchesCountOnProgress; - this.onIsPageVisible = null; - this.#reset(); - eventBus._on("find", this.#onFind.bind(this)); - eventBus._on("findbarclose", this.#onFindBarClose.bind(this)); - } - get highlightMatches() { - return this._highlightMatches; - } - get pageMatches() { - return this._pageMatches; - } - get pageMatchesLength() { - return this._pageMatchesLength; - } - get selected() { - return this._selected; - } - get state() { - return this.#state; - } - setDocument(pdfDocument) { - if (this._pdfDocument) { - this.#reset(); - } - if (!pdfDocument) { - return; - } - this._pdfDocument = pdfDocument; - this._firstPageCapability.resolve(); - } - #onFind(state) { - if (!state) { - return; - } - const pdfDocument = this._pdfDocument; - const { - type - } = state; - if (this.#state === null || this.#shouldDirtyMatch(state)) { - this._dirtyMatch = true; - } - this.#state = state; - if (type !== "highlightallchange") { - this.#updateUIState(FindState.PENDING); - } - this._firstPageCapability.promise.then(() => { - if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) { - return; - } - this.#extractText(); - const findbarClosed = !this._highlightMatches; - const pendingTimeout = !!this._findTimeout; - if (this._findTimeout) { - clearTimeout(this._findTimeout); - this._findTimeout = null; - } - if (!type) { - this._findTimeout = setTimeout(() => { - this.#nextMatch(); - this._findTimeout = null; - }, FIND_TIMEOUT); - } else if (this._dirtyMatch) { - this.#nextMatch(); - } else if (type === "again") { - this.#nextMatch(); - if (findbarClosed && this.#state.highlightAll) { - this.#updateAllPages(); - } - } else if (type === "highlightallchange") { - if (pendingTimeout) { - this.#nextMatch(); - } else { - this._highlightMatches = true; - } - this.#updateAllPages(); - } else { - this.#nextMatch(); - } - }); - } - scrollMatchIntoView({ - element = null, - selectedLeft = 0, - pageIndex = -1, - matchIndex = -1 - }) { - if (!this._scrollMatches || !element) { - return; - } else if (matchIndex === -1 || matchIndex !== this._selected.matchIdx) { - return; - } else if (pageIndex === -1 || pageIndex !== this._selected.pageIdx) { - return; - } - this._scrollMatches = false; - const spot = { - top: MATCH_SCROLL_OFFSET_TOP, - left: selectedLeft + MATCH_SCROLL_OFFSET_LEFT - }; - (0,ui_utils.scrollIntoView)(element, spot, true); - } - #reset() { - this._highlightMatches = false; - this._scrollMatches = false; - this._pdfDocument = null; - this._pageMatches = []; - this._pageMatchesLength = []; - this.#visitedPagesCount = 0; - this.#state = null; - this._selected = { - pageIdx: -1, - matchIdx: -1 - }; - this._offset = { - pageIdx: null, - matchIdx: null, - wrapped: false - }; - this._extractTextPromises = []; - this._pageContents = []; - this._pageDiffs = []; - this._hasDiacritics = []; - this._matchesCountTotal = 0; - this._pagesToSearch = null; - this._pendingFindMatches = new Set(); - this._resumePageIdx = null; - this._dirtyMatch = false; - clearTimeout(this._findTimeout); - this._findTimeout = null; - this._firstPageCapability = Promise.withResolvers(); - } - get #query() { - const { - query - } = this.#state; - if (typeof query === "string") { - if (query !== this._rawQuery) { - this._rawQuery = query; - [this._normalizedQuery] = normalize(query); - } - return this._normalizedQuery; - } - return (query || []).filter(q => !!q).map(q => normalize(q)[0]); - } - #shouldDirtyMatch(state) { - const newQuery = state.query, - prevQuery = this.#state.query; - const newType = typeof newQuery, - prevType = typeof prevQuery; - if (newType !== prevType) { - return true; - } - if (newType === "string") { - if (newQuery !== prevQuery) { - return true; - } - } else if (JSON.stringify(newQuery) !== JSON.stringify(prevQuery)) { - return true; - } - switch (state.type) { - case "again": - const pageNumber = this._selected.pageIdx + 1; - const linkService = this._linkService; - return pageNumber >= 1 && pageNumber <= linkService.pagesCount && pageNumber !== linkService.page && !(this.onIsPageVisible?.(pageNumber) ?? true); - case "highlightallchange": - return false; - } - return true; - } - #isEntireWord(content, startIdx, length) { - let match = content.slice(0, startIdx).match(NOT_DIACRITIC_FROM_END_REG_EXP); - if (match) { - const first = content.charCodeAt(startIdx); - const limit = match[1].charCodeAt(0); - if (getCharacterType(first) === getCharacterType(limit)) { - return false; - } - } - match = content.slice(startIdx + length).match(NOT_DIACRITIC_FROM_START_REG_EXP); - if (match) { - const last = content.charCodeAt(startIdx + length - 1); - const limit = match[1].charCodeAt(0); - if (getCharacterType(last) === getCharacterType(limit)) { - return false; - } - } - return true; - } - #calculateRegExpMatch(query, entireWord, pageIndex, pageContent) { - const matches = this._pageMatches[pageIndex] = []; - const matchesLength = this._pageMatchesLength[pageIndex] = []; - if (!query) { - return; - } - const diffs = this._pageDiffs[pageIndex]; - let match; - while ((match = query.exec(pageContent)) !== null) { - if (entireWord && !this.#isEntireWord(pageContent, match.index, match[0].length)) { - continue; - } - const [matchPos, matchLen] = getOriginalIndex(diffs, match.index, match[0].length); - if (matchLen) { - matches.push(matchPos); - matchesLength.push(matchLen); - } - } - } - #convertToRegExpString(query, hasDiacritics) { - const { - matchDiacritics - } = this.#state; - let isUnicode = false; - query = query.replaceAll(SPECIAL_CHARS_REG_EXP, (match, p1, p2, p3, p4, p5) => { - if (p1) { - return `[ ]*\\${p1}[ ]*`; - } - if (p2) { - return `[ ]*${p2}[ ]*`; - } - if (p3) { - return "[ ]+"; - } - if (matchDiacritics) { - return p4 || p5; - } - if (p4) { - return DIACRITICS_EXCEPTION.has(p4.charCodeAt(0)) ? p4 : ""; - } - if (hasDiacritics) { - isUnicode = true; - return `${p5}\\p{M}*`; - } - return p5; - }); - const trailingSpaces = "[ ]*"; - if (query.endsWith(trailingSpaces)) { - query = query.slice(0, query.length - trailingSpaces.length); - } - if (matchDiacritics) { - if (hasDiacritics) { - DIACRITICS_EXCEPTION_STR ||= String.fromCharCode(...DIACRITICS_EXCEPTION); - isUnicode = true; - query = `${query}(?=[${DIACRITICS_EXCEPTION_STR}]|[^\\p{M}]|$)`; - } - } - return [isUnicode, query]; - } - #calculateMatch(pageIndex) { - let query = this.#query; - if (query.length === 0) { - return; - } - const { - caseSensitive, - entireWord - } = this.#state; - const pageContent = this._pageContents[pageIndex]; - const hasDiacritics = this._hasDiacritics[pageIndex]; - let isUnicode = false; - if (typeof query === "string") { - [isUnicode, query] = this.#convertToRegExpString(query, hasDiacritics); - } else { - query = query.sort().reverse().map(q => { - const [isUnicodePart, queryPart] = this.#convertToRegExpString(q, hasDiacritics); - isUnicode ||= isUnicodePart; - return `(${queryPart})`; - }).join("|"); - } - const flags = `g${isUnicode ? "u" : ""}${caseSensitive ? "" : "i"}`; - query = query ? new RegExp(query, flags) : null; - this.#calculateRegExpMatch(query, entireWord, pageIndex, pageContent); - if (this.#state.highlightAll) { - this.#updatePage(pageIndex); - } - if (this._resumePageIdx === pageIndex) { - this._resumePageIdx = null; - this.#nextPageMatch(); - } - const pageMatchesCount = this._pageMatches[pageIndex].length; - this._matchesCountTotal += pageMatchesCount; - if (this.#updateMatchesCountOnProgress) { - if (pageMatchesCount > 0) { - this.#updateUIResultsCount(); - } - } else if (++this.#visitedPagesCount === this._linkService.pagesCount) { - this.#updateUIResultsCount(); - } - } - #extractText() { - if (this._extractTextPromises.length > 0) { - return; - } - let deferred = Promise.resolve(); - const textOptions = { - disableNormalization: true - }; - for (let i = 0, ii = this._linkService.pagesCount; i < ii; i++) { - const { - promise, - resolve - } = Promise.withResolvers(); - this._extractTextPromises[i] = promise; - deferred = deferred.then(() => { - return this._pdfDocument.getPage(i + 1).then(pdfPage => pdfPage.getTextContent(textOptions)).then(textContent => { - const strBuf = []; - for (const textItem of textContent.items) { - strBuf.push(textItem.str); - if (textItem.hasEOL) { - strBuf.push("\n"); - } - } - [this._pageContents[i], this._pageDiffs[i], this._hasDiacritics[i]] = normalize(strBuf.join("")); - resolve(); - }, reason => { - console.error(`Unable to get text content for page ${i + 1}`, reason); - this._pageContents[i] = ""; - this._pageDiffs[i] = null; - this._hasDiacritics[i] = false; - resolve(); - }); - }); - } - } - #updatePage(index) { - if (this._scrollMatches && this._selected.pageIdx === index) { - this._linkService.page = index + 1; - } - this._eventBus.dispatch("updatetextlayermatches", { - source: this, - pageIndex: index - }); - } - #updateAllPages() { - this._eventBus.dispatch("updatetextlayermatches", { - source: this, - pageIndex: -1 - }); - } - #nextMatch() { - const previous = this.#state.findPrevious; - const currentPageIndex = this._linkService.page - 1; - const numPages = this._linkService.pagesCount; - this._highlightMatches = true; - if (this._dirtyMatch) { - this._dirtyMatch = false; - this._selected.pageIdx = this._selected.matchIdx = -1; - this._offset.pageIdx = currentPageIndex; - this._offset.matchIdx = null; - this._offset.wrapped = false; - this._resumePageIdx = null; - this._pageMatches.length = 0; - this._pageMatchesLength.length = 0; - this.#visitedPagesCount = 0; - this._matchesCountTotal = 0; - this.#updateAllPages(); - for (let i = 0; i < numPages; i++) { - if (this._pendingFindMatches.has(i)) { - continue; - } - this._pendingFindMatches.add(i); - this._extractTextPromises[i].then(() => { - this._pendingFindMatches.delete(i); - this.#calculateMatch(i); - }); - } - } - const query = this.#query; - if (query.length === 0) { - this.#updateUIState(FindState.FOUND); - return; - } - if (this._resumePageIdx) { - return; - } - const offset = this._offset; - this._pagesToSearch = numPages; - if (offset.matchIdx !== null) { - const numPageMatches = this._pageMatches[offset.pageIdx].length; - if (!previous && offset.matchIdx + 1 < numPageMatches || previous && offset.matchIdx > 0) { - offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1; - this.#updateMatch(true); - return; - } - this.#advanceOffsetPage(previous); - } - this.#nextPageMatch(); - } - #matchesReady(matches) { - const offset = this._offset; - const numMatches = matches.length; - const previous = this.#state.findPrevious; - if (numMatches) { - offset.matchIdx = previous ? numMatches - 1 : 0; - this.#updateMatch(true); - return true; - } - this.#advanceOffsetPage(previous); - if (offset.wrapped) { - offset.matchIdx = null; - if (this._pagesToSearch < 0) { - this.#updateMatch(false); - return true; - } - } - return false; - } - #nextPageMatch() { - if (this._resumePageIdx !== null) { - console.error("There can only be one pending page."); - } - let matches = null; - do { - const pageIdx = this._offset.pageIdx; - matches = this._pageMatches[pageIdx]; - if (!matches) { - this._resumePageIdx = pageIdx; - break; - } - } while (!this.#matchesReady(matches)); - } - #advanceOffsetPage(previous) { - const offset = this._offset; - const numPages = this._linkService.pagesCount; - offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1; - offset.matchIdx = null; - this._pagesToSearch--; - if (offset.pageIdx >= numPages || offset.pageIdx < 0) { - offset.pageIdx = previous ? numPages - 1 : 0; - offset.wrapped = true; - } - } - #updateMatch(found = false) { - let state = FindState.NOT_FOUND; - const wrapped = this._offset.wrapped; - this._offset.wrapped = false; - if (found) { - const previousPage = this._selected.pageIdx; - this._selected.pageIdx = this._offset.pageIdx; - this._selected.matchIdx = this._offset.matchIdx; - state = wrapped ? FindState.WRAPPED : FindState.FOUND; - if (previousPage !== -1 && previousPage !== this._selected.pageIdx) { - this.#updatePage(previousPage); - } - } - this.#updateUIState(state, this.#state.findPrevious); - if (this._selected.pageIdx !== -1) { - this._scrollMatches = true; - this.#updatePage(this._selected.pageIdx); - } - } - #onFindBarClose(evt) { - const pdfDocument = this._pdfDocument; - this._firstPageCapability.promise.then(() => { - if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) { - return; - } - if (this._findTimeout) { - clearTimeout(this._findTimeout); - this._findTimeout = null; - } - if (this._resumePageIdx) { - this._resumePageIdx = null; - this._dirtyMatch = true; - } - this.#updateUIState(FindState.FOUND); - this._highlightMatches = false; - this.#updateAllPages(); - }); - } - #requestMatchesCount() { - const { - pageIdx, - matchIdx - } = this._selected; - let current = 0, - total = this._matchesCountTotal; - if (matchIdx !== -1) { - for (let i = 0; i < pageIdx; i++) { - current += this._pageMatches[i]?.length || 0; - } - current += matchIdx + 1; - } - if (current < 1 || current > total) { - current = total = 0; - } - return { - current, - total - }; - } - #updateUIResultsCount() { - this._eventBus.dispatch("updatefindmatchescount", { - source: this, - matchesCount: this.#requestMatchesCount() - }); - } - #updateUIState(state, previous = false) { - if (!this.#updateMatchesCountOnProgress && (this.#visitedPagesCount !== this._linkService.pagesCount || state === FindState.PENDING)) { - return; - } - this._eventBus.dispatch("updatefindcontrolstate", { - source: this, - state, - previous, - matchesCount: this.#requestMatchesCount(), - rawQuery: this.#state?.query ?? null - }); - } -} - - -/***/ }), - -/***/ 8543: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFHistory: () => (/* binding */ PDFHistory) -/* harmony export */ }); -/* unused harmony exports isDestArraysEqual, isDestHashesEqual */ -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); -/* harmony import */ var _event_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5656); - - -const HASH_CHANGE_TIMEOUT = 1000; -const POSITION_UPDATED_THRESHOLD = 50; -const UPDATE_VIEWAREA_TIMEOUT = 1000; -function getCurrentHash() { - return document.location.hash; -} -class PDFHistory { - #eventAbortController = null; - constructor({ - linkService, - eventBus - }) { - this.linkService = linkService; - this.eventBus = eventBus; - this._initialized = false; - this._fingerprint = ""; - this.reset(); - this.eventBus._on("pagesinit", () => { - this._isPagesLoaded = false; - this.eventBus._on("pagesloaded", evt => { - this._isPagesLoaded = !!evt.pagesCount; - }, { - once: true - }); - }); - } - initialize({ - fingerprint, - resetHistory = false, - updateUrl = false - }) { - if (!fingerprint || typeof fingerprint !== "string") { - console.error('PDFHistory.initialize: The "fingerprint" must be a non-empty string.'); - return; - } - if (this._initialized) { - this.reset(); - } - const reInitialized = this._fingerprint !== "" && this._fingerprint !== fingerprint; - this._fingerprint = fingerprint; - this._updateUrl = updateUrl === true; - this._initialized = true; - this.#bindEvents(); - const state = window.history.state; - this._popStateInProgress = false; - this._blockHashChange = 0; - this._currentHash = getCurrentHash(); - this._numPositionUpdates = 0; - this._uid = this._maxUid = 0; - this._destination = null; - this._position = null; - if (!this.#isValidState(state, true) || resetHistory) { - const { - hash, - page, - rotation - } = this.#parseCurrentHash(true); - if (!hash || reInitialized || resetHistory) { - this.#pushOrReplaceState(null, true); - return; - } - this.#pushOrReplaceState({ - hash, - page, - rotation - }, true); - return; - } - const destination = state.destination; - this.#updateInternalState(destination, state.uid, true); - if (destination.rotation !== undefined) { - this._initialRotation = destination.rotation; - } - if (destination.dest) { - this._initialBookmark = JSON.stringify(destination.dest); - this._destination.page = null; - } else if (destination.hash) { - this._initialBookmark = destination.hash; - } else if (destination.page) { - this._initialBookmark = `page=${destination.page}`; - } - } - reset() { - if (this._initialized) { - this.#pageHide(); - this._initialized = false; - this.#unbindEvents(); - } - if (this._updateViewareaTimeout) { - clearTimeout(this._updateViewareaTimeout); - this._updateViewareaTimeout = null; - } - this._initialBookmark = null; - this._initialRotation = null; - } - push({ - namedDest = null, - explicitDest, - pageNumber - }) { - if (!this._initialized) { - return; - } - if (namedDest && typeof namedDest !== "string") { - console.error("PDFHistory.push: " + `"${namedDest}" is not a valid namedDest parameter.`); - return; - } else if (!Array.isArray(explicitDest)) { - console.error("PDFHistory.push: " + `"${explicitDest}" is not a valid explicitDest parameter.`); - return; - } else if (!this.#isValidPage(pageNumber)) { - if (pageNumber !== null || this._destination) { - console.error("PDFHistory.push: " + `"${pageNumber}" is not a valid pageNumber parameter.`); - return; - } - } - const hash = namedDest || JSON.stringify(explicitDest); - if (!hash) { - return; - } - let forceReplace = false; - if (this._destination && (isDestHashesEqual(this._destination.hash, hash) || isDestArraysEqual(this._destination.dest, explicitDest))) { - if (this._destination.page) { - return; - } - forceReplace = true; - } - if (this._popStateInProgress && !forceReplace) { - return; - } - this.#pushOrReplaceState({ - dest: explicitDest, - hash, - page: pageNumber, - rotation: this.linkService.rotation - }, forceReplace); - if (!this._popStateInProgress) { - this._popStateInProgress = true; - Promise.resolve().then(() => { - this._popStateInProgress = false; - }); - } - } - pushPage(pageNumber) { - if (!this._initialized) { - return; - } - if (!this.#isValidPage(pageNumber)) { - console.error(`PDFHistory.pushPage: "${pageNumber}" is not a valid page number.`); - return; - } - if (this._destination?.page === pageNumber) { - return; - } - if (this._popStateInProgress) { - return; - } - this.#pushOrReplaceState({ - dest: null, - hash: `page=${pageNumber}`, - page: pageNumber, - rotation: this.linkService.rotation - }); - if (!this._popStateInProgress) { - this._popStateInProgress = true; - Promise.resolve().then(() => { - this._popStateInProgress = false; - }); - } - } - pushCurrentPosition() { - if (!this._initialized || this._popStateInProgress) { - return; - } - this.#tryPushCurrentPosition(); - } - back() { - if (!this._initialized || this._popStateInProgress) { - return; - } - const state = window.history.state; - if (this.#isValidState(state) && state.uid > 0) { - window.history.back(); - } - } - forward() { - if (!this._initialized || this._popStateInProgress) { - return; - } - const state = window.history.state; - if (this.#isValidState(state) && state.uid < this._maxUid) { - window.history.forward(); - } - } - get popStateInProgress() { - return this._initialized && (this._popStateInProgress || this._blockHashChange > 0); - } - get initialBookmark() { - return this._initialized ? this._initialBookmark : null; - } - get initialRotation() { - return this._initialized ? this._initialRotation : null; - } - #pushOrReplaceState(destination, forceReplace = false) { - const shouldReplace = forceReplace || !this._destination; - const newState = { - fingerprint: this._fingerprint, - uid: shouldReplace ? this._uid : this._uid + 1, - destination - }; - this.#updateInternalState(destination, newState.uid); - let newUrl; - if (this._updateUrl && destination?.hash) { - const baseUrl = document.location.href.split("#", 1)[0]; - if (!baseUrl.startsWith("file://")) { - newUrl = `${baseUrl}#${destination.hash}`; - } - } - if (shouldReplace) { - window.history.replaceState(newState, "", newUrl); - } else { - window.history.pushState(newState, "", newUrl); - } - } - #tryPushCurrentPosition(temporary = false) { - if (!this._position) { - return; - } - let position = this._position; - if (temporary) { - position = Object.assign(Object.create(null), this._position); - position.temporary = true; - } - if (!this._destination) { - this.#pushOrReplaceState(position); - return; - } - if (this._destination.temporary) { - this.#pushOrReplaceState(position, true); - return; - } - if (this._destination.hash === position.hash) { - return; - } - if (!this._destination.page && (POSITION_UPDATED_THRESHOLD <= 0 || this._numPositionUpdates <= POSITION_UPDATED_THRESHOLD)) { - return; - } - let forceReplace = false; - if (this._destination.page >= position.first && this._destination.page <= position.page) { - if (this._destination.dest !== undefined || !this._destination.first) { - return; - } - forceReplace = true; - } - this.#pushOrReplaceState(position, forceReplace); - } - #isValidPage(val) { - return Number.isInteger(val) && val > 0 && val <= this.linkService.pagesCount; - } - #isValidState(state, checkReload = false) { - if (!state) { - return false; - } - if (state.fingerprint !== this._fingerprint) { - if (checkReload) { - if (typeof state.fingerprint !== "string" || state.fingerprint.length !== this._fingerprint.length) { - return false; - } - const [perfEntry] = performance.getEntriesByType("navigation"); - if (perfEntry?.type !== "reload") { - return false; - } - } else { - return false; - } - } - if (!Number.isInteger(state.uid) || state.uid < 0) { - return false; - } - if (state.destination === null || typeof state.destination !== "object") { - return false; - } - return true; - } - #updateInternalState(destination, uid, removeTemporary = false) { - if (this._updateViewareaTimeout) { - clearTimeout(this._updateViewareaTimeout); - this._updateViewareaTimeout = null; - } - if (removeTemporary && destination?.temporary) { - delete destination.temporary; - } - this._destination = destination; - this._uid = uid; - this._maxUid = Math.max(this._maxUid, uid); - this._numPositionUpdates = 0; - } - #parseCurrentHash(checkNameddest = false) { - const hash = unescape(getCurrentHash()).substring(1); - const params = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.parseQueryString)(hash); - const nameddest = params.get("nameddest") || ""; - let page = params.get("page") | 0; - if (!this.#isValidPage(page) || checkNameddest && nameddest.length > 0) { - page = null; - } - return { - hash, - page, - rotation: this.linkService.rotation - }; - } - #updateViewarea({ - location - }) { - if (this._updateViewareaTimeout) { - clearTimeout(this._updateViewareaTimeout); - this._updateViewareaTimeout = null; - } - this._position = { - hash: location.pdfOpenParams.substring(1), - page: this.linkService.page, - first: location.pageNumber, - rotation: location.rotation - }; - if (this._popStateInProgress) { - return; - } - if (POSITION_UPDATED_THRESHOLD > 0 && this._isPagesLoaded && this._destination && !this._destination.page) { - this._numPositionUpdates++; - } - if (UPDATE_VIEWAREA_TIMEOUT > 0) { - this._updateViewareaTimeout = setTimeout(() => { - if (!this._popStateInProgress) { - this.#tryPushCurrentPosition(true); - } - this._updateViewareaTimeout = null; - }, UPDATE_VIEWAREA_TIMEOUT); - } - } - #popState({ - state - }) { - const newHash = getCurrentHash(), - hashChanged = this._currentHash !== newHash; - this._currentHash = newHash; - if (!state) { - this._uid++; - const { - hash, - page, - rotation - } = this.#parseCurrentHash(); - this.#pushOrReplaceState({ - hash, - page, - rotation - }, true); - return; - } - if (!this.#isValidState(state)) { - return; - } - this._popStateInProgress = true; - if (hashChanged) { - this._blockHashChange++; - (0,_event_utils_js__WEBPACK_IMPORTED_MODULE_1__.waitOnEventOrTimeout)({ - target: window, - name: "hashchange", - delay: HASH_CHANGE_TIMEOUT - }).then(() => { - this._blockHashChange--; - }); - } - const destination = state.destination; - this.#updateInternalState(destination, state.uid, true); - if ((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isValidRotation)(destination.rotation)) { - this.linkService.rotation = destination.rotation; - } - if (destination.dest) { - this.linkService.goToDestination(destination.dest); - } else if (destination.hash) { - this.linkService.setHash(destination.hash); - } else if (destination.page) { - this.linkService.page = destination.page; - } - Promise.resolve().then(() => { - this._popStateInProgress = false; - }); - } - #pageHide() { - if (!this._destination || this._destination.temporary) { - this.#tryPushCurrentPosition(); - } - } - #bindEvents() { - if (this.#eventAbortController) { - return; - } - this.#eventAbortController = new AbortController(); - const { - signal - } = this.#eventAbortController; - this.eventBus._on("updateviewarea", this.#updateViewarea.bind(this), { - signal - }); - window.addEventListener("popstate", this.#popState.bind(this), { - signal - }); - window.addEventListener("pagehide", this.#pageHide.bind(this), { - signal - }); - } - #unbindEvents() { - this.#eventAbortController?.abort(); - this.#eventAbortController = null; - } -} -function isDestHashesEqual(destHash, pushHash) { - if (typeof destHash !== "string" || typeof pushHash !== "string") { - return false; - } - if (destHash === pushHash) { - return true; - } - const nameddest = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.parseQueryString)(destHash).get("nameddest"); - if (nameddest === pushHash) { - return true; - } - return false; -} -function isDestArraysEqual(firstDest, secondDest) { - function isEntryEqual(first, second) { - if (typeof first !== typeof second) { - return false; - } - if (Array.isArray(first) || Array.isArray(second)) { - return false; - } - if (first !== null && typeof first === "object" && second !== null) { - if (Object.keys(first).length !== Object.keys(second).length) { - return false; - } - for (const key in first) { - if (!isEntryEqual(first[key], second[key])) { - return false; - } - } - return true; - } - return first === second || Number.isNaN(first) && Number.isNaN(second); - } - if (!(Array.isArray(firstDest) && Array.isArray(secondDest))) { - return false; - } - if (firstDest.length !== secondDest.length) { - return false; - } - for (let i = 0, ii = firstDest.length; i < ii; i++) { - if (!isEntryEqual(firstDest[i], secondDest[i])) { - return false; - } - } - return true; -} - - -/***/ }), - -/***/ 4275: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFLayerViewer: () => (/* binding */ PDFLayerViewer) -/* harmony export */ }); -/* harmony import */ var _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2961); - -class PDFLayerViewer extends _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__.BaseTreeViewer { - constructor(options) { - super(options); - this.eventBus._on("optionalcontentconfigchanged", evt => { - this.#updateLayers(evt.promise); - }); - this.eventBus._on("resetlayers", () => { - this.#updateLayers(); - }); - this.eventBus._on("togglelayerstree", this._toggleAllTreeItems.bind(this)); - } - reset() { - super.reset(); - this._optionalContentConfig = null; - this._optionalContentHash = null; - } - _dispatchEvent(layersCount) { - this.eventBus.dispatch("layersloaded", { - source: this, - layersCount - }); - } - _bindLink(element, { - groupId, - input - }) { - const setVisibility = () => { - this._optionalContentConfig.setVisibility(groupId, input.checked); - this._optionalContentHash = this._optionalContentConfig.getHash(); - this.eventBus.dispatch("optionalcontentconfig", { - source: this, - promise: Promise.resolve(this._optionalContentConfig) - }); - }; - element.onclick = evt => { - if (evt.target === input) { - setVisibility(); - return true; - } else if (evt.target !== element) { - return true; - } - input.checked = !input.checked; - setVisibility(); - return false; - }; - } - async _setNestedName(element, { - name = null - }) { - if (typeof name === "string") { - element.textContent = this._normalizeTextContent(name); - return; - } - element.textContent = await this._l10n.get("pdfjs-additional-layers"); - element.style.fontStyle = "italic"; - } - _addToggleButton(div, { - name = null - }) { - super._addToggleButton(div, name === null); - } - _toggleAllTreeItems() { - if (!this._optionalContentConfig) { - return; - } - super._toggleAllTreeItems(); - } - render({ - optionalContentConfig, - pdfDocument - }) { - if (this._optionalContentConfig) { - this.reset(); - } - this._optionalContentConfig = optionalContentConfig || null; - this._pdfDocument = pdfDocument || null; - const groups = optionalContentConfig?.getOrder(); - if (!groups) { - this._dispatchEvent(0); - return; - } - this._optionalContentHash = optionalContentConfig.getHash(); - const fragment = document.createDocumentFragment(), - queue = [{ - parent: fragment, - groups - }]; - let layersCount = 0, - hasAnyNesting = false; - while (queue.length > 0) { - const levelData = queue.shift(); - for (const groupId of levelData.groups) { - const div = document.createElement("div"); - div.className = "treeItem"; - const element = document.createElement("a"); - div.append(element); - if (typeof groupId === "object") { - hasAnyNesting = true; - this._addToggleButton(div, groupId); - this._setNestedName(element, groupId); - const itemsDiv = document.createElement("div"); - itemsDiv.className = "treeItems"; - div.append(itemsDiv); - queue.push({ - parent: itemsDiv, - groups: groupId.order - }); - } else { - const group = optionalContentConfig.getGroup(groupId); - const input = document.createElement("input"); - this._bindLink(element, { - groupId, - input - }); - input.type = "checkbox"; - input.checked = group.visible; - const label = document.createElement("label"); - label.textContent = this._normalizeTextContent(group.name); - label.append(input); - element.append(label); - layersCount++; - } - levelData.parent.append(div); - } - } - this._finishRendering(fragment, layersCount, hasAnyNesting); - } - async #updateLayers(promise = null) { - if (!this._optionalContentConfig) { - return; - } - const pdfDocument = this._pdfDocument; - const optionalContentConfig = await (promise || pdfDocument.getOptionalContentConfig({ - intent: "display" - })); - if (pdfDocument !== this._pdfDocument) { - return; - } - if (promise) { - if (optionalContentConfig.getHash() === this._optionalContentHash) { - return; - } - } else { - this.eventBus.dispatch("optionalcontentconfig", { - source: this, - promise: Promise.resolve(optionalContentConfig) - }); - } - this.render({ - optionalContentConfig, - pdfDocument: this._pdfDocument - }); - } -} - - -/***/ }), - -/***/ 787: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ LinkTarget: () => (/* binding */ LinkTarget), -/* harmony export */ PDFLinkService: () => (/* binding */ PDFLinkService), -/* harmony export */ SimpleLinkService: () => (/* binding */ SimpleLinkService) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); - -const DEFAULT_LINK_REL = "noopener noreferrer nofollow"; -const LinkTarget = { - NONE: 0, - SELF: 1, - BLANK: 2, - PARENT: 3, - TOP: 4 -}; -class PDFLinkService { - externalLinkEnabled = true; - constructor({ - eventBus, - externalLinkTarget = null, - externalLinkRel = null, - ignoreDestinationZoom = false - } = {}) { - this.eventBus = eventBus; - this.externalLinkTarget = externalLinkTarget; - this.externalLinkRel = externalLinkRel; - this._ignoreDestinationZoom = ignoreDestinationZoom; - this.baseUrl = null; - this.pdfDocument = null; - this.pdfViewer = null; - this.pdfHistory = null; - } - setDocument(pdfDocument, baseUrl = null) { - this.baseUrl = baseUrl; - this.pdfDocument = pdfDocument; - } - setViewer(pdfViewer) { - this.pdfViewer = pdfViewer; - } - setHistory(pdfHistory) { - this.pdfHistory = pdfHistory; - } - get pagesCount() { - return this.pdfDocument ? this.pdfDocument.numPages : 0; - } - get page() { - return this.pdfDocument ? this.pdfViewer.currentPageNumber : 1; - } - set page(value) { - if (this.pdfDocument) { - this.pdfViewer.currentPageNumber = value; - } - } - get rotation() { - return this.pdfDocument ? this.pdfViewer.pagesRotation : 0; - } - set rotation(value) { - if (this.pdfDocument) { - this.pdfViewer.pagesRotation = value; - } - } - get isInPresentationMode() { - return this.pdfDocument ? this.pdfViewer.isInPresentationMode : false; - } - async goToDestination(dest) { - if (!this.pdfDocument) { - return; - } - let namedDest, explicitDest, pageNumber; - if (typeof dest === "string") { - namedDest = dest; - explicitDest = await this.pdfDocument.getDestination(dest); - } else { - namedDest = null; - explicitDest = await dest; - } - if (!Array.isArray(explicitDest)) { - console.error(`goToDestination: "${explicitDest}" is not a valid destination array, for dest="${dest}".`); - return; - } - const [destRef] = explicitDest; - if (destRef && typeof destRef === "object") { - pageNumber = this.pdfDocument.cachedPageNumber(destRef); - if (!pageNumber) { - try { - pageNumber = (await this.pdfDocument.getPageIndex(destRef)) + 1; - } catch { - console.error(`goToDestination: "${destRef}" is not a valid page reference, for dest="${dest}".`); - return; - } - } - } else if (Number.isInteger(destRef)) { - pageNumber = destRef + 1; - } - if (!pageNumber || pageNumber < 1 || pageNumber > this.pagesCount) { - console.error(`goToDestination: "${pageNumber}" is not a valid page number, for dest="${dest}".`); - return; - } - if (this.pdfHistory) { - this.pdfHistory.pushCurrentPosition(); - this.pdfHistory.push({ - namedDest, - explicitDest, - pageNumber - }); - } - this.pdfViewer.scrollPageIntoView({ - pageNumber, - destArray: explicitDest, - ignoreDestinationZoom: this._ignoreDestinationZoom - }); - } - goToPage(val) { - if (!this.pdfDocument) { - return; - } - const pageNumber = typeof val === "string" && this.pdfViewer.pageLabelToPageNumber(val) || val | 0; - if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.pagesCount)) { - console.error(`PDFLinkService.goToPage: "${val}" is not a valid page.`); - return; - } - if (this.pdfHistory) { - this.pdfHistory.pushCurrentPosition(); - this.pdfHistory.pushPage(pageNumber); - } - this.pdfViewer.scrollPageIntoView({ - pageNumber - }); - } - addLinkAttributes(link, url, newWindow = false) { - if (!url || typeof url !== "string") { - throw new Error('A valid "url" parameter must provided.'); - } - const target = newWindow ? LinkTarget.BLANK : this.externalLinkTarget, - rel = this.externalLinkRel; - if (this.externalLinkEnabled) { - link.href = link.title = url; - } else { - link.href = ""; - link.title = `Disabled: ${url}`; - link.onclick = () => false; - } - let targetStr = ""; - switch (target) { - case LinkTarget.NONE: - break; - case LinkTarget.SELF: - targetStr = "_self"; - break; - case LinkTarget.BLANK: - targetStr = "_blank"; - break; - case LinkTarget.PARENT: - targetStr = "_parent"; - break; - case LinkTarget.TOP: - targetStr = "_top"; - break; - } - link.target = targetStr; - link.rel = typeof rel === "string" ? rel : DEFAULT_LINK_REL; - } - getDestinationHash(dest) { - if (typeof dest === "string") { - if (dest.length > 0) { - return this.getAnchorUrl("#" + escape(dest)); - } - } else if (Array.isArray(dest)) { - const str = JSON.stringify(dest); - if (str.length > 0) { - return this.getAnchorUrl("#" + escape(str)); - } - } - return this.getAnchorUrl(""); - } - getAnchorUrl(anchor) { - return this.baseUrl ? this.baseUrl + anchor : anchor; - } - setHash(hash) { - if (!this.pdfDocument) { - return; - } - let pageNumber, dest; - if (hash.includes("=")) { - const params = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.parseQueryString)(hash); - if (params.has("search")) { - const query = params.get("search").replaceAll('"', ""), - phrase = params.get("phrase") === "true"; - this.eventBus.dispatch("findfromurlhash", { - source: this, - query: phrase ? query : query.match(/\S+/g) - }); - } - if (params.has("page")) { - pageNumber = params.get("page") | 0 || 1; - } - if (params.has("zoom")) { - const zoomArgs = params.get("zoom").split(","); - const zoomArg = zoomArgs[0]; - const zoomArgNumber = parseFloat(zoomArg); - if (!zoomArg.includes("Fit")) { - dest = [null, { - name: "XYZ" - }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null, zoomArgs.length > 2 ? zoomArgs[2] | 0 : null, zoomArgNumber ? zoomArgNumber / 100 : zoomArg]; - } else if (zoomArg === "Fit" || zoomArg === "FitB") { - dest = [null, { - name: zoomArg - }]; - } else if (zoomArg === "FitH" || zoomArg === "FitBH" || zoomArg === "FitV" || zoomArg === "FitBV") { - dest = [null, { - name: zoomArg - }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null]; - } else if (zoomArg === "FitR") { - if (zoomArgs.length !== 5) { - console.error('PDFLinkService.setHash: Not enough parameters for "FitR".'); - } else { - dest = [null, { - name: zoomArg - }, zoomArgs[1] | 0, zoomArgs[2] | 0, zoomArgs[3] | 0, zoomArgs[4] | 0]; - } - } else { - console.error(`PDFLinkService.setHash: "${zoomArg}" is not a valid zoom value.`); - } - } - if (dest) { - this.pdfViewer.scrollPageIntoView({ - pageNumber: pageNumber || this.page, - destArray: dest, - allowNegativeOffset: true - }); - } else if (pageNumber) { - this.page = pageNumber; - } - if (params.has("pagemode")) { - this.eventBus.dispatch("pagemode", { - source: this, - mode: params.get("pagemode") - }); - } - if (params.has("nameddest")) { - this.goToDestination(params.get("nameddest")); - } - return; - } - dest = unescape(hash); - try { - dest = JSON.parse(dest); - if (!Array.isArray(dest)) { - dest = dest.toString(); - } - } catch {} - if (typeof dest === "string" || PDFLinkService.#isValidExplicitDest(dest)) { - this.goToDestination(dest); - return; - } - console.error(`PDFLinkService.setHash: "${unescape(hash)}" is not a valid destination.`); - } - executeNamedAction(action) { - if (!this.pdfDocument) { - return; - } - switch (action) { - case "GoBack": - this.pdfHistory?.back(); - break; - case "GoForward": - this.pdfHistory?.forward(); - break; - case "NextPage": - this.pdfViewer.nextPage(); - break; - case "PrevPage": - this.pdfViewer.previousPage(); - break; - case "LastPage": - this.page = this.pagesCount; - break; - case "FirstPage": - this.page = 1; - break; - default: - break; - } - this.eventBus.dispatch("namedaction", { - source: this, - action - }); - } - async executeSetOCGState(action) { - if (!this.pdfDocument) { - return; - } - const pdfDocument = this.pdfDocument, - optionalContentConfig = await this.pdfViewer.optionalContentConfigPromise; - if (pdfDocument !== this.pdfDocument) { - return; - } - optionalContentConfig.setOCGState(action); - this.pdfViewer.optionalContentConfigPromise = Promise.resolve(optionalContentConfig); - } - static #isValidExplicitDest(dest) { - if (!Array.isArray(dest) || dest.length < 2) { - return false; - } - const [page, zoom, ...args] = dest; - if (!(typeof page === "object" && Number.isInteger(page?.num) && Number.isInteger(page?.gen)) && !Number.isInteger(page)) { - return false; - } - if (!(typeof zoom === "object" && typeof zoom?.name === "string")) { - return false; - } - let allowNull = true; - switch (zoom.name) { - case "XYZ": - if (args.length !== 3) { - return false; - } - break; - case "Fit": - case "FitB": - return args.length === 0; - case "FitH": - case "FitBH": - case "FitV": - case "FitBV": - if (args.length !== 1) { - return false; - } - break; - case "FitR": - if (args.length !== 4) { - return false; - } - allowNull = false; - break; - default: - return false; - } - for (const arg of args) { - if (!(typeof arg === "number" || allowNull && arg === null)) { - return false; - } - } - return true; - } -} -class SimpleLinkService extends PDFLinkService { - setDocument(pdfDocument, baseUrl = null) {} -} - - -/***/ }), - -/***/ 5514: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFOutlineViewer: () => (/* binding */ PDFOutlineViewer) -/* harmony export */ }); -/* harmony import */ var _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2961); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256); - - -class PDFOutlineViewer extends _base_tree_viewer_js__WEBPACK_IMPORTED_MODULE_0__.BaseTreeViewer { - constructor(options) { - super(options); - this.linkService = options.linkService; - this.downloadManager = options.downloadManager; - this.eventBus._on("toggleoutlinetree", this._toggleAllTreeItems.bind(this)); - this.eventBus._on("currentoutlineitem", this._currentOutlineItem.bind(this)); - this.eventBus._on("pagechanging", evt => { - this._currentPageNumber = evt.pageNumber; - }); - this.eventBus._on("pagesloaded", evt => { - this._isPagesLoaded = !!evt.pagesCount; - this._currentOutlineItemCapability?.resolve(this._isPagesLoaded); - }); - this.eventBus._on("sidebarviewchanged", evt => { - this._sidebarView = evt.view; - }); - } - reset() { - super.reset(); - this._outline = null; - this._pageNumberToDestHashCapability = null; - this._currentPageNumber = 1; - this._isPagesLoaded = null; - this._currentOutlineItemCapability?.resolve(false); - this._currentOutlineItemCapability = null; - } - _dispatchEvent(outlineCount) { - this._currentOutlineItemCapability = Promise.withResolvers(); - if (outlineCount === 0 || this._pdfDocument?.loadingParams.disableAutoFetch) { - this._currentOutlineItemCapability.resolve(false); - } else if (this._isPagesLoaded !== null) { - this._currentOutlineItemCapability.resolve(this._isPagesLoaded); - } - this.eventBus.dispatch("outlineloaded", { - source: this, - outlineCount, - currentOutlineItemPromise: this._currentOutlineItemCapability.promise - }); - } - _bindLink(element, { - url, - newWindow, - action, - attachment, - dest, - setOCGState - }) { - const { - linkService - } = this; - if (url) { - linkService.addLinkAttributes(element, url, newWindow); - return; - } - if (action) { - element.href = linkService.getAnchorUrl(""); - element.onclick = () => { - linkService.executeNamedAction(action); - return false; - }; - return; - } - if (attachment) { - element.href = linkService.getAnchorUrl(""); - element.onclick = () => { - this.downloadManager.openOrDownloadData(attachment.content, attachment.filename); - return false; - }; - return; - } - if (setOCGState) { - element.href = linkService.getAnchorUrl(""); - element.onclick = () => { - linkService.executeSetOCGState(setOCGState); - return false; - }; - return; - } - element.href = linkService.getDestinationHash(dest); - element.onclick = evt => { - this._updateCurrentTreeItem(evt.target.parentNode); - if (dest) { - linkService.goToDestination(dest); - } - return false; - }; - } - _setStyles(element, { - bold, - italic - }) { - if (bold) { - element.style.fontWeight = "bold"; - } - if (italic) { - element.style.fontStyle = "italic"; - } - } - _addToggleButton(div, { - count, - items - }) { - let hidden = false; - if (count < 0) { - let totalCount = items.length; - if (totalCount > 0) { - const queue = [...items]; - while (queue.length > 0) { - const { - count: nestedCount, - items: nestedItems - } = queue.shift(); - if (nestedCount > 0 && nestedItems.length > 0) { - totalCount += nestedItems.length; - queue.push(...nestedItems); - } - } - } - if (Math.abs(count) === totalCount) { - hidden = true; - } - } - super._addToggleButton(div, hidden); - } - _toggleAllTreeItems() { - if (!this._outline) { - return; - } - super._toggleAllTreeItems(); - } - render({ - outline, - pdfDocument - }) { - if (this._outline) { - this.reset(); - } - this._outline = outline || null; - this._pdfDocument = pdfDocument || null; - if (!outline) { - this._dispatchEvent(0); - return; - } - const fragment = document.createDocumentFragment(); - const queue = [{ - parent: fragment, - items: outline - }]; - let outlineCount = 0, - hasAnyNesting = false; - while (queue.length > 0) { - const levelData = queue.shift(); - for (const item of levelData.items) { - const div = document.createElement("div"); - div.className = "treeItem"; - const element = document.createElement("a"); - this._bindLink(element, item); - this._setStyles(element, item); - element.textContent = this._normalizeTextContent(item.title); - div.append(element); - if (item.items.length > 0) { - hasAnyNesting = true; - this._addToggleButton(div, item); - const itemsDiv = document.createElement("div"); - itemsDiv.className = "treeItems"; - div.append(itemsDiv); - queue.push({ - parent: itemsDiv, - items: item.items - }); - } - levelData.parent.append(div); - outlineCount++; - } - } - this._finishRendering(fragment, outlineCount, hasAnyNesting); - } - async _currentOutlineItem() { - if (!this._isPagesLoaded) { - throw new Error("_currentOutlineItem: All pages have not been loaded."); - } - if (!this._outline || !this._pdfDocument) { - return; - } - const pageNumberToDestHash = await this._getPageNumberToDestHash(this._pdfDocument); - if (!pageNumberToDestHash) { - return; - } - this._updateCurrentTreeItem(null); - if (this._sidebarView !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SidebarView.OUTLINE) { - return; - } - for (let i = this._currentPageNumber; i > 0; i--) { - const destHash = pageNumberToDestHash.get(i); - if (!destHash) { - continue; - } - const linkElement = this.container.querySelector(`a[href="${destHash}"]`); - if (!linkElement) { - continue; - } - this._scrollToCurrentTreeItem(linkElement.parentNode); - break; - } - } - async _getPageNumberToDestHash(pdfDocument) { - if (this._pageNumberToDestHashCapability) { - return this._pageNumberToDestHashCapability.promise; - } - this._pageNumberToDestHashCapability = Promise.withResolvers(); - const pageNumberToDestHash = new Map(), - pageNumberNesting = new Map(); - const queue = [{ - nesting: 0, - items: this._outline - }]; - while (queue.length > 0) { - const levelData = queue.shift(), - currentNesting = levelData.nesting; - for (const { - dest, - items - } of levelData.items) { - let explicitDest, pageNumber; - if (typeof dest === "string") { - explicitDest = await pdfDocument.getDestination(dest); - if (pdfDocument !== this._pdfDocument) { - return null; - } - } else { - explicitDest = dest; - } - if (Array.isArray(explicitDest)) { - const [destRef] = explicitDest; - if (destRef && typeof destRef === "object") { - pageNumber = pdfDocument.cachedPageNumber(destRef); - } else if (Number.isInteger(destRef)) { - pageNumber = destRef + 1; - } - if (Number.isInteger(pageNumber) && (!pageNumberToDestHash.has(pageNumber) || currentNesting > pageNumberNesting.get(pageNumber))) { - const destHash = this.linkService.getDestinationHash(dest); - pageNumberToDestHash.set(pageNumber, destHash); - pageNumberNesting.set(pageNumber, currentNesting); - } - } - if (items.length > 0) { - queue.push({ - nesting: currentNesting + 1, - items - }); - } - } - } - this._pageNumberToDestHashCapability.resolve(pageNumberToDestHash.size > 0 ? pageNumberToDestHash : null); - return this._pageNumberToDestHashCapability.promise; - } -} - - -/***/ }), - -/***/ 9966: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFPageView: () => (/* binding */ PDFPageView) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256); -/* harmony import */ var _annotation_editor_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(283); -/* harmony import */ var _annotation_layer_builder_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2707); -/* harmony import */ var _app_options_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9840); -/* harmony import */ var _draw_layer_builder_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(3088); -/* harmony import */ var web_null_l10n__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(410); -/* harmony import */ var _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(787); -/* harmony import */ var _struct_tree_layer_builder_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(6698); -/* harmony import */ var _text_accessibility_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(5860); -/* harmony import */ var _text_highlighter_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(2027); -/* harmony import */ var _text_layer_builder_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(7765); -/* harmony import */ var _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(2973); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _annotation_editor_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__, _annotation_layer_builder_js__WEBPACK_IMPORTED_MODULE_3__, _draw_layer_builder_js__WEBPACK_IMPORTED_MODULE_5__, web_null_l10n__WEBPACK_IMPORTED_MODULE_6__, _text_layer_builder_js__WEBPACK_IMPORTED_MODULE_10__, _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_11__]); -([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _annotation_editor_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__, _annotation_layer_builder_js__WEBPACK_IMPORTED_MODULE_3__, _draw_layer_builder_js__WEBPACK_IMPORTED_MODULE_5__, web_null_l10n__WEBPACK_IMPORTED_MODULE_6__, _text_layer_builder_js__WEBPACK_IMPORTED_MODULE_10__, _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_11__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__); - - - - - - - - - - - - - -const DEFAULT_LAYER_PROPERTIES = null; -const LAYERS_ORDER = new Map([["canvasWrapper", 0], ["textLayer", 1], ["annotationLayer", 2], ["annotationEditorLayer", 3], ["xfaLayer", 3]]); -class PDFPageView { - #annotationMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS; - #hasRestrictedScaling = false; - #layerProperties = null; - #loadingId = null; - #previousRotation = null; - #renderError = null; - #renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.INITIAL; - #textLayerMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE; - #useThumbnailCanvas = { - directDrawing: true, - initialOptionalContent: true, - regularAnnotations: true - }; - #viewportMap = new WeakMap(); - #layers = [null, null, null, null]; - constructor(options) { - const container = options.container; - const defaultViewport = options.defaultViewport; - this.id = options.id; - this.renderingId = "page" + this.id; - this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES; - this.pdfPage = null; - this.pageLabel = null; - this.rotation = 0; - this.scale = options.scale || _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE; - this.viewport = defaultViewport; - this.pdfPageRotate = defaultViewport.rotation; - this._optionalContentConfigPromise = options.optionalContentConfigPromise || null; - this.#textLayerMode = options.textLayerMode ?? _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE; - this.#annotationMode = options.annotationMode ?? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS; - this.imageResourcesPath = options.imageResourcesPath || ""; - this.maxCanvasPixels = options.maxCanvasPixels ?? _app_options_js__WEBPACK_IMPORTED_MODULE_4__.AppOptions.get("maxCanvasPixels"); - this.pageColors = options.pageColors || null; - this.eventBus = options.eventBus; - this.renderingQueue = options.renderingQueue; - this.l10n = options.l10n; - this.l10n ||= new web_null_l10n__WEBPACK_IMPORTED_MODULE_6__.GenericL10n(); - this.renderTask = null; - this.resume = null; - this._isStandalone = !this.renderingQueue?.hasViewer(); - this._container = container; - this._annotationCanvasMap = null; - this.annotationLayer = null; - this.annotationEditorLayer = null; - this.textLayer = null; - this.zoomLayer = null; - this.xfaLayer = null; - this.structTreeLayer = null; - this.drawLayer = null; - const div = document.createElement("div"); - div.className = "page"; - div.setAttribute("data-page-number", this.id); - div.setAttribute("role", "region"); - div.setAttribute("data-l10n-id", "pdfjs-page-landmark"); - div.setAttribute("data-l10n-args", JSON.stringify({ - page: this.id - })); - this.div = div; - this.#setDimensions(); - container?.append(div); - if (this._isStandalone) { - container?.style.setProperty("--scale-factor", this.scale * pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS); - const { - optionalContentConfigPromise - } = options; - if (optionalContentConfigPromise) { - optionalContentConfigPromise.then(optionalContentConfig => { - if (optionalContentConfigPromise !== this._optionalContentConfigPromise) { - return; - } - this.#useThumbnailCanvas.initialOptionalContent = optionalContentConfig.hasInitialVisibility; - }); - } - if (!options.l10n) { - this.l10n.translate(this.div); - } - } - } - #addLayer(div, name) { - const pos = LAYERS_ORDER.get(name); - const oldDiv = this.#layers[pos]; - this.#layers[pos] = div; - if (oldDiv) { - oldDiv.replaceWith(div); - return; - } - for (let i = pos - 1; i >= 0; i--) { - const layer = this.#layers[i]; - if (layer) { - layer.after(div); - return; - } - } - this.div.prepend(div); - } - get renderingState() { - return this.#renderingState; - } - set renderingState(state) { - if (state === this.#renderingState) { - return; - } - this.#renderingState = state; - if (this.#loadingId) { - clearTimeout(this.#loadingId); - this.#loadingId = null; - } - switch (state) { - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.PAUSED: - this.div.classList.remove("loading"); - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.RUNNING: - this.div.classList.add("loadingIcon"); - this.#loadingId = setTimeout(() => { - this.div.classList.add("loading"); - this.#loadingId = null; - }, 0); - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.INITIAL: - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED: - this.div.classList.remove("loadingIcon", "loading"); - break; - } - } - #setDimensions() { - const { - viewport - } = this; - if (this.pdfPage) { - if (this.#previousRotation === viewport.rotation) { - return; - } - this.#previousRotation = viewport.rotation; - } - (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.setLayerDimensions)(this.div, viewport, true, false); - } - setPdfPage(pdfPage) { - if (this._isStandalone && (this.pageColors?.foreground === "CanvasText" || this.pageColors?.background === "Canvas")) { - this._container?.style.setProperty("--hcm-highlight-filter", pdfPage.filterFactory.addHighlightHCMFilter("highlight", "CanvasText", "Canvas", "HighlightText", "Highlight")); - this._container?.style.setProperty("--hcm-highlight-selected-filter", pdfPage.filterFactory.addHighlightHCMFilter("highlight_selected", "CanvasText", "Canvas", "HighlightText", "Highlight")); - } - this.pdfPage = pdfPage; - this.pdfPageRotate = pdfPage.rotate; - const totalRotation = (this.rotation + this.pdfPageRotate) % 360; - this.viewport = pdfPage.getViewport({ - scale: this.scale * pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS, - rotation: totalRotation - }); - this.#setDimensions(); - this.reset(); - } - destroy() { - this.reset(); - this.pdfPage?.cleanup(); - } - get _textHighlighter() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "_textHighlighter", new _text_highlighter_js__WEBPACK_IMPORTED_MODULE_12__.TextHighlighter({ - pageIndex: this.id - 1, - eventBus: this.eventBus, - findController: this.#layerProperties.findController - })); - } - async #renderAnnotationLayer() { - let error = null; - try { - await this.annotationLayer.render(this.viewport, "display"); - } catch (ex) { - console.error(`#renderAnnotationLayer: "${ex}".`); - error = ex; - } finally { - this.eventBus.dispatch("annotationlayerrendered", { - source: this, - pageNumber: this.id, - error - }); - } - } - async #renderAnnotationEditorLayer() { - let error = null; - try { - await this.annotationEditorLayer.render(this.viewport, "display"); - } catch (ex) { - console.error(`#renderAnnotationEditorLayer: "${ex}".`); - error = ex; - } finally { - this.eventBus.dispatch("annotationeditorlayerrendered", { - source: this, - pageNumber: this.id, - error - }); - - // [Custom] annotationLayer有时候会重建,所以多一层postMesseage保证朦层渲染 - window.parent.postMessage({pageNum: this.id - 1}, '*'); - } - } - async #renderDrawLayer() { - try { - await this.drawLayer.render("display"); - } catch (ex) { - console.error(`#renderDrawLayer: "${ex}".`); - } - } - async #renderXfaLayer() { - let error = null; - try { - const result = await this.xfaLayer.render(this.viewport, "display"); - if (result?.textDivs && this._textHighlighter) { - this.#buildXfaTextContentItems(result.textDivs); - } - } catch (ex) { - console.error(`#renderXfaLayer: "${ex}".`); - error = ex; - } finally { - if (this.xfaLayer?.div) { - this.l10n.pause(); - this.#addLayer(this.xfaLayer.div, "xfaLayer"); - this.l10n.resume(); - } - this.eventBus.dispatch("xfalayerrendered", { - source: this, - pageNumber: this.id, - error - }); - } - } - async #renderTextLayer() { - const { - pdfPage, - textLayer, - viewport - } = this; - if (!textLayer) { - return; - } - let error = null; - try { - if (!textLayer.renderingDone) { - const readableStream = pdfPage.streamTextContent({ - includeMarkedContent: true, - disableNormalization: true - }); - textLayer.setTextContentSource(readableStream); - } - await textLayer.render(viewport); - } catch (ex) { - if (ex instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AbortException) { - return; - } - console.error(`#renderTextLayer: "${ex}".`); - error = ex; - } - this.eventBus.dispatch("textlayerrendered", { - source: this, - pageNumber: this.id, - numTextDivs: textLayer.numTextDivs, - error - }); - this.#renderStructTreeLayer(); - } - async #renderStructTreeLayer() { - if (!this.textLayer) { - return; - } - this.structTreeLayer ||= new _struct_tree_layer_builder_js__WEBPACK_IMPORTED_MODULE_8__.StructTreeLayerBuilder(); - const tree = await (!this.structTreeLayer.renderingDone ? this.pdfPage.getStructTree() : null); - const treeDom = this.structTreeLayer?.render(tree); - if (treeDom) { - this.l10n.pause(); - this.canvas?.append(treeDom); - this.l10n.resume(); - } - this.structTreeLayer?.show(); - } - async #buildXfaTextContentItems(textDivs) { - const text = await this.pdfPage.getTextContent(); - const items = []; - for (const item of text.items) { - items.push(item.str); - } - this._textHighlighter.setTextMapping(textDivs, items); - this._textHighlighter.enable(); - } - _resetZoomLayer(removeFromDOM = false) { - if (!this.zoomLayer) { - return; - } - const zoomLayerCanvas = this.zoomLayer.firstChild; - this.#viewportMap.delete(zoomLayerCanvas); - zoomLayerCanvas.width = 0; - zoomLayerCanvas.height = 0; - if (removeFromDOM) { - this.zoomLayer.remove(); - } - this.zoomLayer = null; - } - reset({ - keepZoomLayer = false, - keepAnnotationLayer = false, - keepAnnotationEditorLayer = false, - keepXfaLayer = false, - keepTextLayer = false - } = {}) { - this.cancelRendering({ - keepAnnotationLayer, - keepAnnotationEditorLayer, - keepXfaLayer, - keepTextLayer - }); - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.INITIAL; - const div = this.div; - const childNodes = div.childNodes, - zoomLayerNode = keepZoomLayer && this.zoomLayer || null, - annotationLayerNode = keepAnnotationLayer && this.annotationLayer?.div || null, - annotationEditorLayerNode = keepAnnotationEditorLayer && this.annotationEditorLayer?.div || null, - xfaLayerNode = keepXfaLayer && this.xfaLayer?.div || null, - textLayerNode = keepTextLayer && this.textLayer?.div || null; - for (let i = childNodes.length - 1; i >= 0; i--) { - const node = childNodes[i]; - switch (node) { - case zoomLayerNode: - case annotationLayerNode: - case annotationEditorLayerNode: - case xfaLayerNode: - case textLayerNode: - continue; - } - node.remove(); - const layerIndex = this.#layers.indexOf(node); - if (layerIndex >= 0) { - this.#layers[layerIndex] = null; - } - } - div.removeAttribute("data-loaded"); - if (annotationLayerNode) { - // this.annotationLayer.hide(); - } - if (annotationEditorLayerNode) { - this.annotationEditorLayer.hide(); - } - if (xfaLayerNode) { - this.xfaLayer.hide(); - } - if (textLayerNode) { - this.textLayer.hide(); - } - this.structTreeLayer?.hide(); - if (!zoomLayerNode) { - if (this.canvas) { - this.#viewportMap.delete(this.canvas); - this.canvas.width = 0; - this.canvas.height = 0; - delete this.canvas; - } - this._resetZoomLayer(); - } - } - update({ - scale = 0, - rotation = null, - optionalContentConfigPromise = null, - drawingDelay = -1 - }) { - this.scale = scale || this.scale; - if (typeof rotation === "number") { - this.rotation = rotation; - } - if (optionalContentConfigPromise instanceof Promise) { - this._optionalContentConfigPromise = optionalContentConfigPromise; - optionalContentConfigPromise.then(optionalContentConfig => { - if (optionalContentConfigPromise !== this._optionalContentConfigPromise) { - return; - } - this.#useThumbnailCanvas.initialOptionalContent = optionalContentConfig.hasInitialVisibility; - }); - } - this.#useThumbnailCanvas.directDrawing = true; - const totalRotation = (this.rotation + this.pdfPageRotate) % 360; - this.viewport = this.viewport.clone({ - scale: this.scale * pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS, - rotation: totalRotation - }); - this.#setDimensions(); - if (this._isStandalone) { - this._container?.style.setProperty("--scale-factor", this.viewport.scale); - } - if (this.canvas) { - let onlyCssZoom = false; - if (this.#hasRestrictedScaling) { - if (this.maxCanvasPixels === 0) { - onlyCssZoom = true; - } else if (this.maxCanvasPixels > 0) { - const { - width, - height - } = this.viewport; - const { - sx, - sy - } = this.outputScale; - onlyCssZoom = (Math.floor(width) * sx | 0) * (Math.floor(height) * sy | 0) > this.maxCanvasPixels; - } - } - const postponeDrawing = !onlyCssZoom && drawingDelay >= 0 && drawingDelay < 1000; - if (postponeDrawing || onlyCssZoom) { - if (postponeDrawing && this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED) { - this.cancelRendering({ - keepZoomLayer: true, - keepAnnotationLayer: true, - keepAnnotationEditorLayer: true, - keepXfaLayer: true, - keepTextLayer: true, - cancelExtraDelay: drawingDelay - }); - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED; - this.#useThumbnailCanvas.directDrawing = false; - } - this.cssTransform({ - target: this.canvas, - redrawAnnotationLayer: true, - redrawAnnotationEditorLayer: true, - redrawXfaLayer: true, - redrawTextLayer: !postponeDrawing, - hideTextLayer: postponeDrawing - }); - if (postponeDrawing) { - return; - } - this.eventBus.dispatch("pagerendered", { - source: this, - pageNumber: this.id, - cssTransform: true, - timestamp: performance.now(), - error: this.#renderError - }); - return; - } - if (!this.zoomLayer && !this.canvas.hidden) { - this.zoomLayer = this.canvas.parentNode; - this.zoomLayer.style.position = "absolute"; - } - } - if (this.zoomLayer) { - this.cssTransform({ - target: this.zoomLayer.firstChild - }); - } - this.reset({ - keepZoomLayer: true, - keepAnnotationLayer: true, - keepAnnotationEditorLayer: true, - keepXfaLayer: true, - keepTextLayer: true - }); - } - cancelRendering({ - keepAnnotationLayer = false, - keepAnnotationEditorLayer = false, - keepXfaLayer = false, - keepTextLayer = false, - cancelExtraDelay = 0 - } = {}) { - if (this.renderTask) { - this.renderTask.cancel(cancelExtraDelay); - this.renderTask = null; - } - this.resume = null; - if (this.textLayer && (!keepTextLayer || !this.textLayer.div)) { - this.textLayer.cancel(); - this.textLayer = null; - } - if (this.structTreeLayer && !this.textLayer) { - this.structTreeLayer = null; - } - if (this.annotationLayer && (!keepAnnotationLayer || !this.annotationLayer.div)) { - this.annotationLayer.cancel(); - this.annotationLayer = null; - this._annotationCanvasMap = null; - } - if (this.annotationEditorLayer && (!keepAnnotationEditorLayer || !this.annotationEditorLayer.div)) { - if (this.drawLayer) { - this.drawLayer.cancel(); - this.drawLayer = null; - } - this.annotationEditorLayer.cancel(); - this.annotationEditorLayer = null; - } - if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) { - this.xfaLayer.cancel(); - this.xfaLayer = null; - this._textHighlighter?.disable(); - } - } - cssTransform({ - target, - redrawAnnotationLayer = false, - redrawAnnotationEditorLayer = false, - redrawXfaLayer = false, - redrawTextLayer = false, - hideTextLayer = false - }) { - if (!target.hasAttribute("zooming")) { - target.setAttribute("zooming", true); - const { - style - } = target; - style.width = style.height = ""; - } - const originalViewport = this.#viewportMap.get(target); - if (this.viewport !== originalViewport) { - const relativeRotation = this.viewport.rotation - originalViewport.rotation; - const absRotation = Math.abs(relativeRotation); - let scaleX = 1, - scaleY = 1; - if (absRotation === 90 || absRotation === 270) { - const { - width, - height - } = this.viewport; - scaleX = height / width; - scaleY = width / height; - } - target.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX}, ${scaleY})`; - } - if (redrawAnnotationLayer && this.annotationLayer) { - this.#renderAnnotationLayer(); - } - if (redrawAnnotationEditorLayer && this.annotationEditorLayer) { - if (this.drawLayer) { - this.#renderDrawLayer(); - } - this.#renderAnnotationEditorLayer(); - } - if (redrawXfaLayer && this.xfaLayer) { - this.#renderXfaLayer(); - } - if (this.textLayer) { - if (hideTextLayer) { - this.textLayer.hide(); - this.structTreeLayer?.hide(); - } else if (redrawTextLayer) { - this.#renderTextLayer(); - } - } - } - get width() { - return this.viewport.width; - } - get height() { - return this.viewport.height; - } - getPagePoint(x, y) { - return this.viewport.convertToPdfPoint(x, y); - } - async #finishRenderTask(renderTask, error = null) { - if (renderTask === this.renderTask) { - this.renderTask = null; - } - if (error instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.RenderingCancelledException) { - this.#renderError = null; - return; - } - this.#renderError = error; - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED; - this._resetZoomLayer(true); - this.#useThumbnailCanvas.regularAnnotations = !renderTask.separateAnnots; - this.eventBus.dispatch("pagerendered", { - source: this, - pageNumber: this.id, - cssTransform: false, - timestamp: performance.now(), - error: this.#renderError - }); - if (error) { - throw error; - } - } - async draw() { - if (this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.INITIAL) { - console.error("Must be in new state before drawing"); - this.reset(); - } - const { - div, - l10n, - pageColors, - pdfPage, - viewport - } = this; - if (!pdfPage) { - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED; - throw new Error("pdfPage is not loaded"); - } - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.RUNNING; - const canvasWrapper = document.createElement("div"); - canvasWrapper.classList.add("canvasWrapper"); - canvasWrapper.setAttribute("aria-hidden", true); - this.#addLayer(canvasWrapper, "canvasWrapper"); - if (!this.textLayer && this.#textLayerMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.DISABLE && !pdfPage.isPureXfa) { - this._accessibilityManager ||= new _text_accessibility_js__WEBPACK_IMPORTED_MODULE_9__.TextAccessibilityManager(); - this.textLayer = new _text_layer_builder_js__WEBPACK_IMPORTED_MODULE_10__.TextLayerBuilder({ - highlighter: this._textHighlighter, - accessibilityManager: this._accessibilityManager, - enablePermissions: this.#textLayerMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE_PERMISSIONS, - onAppend: textLayerDiv => { - this.l10n.pause(); - this.#addLayer(textLayerDiv, "textLayer"); - this.l10n.resume(); - } - }); - } - if (!this.annotationLayer && this.#annotationMode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.DISABLE) { - const { - annotationStorage, - annotationEditorUIManager, - downloadManager, - enableScripting, - fieldObjectsPromise, - hasJSActionsPromise, - linkService - } = this.#layerProperties; - this._annotationCanvasMap ||= new Map(); - this.annotationLayer = new _annotation_layer_builder_js__WEBPACK_IMPORTED_MODULE_3__.AnnotationLayerBuilder({ - pdfPage, - annotationStorage, - imageResourcesPath: this.imageResourcesPath, - renderForms: this.#annotationMode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS, - linkService, - downloadManager, - enableScripting, - hasJSActionsPromise, - fieldObjectsPromise, - annotationCanvasMap: this._annotationCanvasMap, - accessibilityManager: this._accessibilityManager, - annotationEditorUIManager, - onAppend: annotationLayerDiv => { - this.#addLayer(annotationLayerDiv, "annotationLayer"); - } - }); - } - const renderContinueCallback = cont => { - showCanvas?.(false); - if (this.renderingQueue && !this.renderingQueue.isHighestPriority(this)) { - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.PAUSED; - this.resume = () => { - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.RUNNING; - cont(); - }; - return; - } - cont(); - }; - const { - width, - height - } = viewport; - const canvas = document.createElement("canvas"); - canvas.setAttribute("role", "presentation"); - canvas.hidden = true; - const hasHCM = !!(pageColors?.background && pageColors?.foreground); - let showCanvas = isLastShow => { - if (!hasHCM || isLastShow) { - canvas.hidden = false; - showCanvas = null; - } - }; - canvasWrapper.append(canvas); - this.canvas = canvas; - const ctx = canvas.getContext("2d", { - alpha: false - }); - const outputScale = this.outputScale = new _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.OutputScale(); - if (this.maxCanvasPixels === 0) { - const invScale = 1 / this.scale; - outputScale.sx *= invScale; - outputScale.sy *= invScale; - this.#hasRestrictedScaling = true; - } else if (this.maxCanvasPixels > 0) { - const pixelsInViewport = width * height; - const maxScale = Math.sqrt(this.maxCanvasPixels / pixelsInViewport); - if (outputScale.sx > maxScale || outputScale.sy > maxScale) { - outputScale.sx = maxScale; - outputScale.sy = maxScale; - this.#hasRestrictedScaling = true; - } else { - this.#hasRestrictedScaling = false; - } - } - const sfx = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.approximateFraction)(outputScale.sx); - const sfy = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.approximateFraction)(outputScale.sy); - canvas.width = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.roundToDivide)(width * outputScale.sx, sfx[0]); - canvas.height = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.roundToDivide)(height * outputScale.sy, sfy[0]); - const { - style - } = canvas; - style.width = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.roundToDivide)(width, sfx[1]) + "px"; - style.height = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.roundToDivide)(height, sfy[1]) + "px"; - this.#viewportMap.set(canvas, viewport); - const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null; - const renderContext = { - canvasContext: ctx, - transform, - viewport, - annotationMode: this.#annotationMode, - optionalContentConfigPromise: this._optionalContentConfigPromise, - annotationCanvasMap: this._annotationCanvasMap, - pageColors - }; - const renderTask = this.renderTask = this.pdfPage.render(renderContext); - renderTask.onContinue = renderContinueCallback; - const resultPromise = renderTask.promise.then(async () => { - showCanvas?.(true); - await this.#finishRenderTask(renderTask); - this.#renderTextLayer(); - if (this.annotationLayer) { - await this.#renderAnnotationLayer(); - } - const { - annotationEditorUIManager - } = this.#layerProperties; - if (!annotationEditorUIManager) { - return; - } - this.drawLayer ||= new _draw_layer_builder_js__WEBPACK_IMPORTED_MODULE_5__.DrawLayerBuilder({ - pageIndex: this.id - }); - await this.#renderDrawLayer(); - this.drawLayer.setParent(canvasWrapper); - if (!this.annotationEditorLayer) { - // console.log('test-drawer', this.drawLayer.getDrawLayer()) - this.annotationEditorLayer = new _annotation_editor_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__.AnnotationEditorLayerBuilder({ - uiManager: annotationEditorUIManager, - pdfPage, - l10n, - accessibilityManager: this._accessibilityManager, - annotationLayer: this.annotationLayer?.annotationLayer, - textLayer: this.textLayer, - drawLayer: this.drawLayer.getDrawLayer(), - // drawLayer:null, - onAppend: annotationEditorLayerDiv => { - this.#addLayer(annotationEditorLayerDiv, "annotationEditorLayer"); - } - }); - } - this.#renderAnnotationEditorLayer(); - }, error => { - if (!(error instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.RenderingCancelledException)) { - showCanvas?.(true); - } - return this.#finishRenderTask(renderTask, error); - }); - if (pdfPage.isPureXfa) { - if (!this.xfaLayer) { - const { - annotationStorage, - linkService - } = this.#layerProperties; - this.xfaLayer = new _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_11__.XfaLayerBuilder({ - pdfPage, - annotationStorage, - linkService - }); - } - this.#renderXfaLayer(); - } - div.setAttribute("data-loaded", true); - this.eventBus.dispatch("pagerender", { - source: this, - pageNumber: this.id - }); - return resultPromise; - } - setPageLabel(label) { - this.pageLabel = typeof label === "string" ? label : null; - this.div.setAttribute("data-l10n-args", JSON.stringify({ - page: this.pageLabel ?? this.id - })); - if (this.pageLabel !== null) { - this.div.setAttribute("data-page-label", this.pageLabel); - } else { - this.div.removeAttribute("data-page-label"); - } - } - get thumbnailCanvas() { - const { - directDrawing, - initialOptionalContent, - regularAnnotations - } = this.#useThumbnailCanvas; - return directDrawing && initialOptionalContent && regularAnnotations ? this.canvas : null; - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 8917: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFPresentationMode: () => (/* binding */ PDFPresentationMode) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -const DELAY_BEFORE_HIDING_CONTROLS = 3000; -const ACTIVE_SELECTOR = "pdfPresentationMode"; -const CONTROLS_SELECTOR = "pdfPresentationModeControls"; -const MOUSE_SCROLL_COOLDOWN_TIME = 50; -const PAGE_SWITCH_THRESHOLD = 0.1; -const SWIPE_MIN_DISTANCE_THRESHOLD = 50; -const SWIPE_ANGLE_THRESHOLD = Math.PI / 6; -class PDFPresentationMode { - #state = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.UNKNOWN; - #args = null; - #fullscreenChangeAbortController = null; - #windowAbortController = null; - constructor({ - container, - pdfViewer, - eventBus - }) { - this.container = container; - this.pdfViewer = pdfViewer; - this.eventBus = eventBus; - this.contextMenuOpen = false; - this.mouseScrollTimeStamp = 0; - this.mouseScrollDelta = 0; - this.touchSwipeState = null; - } - async request() { - const { - container, - pdfViewer - } = this; - if (this.active || !pdfViewer.pagesCount || !container.requestFullscreen) { - return false; - } - this.#addFullscreenChangeListeners(); - this.#notifyStateChange(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.CHANGING); - const promise = container.requestFullscreen(); - this.#args = { - pageNumber: pdfViewer.currentPageNumber, - scaleValue: pdfViewer.currentScaleValue, - scrollMode: pdfViewer.scrollMode, - spreadMode: null, - annotationEditorMode: null - }; - if (pdfViewer.spreadMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.NONE && !(pdfViewer.pageViewsReady && pdfViewer.hasEqualPageSizes)) { - console.warn("Ignoring Spread modes when entering PresentationMode, " + "since the document may contain varying page sizes."); - this.#args.spreadMode = pdfViewer.spreadMode; - } - if (pdfViewer.annotationEditorMode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditorType.DISABLE) { - this.#args.annotationEditorMode = pdfViewer.annotationEditorMode; - } - try { - await promise; - pdfViewer.focus(); - return true; - } catch { - this.#removeFullscreenChangeListeners(); - this.#notifyStateChange(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.NORMAL); - } - return false; - } - get active() { - return this.#state === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.CHANGING || this.#state === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.FULLSCREEN; - } - #mouseWheel(evt) { - if (!this.active) { - return; - } - evt.preventDefault(); - const delta = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.normalizeWheelEventDelta)(evt); - const currentTime = Date.now(); - const storedTime = this.mouseScrollTimeStamp; - if (currentTime > storedTime && currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) { - return; - } - if (this.mouseScrollDelta > 0 && delta < 0 || this.mouseScrollDelta < 0 && delta > 0) { - this.#resetMouseScrollState(); - } - this.mouseScrollDelta += delta; - if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) { - const totalDelta = this.mouseScrollDelta; - this.#resetMouseScrollState(); - const success = totalDelta > 0 ? this.pdfViewer.previousPage() : this.pdfViewer.nextPage(); - if (success) { - this.mouseScrollTimeStamp = currentTime; - } - } - } - #notifyStateChange(state) { - this.#state = state; - this.eventBus.dispatch("presentationmodechanged", { - source: this, - state - }); - } - #enter() { - this.#notifyStateChange(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.FULLSCREEN); - this.container.classList.add(ACTIVE_SELECTOR); - setTimeout(() => { - this.pdfViewer.scrollMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.PAGE; - if (this.#args.spreadMode !== null) { - this.pdfViewer.spreadMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.NONE; - } - this.pdfViewer.currentPageNumber = this.#args.pageNumber; - this.pdfViewer.currentScaleValue = "page-fit"; - if (this.#args.annotationEditorMode !== null) { - this.pdfViewer.annotationEditorMode = { - mode: pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.AnnotationEditorType.NONE - }; - } - }, 0); - this.#addWindowListeners(); - this.#showControls(); - this.contextMenuOpen = false; - document.getSelection().empty(); - } - #exit() { - const pageNumber = this.pdfViewer.currentPageNumber; - this.container.classList.remove(ACTIVE_SELECTOR); - setTimeout(() => { - this.#removeFullscreenChangeListeners(); - this.#notifyStateChange(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.NORMAL); - this.pdfViewer.scrollMode = this.#args.scrollMode; - if (this.#args.spreadMode !== null) { - this.pdfViewer.spreadMode = this.#args.spreadMode; - } - this.pdfViewer.currentScaleValue = this.#args.scaleValue; - this.pdfViewer.currentPageNumber = pageNumber; - if (this.#args.annotationEditorMode !== null) { - this.pdfViewer.annotationEditorMode = { - mode: this.#args.annotationEditorMode - }; - } - this.#args = null; - }, 0); - this.#removeWindowListeners(); - this.#hideControls(); - this.#resetMouseScrollState(); - this.contextMenuOpen = false; - } - #mouseDown(evt) { - if (this.contextMenuOpen) { - this.contextMenuOpen = false; - evt.preventDefault(); - return; - } - if (evt.button !== 0) { - return; - } - if (evt.target.href && evt.target.parentNode?.hasAttribute("data-internal-link")) { - return; - } - evt.preventDefault(); - if (evt.shiftKey) { - this.pdfViewer.previousPage(); - } else { - this.pdfViewer.nextPage(); - } - } - #contextMenu() { - this.contextMenuOpen = true; - } - #showControls() { - if (this.controlsTimeout) { - clearTimeout(this.controlsTimeout); - } else { - this.container.classList.add(CONTROLS_SELECTOR); - } - this.controlsTimeout = setTimeout(() => { - this.container.classList.remove(CONTROLS_SELECTOR); - delete this.controlsTimeout; - }, DELAY_BEFORE_HIDING_CONTROLS); - } - #hideControls() { - if (!this.controlsTimeout) { - return; - } - clearTimeout(this.controlsTimeout); - this.container.classList.remove(CONTROLS_SELECTOR); - delete this.controlsTimeout; - } - #resetMouseScrollState() { - this.mouseScrollTimeStamp = 0; - this.mouseScrollDelta = 0; - } - #touchSwipe(evt) { - if (!this.active) { - return; - } - if (evt.touches.length > 1) { - this.touchSwipeState = null; - return; - } - switch (evt.type) { - case "touchstart": - this.touchSwipeState = { - startX: evt.touches[0].pageX, - startY: evt.touches[0].pageY, - endX: evt.touches[0].pageX, - endY: evt.touches[0].pageY - }; - break; - case "touchmove": - if (this.touchSwipeState === null) { - return; - } - this.touchSwipeState.endX = evt.touches[0].pageX; - this.touchSwipeState.endY = evt.touches[0].pageY; - evt.preventDefault(); - break; - case "touchend": - if (this.touchSwipeState === null) { - return; - } - let delta = 0; - const dx = this.touchSwipeState.endX - this.touchSwipeState.startX; - const dy = this.touchSwipeState.endY - this.touchSwipeState.startY; - const absAngle = Math.abs(Math.atan2(dy, dx)); - if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD && (absAngle <= SWIPE_ANGLE_THRESHOLD || absAngle >= Math.PI - SWIPE_ANGLE_THRESHOLD)) { - delta = dx; - } else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD && Math.abs(absAngle - Math.PI / 2) <= SWIPE_ANGLE_THRESHOLD) { - delta = dy; - } - if (delta > 0) { - this.pdfViewer.previousPage(); - } else if (delta < 0) { - this.pdfViewer.nextPage(); - } - break; - } - } - #addWindowListeners() { - if (this.#windowAbortController) { - return; - } - this.#windowAbortController = new AbortController(); - const { - signal - } = this.#windowAbortController; - const touchSwipeBind = this.#touchSwipe.bind(this); - window.addEventListener("mousemove", this.#showControls.bind(this), { - signal - }); - window.addEventListener("mousedown", this.#mouseDown.bind(this), { - signal - }); - window.addEventListener("wheel", this.#mouseWheel.bind(this), { - passive: false, - signal - }); - window.addEventListener("keydown", this.#resetMouseScrollState.bind(this), { - signal - }); - window.addEventListener("contextmenu", this.#contextMenu.bind(this), { - signal - }); - window.addEventListener("touchstart", touchSwipeBind, { - signal - }); - window.addEventListener("touchmove", touchSwipeBind, { - signal - }); - window.addEventListener("touchend", touchSwipeBind, { - signal - }); - } - #removeWindowListeners() { - this.#windowAbortController?.abort(); - this.#windowAbortController = null; - } - #addFullscreenChangeListeners() { - if (this.#fullscreenChangeAbortController) { - return; - } - this.#fullscreenChangeAbortController = new AbortController(); - window.addEventListener("fullscreenchange", () => { - if (document.fullscreenElement) { - this.#enter(); - } else { - this.#exit(); - } - }, { - signal: this.#fullscreenChangeAbortController.signal - }); - } - #removeFullscreenChangeListeners() { - this.#fullscreenChangeAbortController?.abort(); - this.#fullscreenChangeAbortController = null; - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 1144: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFPrintServiceFactory: () => (/* binding */ PDFPrintServiceFactory) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -/* harmony import */ var _print_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(659); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _print_utils_js__WEBPACK_IMPORTED_MODULE_1__]); -([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _print_utils_js__WEBPACK_IMPORTED_MODULE_1__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__); - - -let activeService = null; -let dialog = null; -let overlayManager = null; -let viewerApp = { - initialized: false -}; -function renderPage(activeServiceOnEntry, pdfDocument, pageNumber, size, printResolution, optionalContentConfigPromise, printAnnotationStoragePromise) { - const scratchCanvas = activeService.scratchCanvas; - const PRINT_UNITS = printResolution / pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF; - scratchCanvas.width = Math.floor(size.width * PRINT_UNITS); - scratchCanvas.height = Math.floor(size.height * PRINT_UNITS); - const ctx = scratchCanvas.getContext("2d"); - ctx.save(); - ctx.fillStyle = "rgb(255, 255, 255)"; - ctx.fillRect(0, 0, scratchCanvas.width, scratchCanvas.height); - ctx.restore(); - return Promise.all([pdfDocument.getPage(pageNumber), printAnnotationStoragePromise]).then(function ([pdfPage, printAnnotationStorage]) { - const renderContext = { - canvasContext: ctx, - transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0], - viewport: pdfPage.getViewport({ - scale: 1, - rotation: size.rotation - }), - intent: "print", - annotationMode: pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_STORAGE, - optionalContentConfigPromise, - printAnnotationStorage - }; - const renderTask = pdfPage.render(renderContext); - return renderTask.promise.catch(reason => { - if (!(reason instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.RenderingCancelledException)) { - console.error(reason); - } - throw reason; - }); - }); -} -class PDFPrintService { - constructor({ - pdfDocument, - pagesOverview, - printContainer, - printResolution, - printAnnotationStoragePromise = null - }) { - this.pdfDocument = pdfDocument; - this.pagesOverview = pagesOverview; - this.printContainer = printContainer; - this._printResolution = printResolution || 150; - this._optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({ - intent: "print" - }); - this._printAnnotationStoragePromise = printAnnotationStoragePromise || Promise.resolve(); - this.currentPage = -1; - this.scratchCanvas = document.createElement("canvas"); - } - layout() { - this.throwIfInactive(); - const body = document.querySelector("body"); - body.setAttribute("data-pdfjsprinting", true); - const { - width, - height - } = this.pagesOverview[0]; - const hasEqualPageSizes = this.pagesOverview.every(size => size.width === width && size.height === height); - if (!hasEqualPageSizes) { - console.warn("Not all pages have the same size. The printed result may be incorrect!"); - } - this.pageStyleSheet = document.createElement("style"); - this.pageStyleSheet.textContent = `@page { size: ${width}pt ${height}pt;}`; - body.append(this.pageStyleSheet); - } - destroy() { - if (activeService !== this) { - return; - } - this.printContainer.textContent = ""; - const body = document.querySelector("body"); - body.removeAttribute("data-pdfjsprinting"); - if (this.pageStyleSheet) { - this.pageStyleSheet.remove(); - this.pageStyleSheet = null; - } - this.scratchCanvas.width = this.scratchCanvas.height = 0; - this.scratchCanvas = null; - activeService = null; - ensureOverlay().then(function () { - if (overlayManager.active === dialog) { - overlayManager.close(dialog); - } - }); - } - renderPages() { - if (this.pdfDocument.isPureXfa) { - (0,_print_utils_js__WEBPACK_IMPORTED_MODULE_1__.getXfaHtmlForPrinting)(this.printContainer, this.pdfDocument); - return Promise.resolve(); - } - const pageCount = this.pagesOverview.length; - const renderNextPage = (resolve, reject) => { - this.throwIfInactive(); - if (++this.currentPage >= pageCount) { - renderProgress(pageCount, pageCount); - resolve(); - return; - } - const index = this.currentPage; - renderProgress(index, pageCount); - renderPage(this, this.pdfDocument, index + 1, this.pagesOverview[index], this._printResolution, this._optionalContentConfigPromise, this._printAnnotationStoragePromise).then(this.useRenderedPage.bind(this)).then(function () { - renderNextPage(resolve, reject); - }, reject); - }; - return new Promise(renderNextPage); - } - useRenderedPage() { - this.throwIfInactive(); - const img = document.createElement("img"); - const scratchCanvas = this.scratchCanvas; - if ("toBlob" in scratchCanvas) { - scratchCanvas.toBlob(function (blob) { - img.src = URL.createObjectURL(blob); - }); - } else { - img.src = scratchCanvas.toDataURL(); - } - const wrapper = document.createElement("div"); - wrapper.className = "printedPage"; - wrapper.append(img); - this.printContainer.append(wrapper); - return new Promise(function (resolve, reject) { - img.onload = resolve; - img.onerror = reject; - }); - } - performPrint() { - this.throwIfInactive(); - return new Promise(resolve => { - setTimeout(() => { - if (!this.active) { - resolve(); - return; - } - print.call(window); - setTimeout(resolve, 20); - }, 0); - }); - } - get active() { - return this === activeService; - } - throwIfInactive() { - if (!this.active) { - throw new Error("This print request was cancelled or completed."); - } - } -} -const print = window.print; -window.print = function () { - if (activeService) { - console.warn("Ignored window.print() because of a pending print job."); - return; - } - ensureOverlay().then(function () { - if (activeService) { - overlayManager.open(dialog); - } - }); - try { - dispatchEvent("beforeprint"); - } finally { - if (!activeService) { - console.error("Expected print service to be initialized."); - ensureOverlay().then(function () { - if (overlayManager.active === dialog) { - overlayManager.close(dialog); - } - }); - return; - } - const activeServiceOnEntry = activeService; - activeService.renderPages().then(function () { - return activeServiceOnEntry.performPrint(); - }).catch(function () {}).then(function () { - if (activeServiceOnEntry.active) { - abort(); - } - }); - } -}; -function dispatchEvent(eventType) { - const event = new CustomEvent(eventType, { - bubbles: false, - cancelable: false, - detail: "custom" - }); - window.dispatchEvent(event); -} -function abort() { - if (activeService) { - activeService.destroy(); - dispatchEvent("afterprint"); - } -} -function renderProgress(index, total) { - dialog ||= document.getElementById("printServiceDialog"); - const progress = Math.round(100 * index / total); - const progressBar = dialog.querySelector("progress"); - const progressPerc = dialog.querySelector(".relative-progress"); - progressBar.value = progress; - progressPerc.setAttribute("data-l10n-args", JSON.stringify({ - progress - })); -} -window.addEventListener("keydown", function (event) { - if (event.keyCode === 80 && (event.ctrlKey || event.metaKey) && !event.altKey && (!event.shiftKey || window.chrome || window.opera)) { - window.print(); - event.preventDefault(); - event.stopImmediatePropagation(); - } -}, true); -if ("onbeforeprint" in window) { - const stopPropagationIfNeeded = function (event) { - if (event.detail !== "custom") { - event.stopImmediatePropagation(); - } - }; - window.addEventListener("beforeprint", stopPropagationIfNeeded); - window.addEventListener("afterprint", stopPropagationIfNeeded); -} -let overlayPromise; -function ensureOverlay() { - if (!overlayPromise) { - overlayManager = viewerApp.overlayManager; - if (!overlayManager) { - throw new Error("The overlay manager has not yet been initialized."); - } - dialog ||= document.getElementById("printServiceDialog"); - overlayPromise = overlayManager.register(dialog, true); - document.getElementById("printCancel").onclick = abort; - dialog.addEventListener("close", abort); - } - return overlayPromise; -} -class PDFPrintServiceFactory { - static initGlobals(app) { - viewerApp = app; - } - static get supportsPrinting() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "supportsPrinting", true); - } - static createPrintService(params) { - if (activeService) { - throw new Error("The print service is created and active."); - } - return activeService = new PDFPrintService(params); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 6615: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFRenderingQueue: () => (/* binding */ PDFRenderingQueue) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -const CLEANUP_TIMEOUT = 30000; -class PDFRenderingQueue { - constructor() { - this.pdfViewer = null; - this.pdfThumbnailViewer = null; - this.onIdle = null; - this.highestPriorityPage = null; - this.idleTimeout = null; - this.printing = false; - this.isThumbnailViewEnabled = false; - Object.defineProperty(this, "hasViewer", { - value: () => !!this.pdfViewer - }); - } - setViewer(pdfViewer) { - this.pdfViewer = pdfViewer; - } - setThumbnailViewer(pdfThumbnailViewer) { - this.pdfThumbnailViewer = pdfThumbnailViewer; - } - isHighestPriority(view) { - return this.highestPriorityPage === view.renderingId; - } - renderHighestPriority(currentlyVisiblePages) { - if (this.idleTimeout) { - clearTimeout(this.idleTimeout); - this.idleTimeout = null; - } - if (this.pdfViewer.forceRendering(currentlyVisiblePages)) { - return; - } - if (this.isThumbnailViewEnabled && this.pdfThumbnailViewer?.forceRendering()) { - return; - } - if (this.printing) { - return; - } - if (this.onIdle) { - this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT); - } - } - getHighestPriority(visible, views, scrolledDown, preRenderExtra = false) { - const visibleViews = visible.views, - numVisible = visibleViews.length; - if (numVisible === 0) { - return null; - } - for (let i = 0; i < numVisible; i++) { - const view = visibleViews[i].view; - if (!this.isViewFinished(view)) { - return view; - } - } - const firstId = visible.first.id, - lastId = visible.last.id; - if (lastId - firstId + 1 > numVisible) { - const visibleIds = visible.ids; - for (let i = 1, ii = lastId - firstId; i < ii; i++) { - const holeId = scrolledDown ? firstId + i : lastId - i; - if (visibleIds.has(holeId)) { - continue; - } - const holeView = views[holeId - 1]; - if (!this.isViewFinished(holeView)) { - return holeView; - } - } - } - let preRenderIndex = scrolledDown ? lastId : firstId - 2; - let preRenderView = views[preRenderIndex]; - if (preRenderView && !this.isViewFinished(preRenderView)) { - return preRenderView; - } - if (preRenderExtra) { - preRenderIndex += scrolledDown ? 1 : -1; - preRenderView = views[preRenderIndex]; - if (preRenderView && !this.isViewFinished(preRenderView)) { - return preRenderView; - } - } - return null; - } - isViewFinished(view) { - return view.renderingState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED; - } - renderView(view) { - switch (view.renderingState) { - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED: - return false; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.PAUSED: - this.highestPriorityPage = view.renderingId; - view.resume(); - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.RUNNING: - this.highestPriorityPage = view.renderingId; - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.INITIAL: - this.highestPriorityPage = view.renderingId; - view.draw().finally(() => { - this.renderHighestPriority(); - }).catch(reason => { - if (reason instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.RenderingCancelledException) { - return; - } - console.error(`renderView: "${reason}"`); - }); - break; - } - return true; - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 5942: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFScriptingManager: () => (/* binding */ PDFScriptingManager) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -class PDFScriptingManager { - #closeCapability = null; - #destroyCapability = null; - #docProperties = null; - #eventAbortController = null; - #eventBus = null; - #externalServices = null; - #pdfDocument = null; - #pdfViewer = null; - #ready = false; - #scripting = null; - #willPrintCapability = null; - constructor({ - eventBus, - externalServices = null, - docProperties = null - }) { - this.#eventBus = eventBus; - this.#externalServices = externalServices; - this.#docProperties = docProperties; - } - setViewer(pdfViewer) { - this.#pdfViewer = pdfViewer; - } - async setDocument(pdfDocument) { - if (this.#pdfDocument) { - await this.#destroyScripting(); - } - this.#pdfDocument = pdfDocument; - if (!pdfDocument) { - return; - } - const [objects, calculationOrder, docActions] = await Promise.all([pdfDocument.getFieldObjects(), pdfDocument.getCalculationOrderIds(), pdfDocument.getJSActions()]); - if (!objects && !docActions) { - await this.#destroyScripting(); - return; - } - if (pdfDocument !== this.#pdfDocument) { - return; - } - try { - this.#scripting = this.#initScripting(); - } catch (error) { - console.error(`setDocument: "${error.message}".`); - await this.#destroyScripting(); - return; - } - const eventBus = this.#eventBus; - this.#eventAbortController = new AbortController(); - const { - signal - } = this.#eventAbortController; - eventBus._on("updatefromsandbox", event => { - if (event?.source === window) { - this.#updateFromSandbox(event.detail); - } - }, { - signal - }); - eventBus._on("dispatcheventinsandbox", event => { - this.#scripting?.dispatchEventInSandbox(event.detail); - }, { - signal - }); - eventBus._on("pagechanging", ({ - pageNumber, - previous - }) => { - if (pageNumber === previous) { - return; - } - this.#dispatchPageClose(previous); - this.#dispatchPageOpen(pageNumber); - }, { - signal - }); - eventBus._on("pagerendered", ({ - pageNumber - }) => { - if (!this._pageOpenPending.has(pageNumber)) { - return; - } - if (pageNumber !== this.#pdfViewer.currentPageNumber) { - return; - } - this.#dispatchPageOpen(pageNumber); - }, { - signal - }); - eventBus._on("pagesdestroy", async () => { - await this.#dispatchPageClose(this.#pdfViewer.currentPageNumber); - await this.#scripting?.dispatchEventInSandbox({ - id: "doc", - name: "WillClose" - }); - this.#closeCapability?.resolve(); - }, { - signal - }); - try { - const docProperties = await this.#docProperties(pdfDocument); - if (pdfDocument !== this.#pdfDocument) { - return; - } - await this.#scripting.createSandbox({ - objects, - calculationOrder, - appInfo: { - platform: navigator.platform, - language: navigator.language - }, - docInfo: { - ...docProperties, - actions: docActions - } - }); - eventBus.dispatch("sandboxcreated", { - source: this - }); - } catch (error) { - console.error(`setDocument: "${error.message}".`); - await this.#destroyScripting(); - return; - } - await this.#scripting?.dispatchEventInSandbox({ - id: "doc", - name: "Open" - }); - await this.#dispatchPageOpen(this.#pdfViewer.currentPageNumber, true); - Promise.resolve().then(() => { - if (pdfDocument === this.#pdfDocument) { - this.#ready = true; - } - }); - } - async dispatchWillSave() { - return this.#scripting?.dispatchEventInSandbox({ - id: "doc", - name: "WillSave" - }); - } - async dispatchDidSave() { - return this.#scripting?.dispatchEventInSandbox({ - id: "doc", - name: "DidSave" - }); - } - async dispatchWillPrint() { - if (!this.#scripting) { - return; - } - await this.#willPrintCapability?.promise; - this.#willPrintCapability = Promise.withResolvers(); - try { - await this.#scripting.dispatchEventInSandbox({ - id: "doc", - name: "WillPrint" - }); - } catch (ex) { - this.#willPrintCapability.resolve(); - this.#willPrintCapability = null; - throw ex; - } - await this.#willPrintCapability.promise; - } - async dispatchDidPrint() { - return this.#scripting?.dispatchEventInSandbox({ - id: "doc", - name: "DidPrint" - }); - } - get destroyPromise() { - return this.#destroyCapability?.promise || null; - } - get ready() { - return this.#ready; - } - get _pageOpenPending() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "_pageOpenPending", new Set()); - } - get _visitedPages() { - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.shadow)(this, "_visitedPages", new Map()); - } - async #updateFromSandbox(detail) { - const pdfViewer = this.#pdfViewer; - const isInPresentationMode = pdfViewer.isInPresentationMode || pdfViewer.isChangingPresentationMode; - const { - id, - siblings, - command, - value - } = detail; - if (!id) { - switch (command) { - case "clear": - console.clear(); - break; - case "error": - console.error(value); - break; - case "layout": - if (!isInPresentationMode) { - const modes = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.apiPageLayoutToViewerModes)(value); - pdfViewer.spreadMode = modes.spreadMode; - } - break; - case "page-num": - pdfViewer.currentPageNumber = value + 1; - break; - case "print": - await pdfViewer.pagesPromise; - this.#eventBus.dispatch("print", { - source: this - }); - break; - case "println": - console.log(value); - break; - case "zoom": - if (!isInPresentationMode) { - pdfViewer.currentScaleValue = value; - } - break; - case "SaveAs": - this.#eventBus.dispatch("download", { - source: this - }); - break; - case "FirstPage": - pdfViewer.currentPageNumber = 1; - break; - case "LastPage": - pdfViewer.currentPageNumber = pdfViewer.pagesCount; - break; - case "NextPage": - pdfViewer.nextPage(); - break; - case "PrevPage": - pdfViewer.previousPage(); - break; - case "ZoomViewIn": - if (!isInPresentationMode) { - pdfViewer.increaseScale(); - } - break; - case "ZoomViewOut": - if (!isInPresentationMode) { - pdfViewer.decreaseScale(); - } - break; - case "WillPrintFinished": - this.#willPrintCapability?.resolve(); - this.#willPrintCapability = null; - break; - } - return; - } - if (isInPresentationMode && detail.focus) { - return; - } - delete detail.id; - delete detail.siblings; - const ids = siblings ? [id, ...siblings] : [id]; - for (const elementId of ids) { - const element = document.querySelector(`[data-element-id="${elementId}"]`); - if (element) { - element.dispatchEvent(new CustomEvent("updatefromsandbox", { - detail - })); - } else { - this.#pdfDocument?.annotationStorage.setValue(elementId, detail); - } - } - } - async #dispatchPageOpen(pageNumber, initialize = false) { - const pdfDocument = this.#pdfDocument, - visitedPages = this._visitedPages; - if (initialize) { - this.#closeCapability = Promise.withResolvers(); - } - if (!this.#closeCapability) { - return; - } - const pageView = this.#pdfViewer.getPageView(pageNumber - 1); - if (pageView?.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED) { - this._pageOpenPending.add(pageNumber); - return; - } - this._pageOpenPending.delete(pageNumber); - const actionsPromise = (async () => { - const actions = await (!visitedPages.has(pageNumber) ? pageView.pdfPage?.getJSActions() : null); - if (pdfDocument !== this.#pdfDocument) { - return; - } - await this.#scripting?.dispatchEventInSandbox({ - id: "page", - name: "PageOpen", - pageNumber, - actions - }); - })(); - visitedPages.set(pageNumber, actionsPromise); - } - async #dispatchPageClose(pageNumber) { - const pdfDocument = this.#pdfDocument, - visitedPages = this._visitedPages; - if (!this.#closeCapability) { - return; - } - if (this._pageOpenPending.has(pageNumber)) { - return; - } - const actionsPromise = visitedPages.get(pageNumber); - if (!actionsPromise) { - return; - } - visitedPages.set(pageNumber, null); - await actionsPromise; - if (pdfDocument !== this.#pdfDocument) { - return; - } - await this.#scripting?.dispatchEventInSandbox({ - id: "page", - name: "PageClose", - pageNumber - }); - } - #initScripting() { - this.#destroyCapability = Promise.withResolvers(); - if (this.#scripting) { - throw new Error("#initScripting: Scripting already exists."); - } - return this.#externalServices.createScripting(); - } - async #destroyScripting() { - if (!this.#scripting) { - this.#pdfDocument = null; - this.#destroyCapability?.resolve(); - return; - } - if (this.#closeCapability) { - await Promise.race([this.#closeCapability.promise, new Promise(resolve => { - setTimeout(resolve, 1000); - })]).catch(() => {}); - this.#closeCapability = null; - } - this.#pdfDocument = null; - try { - await this.#scripting.destroySandbox(); - } catch {} - this.#willPrintCapability?.reject(new Error("Scripting destroyed.")); - this.#willPrintCapability = null; - this.#eventAbortController?.abort(); - this.#eventAbortController = null; - this._pageOpenPending.clear(); - this._visitedPages.clear(); - this.#scripting = null; - this.#ready = false; - this.#destroyCapability?.resolve(); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 2275: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFSidebar: () => (/* binding */ PDFSidebar) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); - -const SIDEBAR_WIDTH_VAR = "--sidebar-width"; -const SIDEBAR_MIN_WIDTH = 200; -const SIDEBAR_RESIZING_CLASS = "sidebarResizing"; -const UI_NOTIFICATION_CLASS = "pdfSidebarNotification"; -class PDFSidebar { - #isRTL = false; - #mouseMoveBound = this.#mouseMove.bind(this); - #mouseUpBound = this.#mouseUp.bind(this); - #outerContainerWidth = null; - #width = null; - constructor({ - elements, - eventBus, - l10n - }) { - this.isOpen = false; - this.active = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS; - this.isInitialViewSet = false; - this.isInitialEventDispatched = false; - this.onToggled = null; - this.onUpdateThumbnails = null; - this.outerContainer = elements.outerContainer; - this.sidebarContainer = elements.sidebarContainer; - this.toggleButton = elements.toggleButton; - this.resizer = elements.resizer; - this.thumbnailButton = elements.thumbnailButton; - this.outlineButton = elements.outlineButton; - this.attachmentsButton = elements.attachmentsButton; - this.layersButton = elements.layersButton; - this.thumbnailView = elements.thumbnailView; - this.outlineView = elements.outlineView; - this.attachmentsView = elements.attachmentsView; - this.layersView = elements.layersView; - this._currentOutlineItemButton = elements.currentOutlineItemButton; - this.eventBus = eventBus; - this.#isRTL = l10n.getDirection() === "rtl"; - this.#addEventListeners(); - } - reset() { - this.isInitialViewSet = false; - this.isInitialEventDispatched = false; - this.#hideUINotification(true); - this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS); - this.outlineButton.disabled = false; - this.attachmentsButton.disabled = false; - this.layersButton.disabled = false; - this._currentOutlineItemButton.disabled = true; - } - get visibleView() { - return this.isOpen ? this.active : _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.NONE; - } - setInitialView(view = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.NONE) { - if (this.isInitialViewSet) { - return; - } - this.isInitialViewSet = true; - if (view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.NONE || view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.UNKNOWN) { - this.#dispatchEvent(); - return; - } - // [Custom] desc: do not open the siderBar when init the view - // this.switchView(view, true); - if (!this.isInitialEventDispatched) { - this.#dispatchEvent(); - } - } - switchView(view, forceOpen = false) { - const isViewChanged = view !== this.active; - let forceRendering = false; - switch (view) { - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.NONE: - if (this.isOpen) { - this.close(); - } - return; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS: - if (this.isOpen && isViewChanged) { - forceRendering = true; - } - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.OUTLINE: - if (this.outlineButton.disabled) { - return; - } - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.ATTACHMENTS: - if (this.attachmentsButton.disabled) { - return; - } - break; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.LAYERS: - if (this.layersButton.disabled) { - return; - } - break; - default: - console.error(`PDFSidebar.switchView: "${view}" is not a valid view.`); - return; - } - this.active = view; - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(this.thumbnailButton, view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS, this.thumbnailView); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(this.outlineButton, view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.OUTLINE, this.outlineView); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(this.attachmentsButton, view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.ATTACHMENTS, this.attachmentsView); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(this.layersButton, view === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.LAYERS, this.layersView); - if (forceOpen && !this.isOpen) { - this.open(); - return; - } - if (forceRendering) { - this.onUpdateThumbnails(); - this.onToggled(); - } - if (isViewChanged) { - this.#dispatchEvent(); - } - } - open() { - if (this.isOpen) { - return; - } - this.isOpen = true; - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleExpandedBtn)(this.toggleButton, true); - this.outerContainer.classList.add("sidebarMoving", "sidebarOpen"); - if (this.active === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS) { - this.onUpdateThumbnails(); - } - this.onToggled(); - this.#dispatchEvent(); - this.#hideUINotification(); - } - close(evt = null) { - if (!this.isOpen) { - return; - } - this.isOpen = false; - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleExpandedBtn)(this.toggleButton, false); - this.outerContainer.classList.add("sidebarMoving"); - this.outerContainer.classList.remove("sidebarOpen"); - this.onToggled(); - this.#dispatchEvent(); - if (evt?.detail > 0) { - this.toggleButton.blur(); - } - } - toggle(evt = null) { - if (this.isOpen) { - this.close(evt); - } else { - this.open(); - } - } - #dispatchEvent() { - if (this.isInitialViewSet) { - this.isInitialEventDispatched ||= true; - } - this.eventBus.dispatch("sidebarviewchanged", { - source: this, - view: this.visibleView - }); - } - #showUINotification() { - this.toggleButton.setAttribute("data-l10n-id", "pdfjs-toggle-sidebar-notification-button"); - if (!this.isOpen) { - this.toggleButton.classList.add(UI_NOTIFICATION_CLASS); - } - } - #hideUINotification(reset = false) { - if (this.isOpen || reset) { - this.toggleButton.classList.remove(UI_NOTIFICATION_CLASS); - } - if (reset) { - this.toggleButton.setAttribute("data-l10n-id", "pdfjs-toggle-sidebar-button"); - } - } - #addEventListeners() { - this.sidebarContainer.addEventListener("transitionend", evt => { - if (evt.target === this.sidebarContainer) { - this.outerContainer.classList.remove("sidebarMoving"); - this.eventBus.dispatch("resize", { - source: this - }); - } - }); - this.toggleButton.addEventListener("click", evt => { - this.toggle(evt); - }); - this.thumbnailButton.addEventListener("click", () => { - this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS); - }); - this.outlineButton.addEventListener("click", () => { - this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.OUTLINE); - }); - this.outlineButton.addEventListener("dblclick", () => { - this.eventBus.dispatch("toggleoutlinetree", { - source: this - }); - }); - this.attachmentsButton.addEventListener("click", () => { - this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.ATTACHMENTS); - }); - this.layersButton.addEventListener("click", () => { - this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.LAYERS); - }); - this.layersButton.addEventListener("dblclick", () => { - this.eventBus.dispatch("resetlayers", { - source: this - }); - }); - this._currentOutlineItemButton.addEventListener("click", () => { - this.eventBus.dispatch("currentoutlineitem", { - source: this - }); - }); - const onTreeLoaded = (count, button, view) => { - button.disabled = !count; - if (count) { - this.#showUINotification(); - } else if (this.active === view) { - this.switchView(_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS); - } - }; - this.eventBus._on("outlineloaded", evt => { - onTreeLoaded(evt.outlineCount, this.outlineButton, _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.OUTLINE); - evt.currentOutlineItemPromise.then(enabled => { - if (!this.isInitialViewSet) { - return; - } - this._currentOutlineItemButton.disabled = !enabled; - }); - }); - this.eventBus._on("attachmentsloaded", evt => { - onTreeLoaded(evt.attachmentsCount, this.attachmentsButton, _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.ATTACHMENTS); - }); - this.eventBus._on("layersloaded", evt => { - onTreeLoaded(evt.layersCount, this.layersButton, _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.LAYERS); - }); - this.eventBus._on("presentationmodechanged", evt => { - if (evt.state === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.PresentationModeState.NORMAL && this.visibleView === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SidebarView.THUMBS) { - this.onUpdateThumbnails(); - } - }); - this.resizer.addEventListener("mousedown", evt => { - if (evt.button !== 0) { - return; - } - this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS); - window.addEventListener("mousemove", this.#mouseMoveBound); - window.addEventListener("mouseup", this.#mouseUpBound); - }); - this.eventBus._on("resize", evt => { - if (evt.source !== window) { - return; - } - this.#outerContainerWidth = null; - if (!this.#width) { - return; - } - if (!this.isOpen) { - this.#updateWidth(this.#width); - return; - } - this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS); - const updated = this.#updateWidth(this.#width); - Promise.resolve().then(() => { - this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS); - if (updated) { - this.eventBus.dispatch("resize", { - source: this - }); - } - }); - }); - } - get outerContainerWidth() { - return this.#outerContainerWidth ||= this.outerContainer.clientWidth; - } - #updateWidth(width = 0) { - const maxWidth = Math.floor(this.outerContainerWidth / 2); - if (width > maxWidth) { - width = maxWidth; - } - if (width < SIDEBAR_MIN_WIDTH) { - width = SIDEBAR_MIN_WIDTH; - } - if (width === this.#width) { - return false; - } - this.#width = width; - _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.docStyle.setProperty(SIDEBAR_WIDTH_VAR, `${width}px`); - return true; - } - #mouseMove(evt) { - let width = evt.clientX; - if (this.#isRTL) { - width = this.outerContainerWidth - width; - } - this.#updateWidth(width); - } - #mouseUp(evt) { - this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS); - this.eventBus.dispatch("resize", { - source: this - }); - window.removeEventListener("mousemove", this.#mouseMoveBound); - window.removeEventListener("mouseup", this.#mouseUpBound); - } -} - - -/***/ }), - -/***/ 1123: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFThumbnailView: () => (/* binding */ PDFThumbnailView), -/* harmony export */ TempImageFactory: () => (/* binding */ TempImageFactory) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -const DRAW_UPSCALE_FACTOR = 2; -const MAX_NUM_SCALING_STEPS = 3; -const THUMBNAIL_WIDTH = 90; -class TempImageFactory { - static #tempCanvas = null; - static getCanvas(width, height) { - const tempCanvas = this.#tempCanvas ||= document.createElement("canvas"); - tempCanvas.width = width; - tempCanvas.height = height; - const ctx = tempCanvas.getContext("2d", { - alpha: false - }); - ctx.save(); - ctx.fillStyle = "rgb(255, 255, 255)"; - ctx.fillRect(0, 0, width, height); - ctx.restore(); - return [tempCanvas, tempCanvas.getContext("2d")]; - } - static destroyCanvas() { - const tempCanvas = this.#tempCanvas; - if (tempCanvas) { - tempCanvas.width = 0; - tempCanvas.height = 0; - } - this.#tempCanvas = null; - } -} -class PDFThumbnailView { - constructor({ - container, - eventBus, - id, - defaultViewport, - optionalContentConfigPromise, - linkService, - renderingQueue, - pageColors - }) { - this.id = id; - this.renderingId = "thumbnail" + id; - this.pageLabel = null; - this.pdfPage = null; - this.rotation = 0; - this.viewport = defaultViewport; - this.pdfPageRotate = defaultViewport.rotation; - this._optionalContentConfigPromise = optionalContentConfigPromise || null; - this.pageColors = pageColors || null; - this.eventBus = eventBus; - this.linkService = linkService; - this.renderingQueue = renderingQueue; - this.renderTask = null; - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.INITIAL; - this.resume = null; - this.oldNumHeight = 20; - const anchor = document.createElement("a"); - anchor.href = linkService.getAnchorUrl("#page=" + id); - anchor.setAttribute("data-l10n-id", "pdfjs-thumb-page-title"); - anchor.setAttribute("data-l10n-args", this.#pageL10nArgs); - anchor.onclick = function () { - linkService.goToPage(id); - return false; - }; - this.anchor = anchor; - const div = document.createElement("div"); - div.className = "thumbnail"; - div.setAttribute("data-page-number", this.id); - this.div = div; - this.#updateDims(); - const img = document.createElement("div"); - img.className = "thumbnailImage"; - this._placeholderImg = img; - div.append(img); - anchor.append(div); - container.append(anchor); - - const odlImageNum = document.createElement("div"); - odlImageNum.classList.add(window.odlCustomSiderDomList.odl_imageNum); - // console.log('test-this', this) - odlImageNum.innerText = this.id - anchor.append(odlImageNum) - } - #updateDims() { - const { - width, - height - } = this.viewport; - const ratio = width / height; - this.canvasWidth = THUMBNAIL_WIDTH; - this.canvasHeight = this.canvasWidth / ratio | 0; - this.scale = this.canvasWidth / width; - const { - style - } = this.div; - // console.log('test-canvas', this.canvasWidth, this.canvasHeight, THUMBNAIL_WIDTH); - style.setProperty("--thumbnail-width", `${this.canvasWidth}px`); - style.setProperty("--thumbnail-height", `${this.canvasHeight}px`); - } - setPdfPage(pdfPage) { - this.pdfPage = pdfPage; - this.pdfPageRotate = pdfPage.rotate; - const totalRotation = (this.rotation + this.pdfPageRotate) % 360; - this.viewport = pdfPage.getViewport({ - scale: 1, - rotation: totalRotation - }); - this.reset(); - } - reset() { - this.cancelRendering(); - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.INITIAL; - this.div.removeAttribute("data-loaded"); - this.image?.replaceWith(this._placeholderImg); - this.#updateDims(); - if (this.image) { - this.image.removeAttribute("src"); - delete this.image; - } - } - update({ - rotation = null - }) { - if (typeof rotation === "number") { - this.rotation = rotation; - } - const totalRotation = (this.rotation + this.pdfPageRotate) % 360; - this.viewport = this.viewport.clone({ - scale: 1, - rotation: totalRotation - }); - this.reset(); - } - cancelRendering() { - if (this.renderTask) { - this.renderTask.cancel(); - this.renderTask = null; - } - this.resume = null; - } - #getPageDrawContext(upscaleFactor = 1) { - const canvas = document.createElement("canvas"); - const ctx = canvas.getContext("2d", { - alpha: false - }); - const outputScale = new _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.OutputScale(); - canvas.width = upscaleFactor * this.canvasWidth * outputScale.sx | 0; - canvas.height = upscaleFactor * this.canvasHeight * outputScale.sy | 0; - const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null; - return { - ctx, - canvas, - transform - }; - } - #convertCanvasToImage(canvas) { - if (this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED) { - throw new Error("#convertCanvasToImage: Rendering has not finished."); - } - const reducedCanvas = this.#reduceImage(canvas); - const image = document.createElement("img"); - image.className = "thumbnailImage"; - image.setAttribute("data-l10n-id", "pdfjs-thumb-page-canvas"); - image.setAttribute("data-l10n-args", this.#pageL10nArgs); - image.src = reducedCanvas.toDataURL(); - this.image = image; - this.div.setAttribute("data-loaded", true); - this._placeholderImg.replaceWith(image); - reducedCanvas.width = 0; - reducedCanvas.height = 0; - } - async #finishRenderTask(renderTask, canvas, error = null) { - if (renderTask === this.renderTask) { - this.renderTask = null; - } - if (error instanceof pdfjs_lib__WEBPACK_IMPORTED_MODULE_1__.RenderingCancelledException) { - return; - } - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED; - this.#convertCanvasToImage(canvas); - if (error) { - throw error; - } - } - async draw() { - if (this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.INITIAL) { - console.error("Must be in new state before drawing"); - return undefined; - } - const { - pdfPage - } = this; - if (!pdfPage) { - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED; - throw new Error("pdfPage is not loaded"); - } - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.RUNNING; - const { - ctx, - canvas, - transform - } = this.#getPageDrawContext(DRAW_UPSCALE_FACTOR); - const drawViewport = this.viewport.clone({ - scale: DRAW_UPSCALE_FACTOR * this.scale - }); - const renderContinueCallback = cont => { - if (!this.renderingQueue.isHighestPriority(this)) { - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.PAUSED; - this.resume = () => { - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.RUNNING; - cont(); - }; - return; - } - cont(); - }; - const renderContext = { - canvasContext: ctx, - transform, - viewport: drawViewport, - optionalContentConfigPromise: this._optionalContentConfigPromise, - pageColors: this.pageColors - }; - const renderTask = this.renderTask = pdfPage.render(renderContext); - renderTask.onContinue = renderContinueCallback; - const resultPromise = renderTask.promise.then(() => this.#finishRenderTask(renderTask, canvas), error => this.#finishRenderTask(renderTask, canvas, error)); - resultPromise.finally(() => { - canvas.width = 0; - canvas.height = 0; - this.eventBus.dispatch("thumbnailrendered", { - source: this, - pageNumber: this.id, - pdfPage: this.pdfPage - }); - }); - return resultPromise; - } - setImage(pageView) { - if (this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.INITIAL) { - return; - } - const { - thumbnailCanvas: canvas, - pdfPage, - scale - } = pageView; - if (!canvas) { - return; - } - if (!this.pdfPage) { - this.setPdfPage(pdfPage); - } - if (scale < this.scale) { - return; - } - this.renderingState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED; - this.#convertCanvasToImage(canvas); - } - #reduceImage(img) { - const { - ctx, - canvas - } = this.#getPageDrawContext(); - if (img.width <= 2 * canvas.width) { - ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height); - return canvas; - } - let reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS; - let reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS; - const [reducedImage, reducedImageCtx] = TempImageFactory.getCanvas(reducedWidth, reducedHeight); - while (reducedWidth > img.width || reducedHeight > img.height) { - reducedWidth >>= 1; - reducedHeight >>= 1; - } - reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight); - while (reducedWidth > 2 * canvas.width) { - reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1); - reducedWidth >>= 1; - reducedHeight >>= 1; - } - ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height); - return canvas; - } - get #pageL10nArgs() { - return JSON.stringify({ - page: this.pageLabel ?? this.id - }); - } - setPageLabel(label) { - this.pageLabel = typeof label === "string" ? label : null; - this.anchor.setAttribute("data-l10n-args", this.#pageL10nArgs); - if (this.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED) { - return; - } - this.image?.setAttribute("data-l10n-args", this.#pageL10nArgs); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 8280: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFThumbnailViewer: () => (/* binding */ PDFThumbnailViewer) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); -/* harmony import */ var _pdf_thumbnail_view_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1123); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_pdf_thumbnail_view_js__WEBPACK_IMPORTED_MODULE_1__]); -_pdf_thumbnail_view_js__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -const THUMBNAIL_SCROLL_MARGIN = -19; -const THUMBNAIL_SELECTED_CLASS = "selected"; -const ODL_THUMBNAIL_SELECTED_CLASS = "odl_selected"; -class PDFThumbnailViewer { - constructor({ - container, - eventBus, - linkService, - renderingQueue, - pageColors - }) { - this.container = container; - this.eventBus = eventBus; - this.linkService = linkService; - this.renderingQueue = renderingQueue; - this.pageColors = pageColors || null; - this.scroll = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.watchScroll)(this.container, this.#scrollUpdated.bind(this)); - this.#resetView(); - } - #scrollUpdated() { - this.renderingQueue.renderHighestPriority(); - } - getThumbnail(index) { - return this._thumbnails[index]; - } - #getVisibleThumbs() { - return (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.getVisibleElements)({ - scrollEl: this.container, - views: this._thumbnails - }); - } - scrollThumbnailIntoView(pageNumber) { - if (!this.pdfDocument) { - return; - } - const thumbnailView = this._thumbnails[pageNumber - 1]; - if (!thumbnailView) { - console.error('scrollThumbnailIntoView: Invalid "pageNumber" parameter.'); - return; - } - if (pageNumber !== this._currentPageNumber) { - const prevThumbnailView = this._thumbnails[this._currentPageNumber - 1]; - prevThumbnailView.div.classList.remove(THUMBNAIL_SELECTED_CLASS); - prevThumbnailView.div.parentNode.classList.remove(ODL_THUMBNAIL_SELECTED_CLASS) - thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS); - thumbnailView.div.parentNode.classList.add(ODL_THUMBNAIL_SELECTED_CLASS) - } - const { - first, - last, - views - } = this.#getVisibleThumbs(); - if (views.length > 0) { - let shouldScroll = false; - if (pageNumber <= first.id || pageNumber >= last.id) { - shouldScroll = true; - } else { - for (const { - id, - percent - } of views) { - if (id !== pageNumber) { - continue; - } - shouldScroll = percent < 100; - break; - } - } - if (shouldScroll) { - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.scrollIntoView)(thumbnailView.div, { - top: THUMBNAIL_SCROLL_MARGIN - }); - } - } - this._currentPageNumber = pageNumber; - } - get pagesRotation() { - return this._pagesRotation; - } - set pagesRotation(rotation) { - if (!(0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.isValidRotation)(rotation)) { - throw new Error("Invalid thumbnails rotation angle."); - } - if (!this.pdfDocument) { - return; - } - if (this._pagesRotation === rotation) { - return; - } - this._pagesRotation = rotation; - const updateArgs = { - rotation - }; - for (const thumbnail of this._thumbnails) { - thumbnail.update(updateArgs); - } - } - cleanup() { - for (const thumbnail of this._thumbnails) { - if (thumbnail.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates.FINISHED) { - thumbnail.reset(); - } - } - _pdf_thumbnail_view_js__WEBPACK_IMPORTED_MODULE_1__.TempImageFactory.destroyCanvas(); - } - #resetView() { - this._thumbnails = []; - this._currentPageNumber = 1; - this._pageLabels = null; - this._pagesRotation = 0; - this.container.textContent = ""; - } - setDocument(pdfDocument) { - if (this.pdfDocument) { - this.#cancelRendering(); - this.#resetView(); - } - this.pdfDocument = pdfDocument; - if (!pdfDocument) { - return; - } - const firstPagePromise = pdfDocument.getPage(1); - const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({ - intent: "display" - }); - firstPagePromise.then(firstPdfPage => { - const pagesCount = pdfDocument.numPages; - const viewport = firstPdfPage.getViewport({ - scale: 1 - }); - for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { - const thumbnail = new _pdf_thumbnail_view_js__WEBPACK_IMPORTED_MODULE_1__.PDFThumbnailView({ - container: this.container, - eventBus: this.eventBus, - id: pageNum, - defaultViewport: viewport.clone(), - optionalContentConfigPromise, - linkService: this.linkService, - renderingQueue: this.renderingQueue, - pageColors: this.pageColors - }); - this._thumbnails.push(thumbnail); - } - this._thumbnails[0]?.setPdfPage(firstPdfPage); - const thumbnailView = this._thumbnails[this._currentPageNumber - 1]; - thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS); - }).catch(reason => { - console.error("Unable to initialize thumbnail viewer", reason); - }); - } - #cancelRendering() { - for (const thumbnail of this._thumbnails) { - thumbnail.cancelRendering(); - } - } - setPageLabels(labels) { - if (!this.pdfDocument) { - return; - } - if (!labels) { - this._pageLabels = null; - } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) { - this._pageLabels = null; - console.error("PDFThumbnailViewer_setPageLabels: Invalid page labels."); - } else { - this._pageLabels = labels; - } - for (let i = 0, ii = this._thumbnails.length; i < ii; i++) { - this._thumbnails[i].setPageLabel(this._pageLabels?.[i] ?? null); - } - } - async #ensurePdfPageLoaded(thumbView) { - if (thumbView.pdfPage) { - return thumbView.pdfPage; - } - try { - const pdfPage = await this.pdfDocument.getPage(thumbView.id); - if (!thumbView.pdfPage) { - thumbView.setPdfPage(pdfPage); - } - return pdfPage; - } catch (reason) { - console.error("Unable to get page for thumb view", reason); - return null; - } - } - #getScrollAhead(visible) { - if (visible.first?.id === 1) { - return true; - } else if (visible.last?.id === this._thumbnails.length) { - return false; - } - return this.scroll.down; - } - forceRendering() { - const visibleThumbs = this.#getVisibleThumbs(); - const scrollAhead = this.#getScrollAhead(visibleThumbs); - const thumbView = this.renderingQueue.getHighestPriority(visibleThumbs, this._thumbnails, scrollAhead); - // 有缓存 thumbView null 所以返回false, 不强制更新 - if (thumbView) { - this.#ensurePdfPageLoaded(thumbView).then(() => { - this.renderingQueue.renderView(thumbView); - }); - return true; - } - return false; - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 6285: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFViewer: () => (/* binding */ PDFViewer), -/* harmony export */ PagesCountLimit: () => (/* binding */ PagesCountLimit) -/* harmony export */ }); -/* unused harmony export PDFPageViewBuffer */ -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256); -/* harmony import */ var web_null_l10n__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(410); -/* harmony import */ var _pdf_page_view_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9966); -/* harmony import */ var _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6615); -/* harmony import */ var _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(787); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, web_null_l10n__WEBPACK_IMPORTED_MODULE_2__, _pdf_page_view_js__WEBPACK_IMPORTED_MODULE_3__, _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_4__]); -([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, web_null_l10n__WEBPACK_IMPORTED_MODULE_2__, _pdf_page_view_js__WEBPACK_IMPORTED_MODULE_3__, _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_4__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__); - - - - - - -const DEFAULT_CACHE_SIZE = 10; -const PagesCountLimit = { - FORCE_SCROLL_MODE_PAGE: 15000, - FORCE_LAZY_PAGE_INIT: 7500, - PAUSE_EAGER_PAGE_INIT: 250 -}; -function isValidAnnotationEditorMode(mode) { - return Object.values(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType).includes(mode) && mode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE; -} -class PDFPageViewBuffer { - #buf = new Set(); - #size = 0; - constructor(size) { - this.#size = size; - } - push(view) { - const buf = this.#buf; - if (buf.has(view)) { - buf.delete(view); - } - buf.add(view); - if (buf.size > this.#size) { - this.#destroyFirstView(); - } - } - resize(newSize, idsToKeep = null) { - this.#size = newSize; - const buf = this.#buf; - if (idsToKeep) { - const ii = buf.size; - let i = 1; - for (const view of buf) { - if (idsToKeep.has(view.id)) { - buf.delete(view); - buf.add(view); - } - if (++i > ii) { - break; - } - } - } - while (buf.size > this.#size) { - this.#destroyFirstView(); - } - } - has(view) { - return this.#buf.has(view); - } - [Symbol.iterator]() { - return this.#buf.keys(); - } - #destroyFirstView() { - const firstView = this.#buf.keys().next().value; - firstView?.destroy(); - this.#buf.delete(firstView); - } -} -class PDFViewer { - #buffer = null; - #altTextManager = null; - #annotationEditorHighlightColors = null; - #annotationEditorMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE; - #annotationEditorUIManager = null; - #annotationMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS; - #containerTopLeft = null; - #copyCallbackBound = null; - #enableHighlightFloatingButton = false; - #enablePermissions = false; - #mlManager = null; - #getAllTextInProgress = false; - #hiddenCopyElement = null; - #interruptCopyCondition = false; - #previousContainerHeight = 0; - #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this)); - #scrollModePageState = null; - #onVisibilityChange = null; - #scaleTimeoutId = null; - #textLayerMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE; - constructor(options) { - const viewerVersion = "4.2.67"; - if (pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.version !== viewerVersion) { - throw new Error(`The API version "${pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.version}" does not match the Viewer version "${viewerVersion}".`); - } - this.container = options.container; - this.viewer = options.viewer || options.container.firstElementChild; - if (this.container?.tagName !== "DIV" || this.viewer?.tagName !== "DIV") { - throw new Error("Invalid `container` and/or `viewer` option."); - } - if (this.container.offsetParent && getComputedStyle(this.container).position !== "absolute") { - throw new Error("The `container` must be absolutely positioned."); - } - this.#resizeObserver.observe(this.container); - this.eventBus = options.eventBus; - this.linkService = options.linkService || new _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_5__.SimpleLinkService(); - this.downloadManager = options.downloadManager || null; - this.findController = options.findController || null; - this.#altTextManager = options.altTextManager || null; - if (this.findController) { - this.findController.onIsPageVisible = pageNumber => this._getVisiblePages().ids.has(pageNumber); - } - this._scriptingManager = options.scriptingManager || null; - this.#textLayerMode = options.textLayerMode ?? _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE; - this.#annotationMode = options.annotationMode ?? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS; - this.#annotationEditorMode = options.annotationEditorMode ?? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE; - this.#annotationEditorHighlightColors = options.annotationEditorHighlightColors || null; - this.#enableHighlightFloatingButton = options.enableHighlightFloatingButton === true; - this.imageResourcesPath = options.imageResourcesPath || ""; - this.enablePrintAutoRotate = options.enablePrintAutoRotate || false; - this.removePageBorders = options.removePageBorders || false; - this.maxCanvasPixels = options.maxCanvasPixels; - this.l10n = options.l10n; - this.l10n ||= new web_null_l10n__WEBPACK_IMPORTED_MODULE_2__.GenericL10n(); - this.#enablePermissions = options.enablePermissions || false; - this.pageColors = options.pageColors || null; - this.#mlManager = options.mlManager || null; - this.defaultRenderingQueue = !options.renderingQueue; - if (this.defaultRenderingQueue) { - this.renderingQueue = new _pdf_rendering_queue_js__WEBPACK_IMPORTED_MODULE_4__.PDFRenderingQueue(); - this.renderingQueue.setViewer(this); - } else { - this.renderingQueue = options.renderingQueue; - } - this.scroll = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.watchScroll)(this.container, this._scrollUpdate.bind(this)); - this.presentationModeState = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.UNKNOWN; - this._onBeforeDraw = this._onAfterDraw = null; - this._resetView(); - if (this.removePageBorders) { - this.viewer.classList.add("removePageBorders"); - } - this.#updateContainerHeightCss(); - this.eventBus._on("thumbnailrendered", ({ - pageNumber, - pdfPage - }) => { - const pageView = this._pages[pageNumber - 1]; - if (!this.#buffer.has(pageView)) { - pdfPage?.cleanup(); - } - }); - if (!options.l10n) { - this.l10n.translate(this.container); - } - } - get pagesCount() { - return this._pages.length; - } - getPageView(index) { - return this._pages[index]; - } - getCachedPageViews() { - return new Set(this.#buffer); - } - get pageViewsReady() { - return this._pages.every(pageView => pageView?.pdfPage); - } - get renderForms() { - return this.#annotationMode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS; - } - get enableScripting() { - return !!this._scriptingManager; - } - get currentPageNumber() { - return this._currentPageNumber; - } - set currentPageNumber(val) { - if (!Number.isInteger(val)) { - throw new Error("Invalid page number."); - } - if (!this.pdfDocument) { - return; - } - // console.log('test-setCurrent-1') - // [custom] desc: 上面按钮切换pageNumber - if (!this._setCurrentPageNumber(val, true)) { - console.error(`currentPageNumber: "${val}" is not a valid page.`); - } - } - _setCurrentPageNumber(val, resetCurrentPageView = false) { - if (this._currentPageNumber === val) { - if (resetCurrentPageView) { - this.#resetCurrentPageView(); - } - return true; - } - if (!(0 < val && val <= this.pagesCount)) { - return false; - } - const previous = this._currentPageNumber; - this._currentPageNumber = val; - this.eventBus.dispatch("pagechanging", { - source: this, - pageNumber: val, - pageLabel: this._pageLabels?.[val - 1] ?? null, - previous - }); - - if (resetCurrentPageView) { - this.#resetCurrentPageView(); - } - return true; - } - get currentPageLabel() { - return this._pageLabels?.[this._currentPageNumber - 1] ?? null; - } - set currentPageLabel(val) { - if (!this.pdfDocument) { - return; - } - let page = val | 0; - if (this._pageLabels) { - const i = this._pageLabels.indexOf(val); - if (i >= 0) { - page = i + 1; - } - } - if (!this._setCurrentPageNumber(page, true)) { - console.error(`currentPageLabel: "${val}" is not a valid page.`); - } - } - get currentScale() { - return this._currentScale !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.UNKNOWN_SCALE ? this._currentScale : _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE; - } - set currentScale(val) { - if (isNaN(val)) { - throw new Error("Invalid numeric scale."); - } - if (!this.pdfDocument) { - return; - } - this.#setScale(val, { - noScroll: false - }); - } - get currentScaleValue() { - return this._currentScaleValue; - } - set currentScaleValue(val) { - if (!this.pdfDocument) { - return; - } - this.#setScale(val, { - noScroll: false - }); - } - get pagesRotation() { - return this._pagesRotation; - } - set pagesRotation(rotation) { - if (!(0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.isValidRotation)(rotation)) { - throw new Error("Invalid pages rotation angle."); - } - if (!this.pdfDocument) { - return; - } - rotation %= 360; - if (rotation < 0) { - rotation += 360; - } - if (this._pagesRotation === rotation) { - return; - } - this._pagesRotation = rotation; - const pageNumber = this._currentPageNumber; - this.refresh(true, { - rotation - }); - if (this._currentScaleValue) { - this.#setScale(this._currentScaleValue, { - noScroll: true - }); - } - this.eventBus.dispatch("rotationchanging", { - source: this, - pagesRotation: rotation, - pageNumber - }); - if (this.defaultRenderingQueue) { - this.update(); - } - } - get firstPagePromise() { - return this.pdfDocument ? this._firstPageCapability.promise : null; - } - get onePageRendered() { - return this.pdfDocument ? this._onePageRenderedCapability.promise : null; - } - get pagesPromise() { - return this.pdfDocument ? this._pagesCapability.promise : null; - } - get _layerProperties() { - const self = this; - return (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.shadow)(this, "_layerProperties", { - get annotationEditorUIManager() { - return self.#annotationEditorUIManager; - }, - get annotationStorage() { - return self.pdfDocument?.annotationStorage; - }, - get downloadManager() { - return self.downloadManager; - }, - get enableScripting() { - return !!self._scriptingManager; - }, - get fieldObjectsPromise() { - return self.pdfDocument?.getFieldObjects(); - }, - get findController() { - return self.findController; - }, - get hasJSActionsPromise() { - return self.pdfDocument?.hasJSActions(); - }, - get linkService() { - return self.linkService; - } - }); - } - #initializePermissions(permissions) { - const params = { - annotationEditorMode: this.#annotationEditorMode, - annotationMode: this.#annotationMode, - textLayerMode: this.#textLayerMode - }; - if (!permissions) { - return params; - } - if (!permissions.includes(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PermissionFlag.COPY) && this.#textLayerMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE) { - params.textLayerMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE_PERMISSIONS; - } - if (!permissions.includes(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PermissionFlag.MODIFY_CONTENTS)) { - params.annotationEditorMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE; - } - if (!permissions.includes(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PermissionFlag.MODIFY_ANNOTATIONS) && !permissions.includes(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PermissionFlag.FILL_INTERACTIVE_FORMS) && this.#annotationMode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE_FORMS) { - params.annotationMode = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationMode.ENABLE; - } - return params; - } - async #onePageRenderedOrForceFetch() { - if (document.visibilityState === "hidden" || !this.container.offsetParent || this._getVisiblePages().views.length === 0) { - return; - } - const visibilityChangePromise = new Promise(resolve => { - this.#onVisibilityChange = () => { - if (document.visibilityState !== "hidden") { - return; - } - resolve(); - }; - document.addEventListener("visibilitychange", this.#onVisibilityChange); - }); - await Promise.race([this._onePageRenderedCapability.promise, visibilityChangePromise]); - document.removeEventListener("visibilitychange", this.#onVisibilityChange); - this.#onVisibilityChange = null; - } - async getAllText() { - const texts = []; - const buffer = []; - for (let pageNum = 1, pagesCount = this.pdfDocument.numPages; pageNum <= pagesCount; ++pageNum) { - if (this.#interruptCopyCondition) { - return null; - } - buffer.length = 0; - const page = await this.pdfDocument.getPage(pageNum); - const { - items - } = await page.getTextContent(); - for (const item of items) { - if (item.str) { - buffer.push(item.str); - } - if (item.hasEOL) { - buffer.push("\n"); - } - } - texts.push((0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.removeNullCharacters)(buffer.join(""))); - } - return texts.join("\n"); - } - #copyCallback(textLayerMode, event) { - const selection = document.getSelection(); - const { - focusNode, - anchorNode - } = selection; - if (anchorNode && focusNode && selection.containsNode(this.#hiddenCopyElement)) { - if (this.#getAllTextInProgress || textLayerMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.ENABLE_PERMISSIONS) { - event.preventDefault(); - event.stopPropagation(); - return; - } - this.#getAllTextInProgress = true; - const savedCursor = this.container.style.cursor; - this.container.style.cursor = "wait"; - const interruptCopy = ev => this.#interruptCopyCondition = ev.key === "Escape"; - window.addEventListener("keydown", interruptCopy); - this.getAllText().then(async text => { - if (text !== null) { - await navigator.clipboard.writeText(text); - } - }).catch(reason => { - console.warn(`Something goes wrong when extracting the text: ${reason.message}`); - }).finally(() => { - this.#getAllTextInProgress = false; - this.#interruptCopyCondition = false; - window.removeEventListener("keydown", interruptCopy); - this.container.style.cursor = savedCursor; - }); - event.preventDefault(); - event.stopPropagation(); - } - } - setDocument(pdfDocument) { - if (this.pdfDocument) { - this.eventBus.dispatch("pagesdestroy", { - source: this - }); - this._cancelRendering(); - this._resetView(); - this.findController?.setDocument(null); - this._scriptingManager?.setDocument(null); - if (this.#annotationEditorUIManager) { - this.#annotationEditorUIManager.destroy(); - this.#annotationEditorUIManager = null; - } - } - this.pdfDocument = pdfDocument; - if (!pdfDocument) { - return; - } - const pagesCount = pdfDocument.numPages; - const firstPagePromise = pdfDocument.getPage(1); - const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({ - intent: "display" - }); - const permissionsPromise = this.#enablePermissions ? pdfDocument.getPermissions() : Promise.resolve(); - if (pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) { - console.warn("Forcing PAGE-scrolling for performance reasons, given the length of the document."); - const mode = this._scrollMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE; - this.eventBus.dispatch("scrollmodechanged", { - source: this, - mode - }); - } - this._pagesCapability.promise.then(() => { - this.eventBus.dispatch("pagesloaded", { - source: this, - pagesCount - }); - }, () => {}); - this._onBeforeDraw = evt => { - const pageView = this._pages[evt.pageNumber - 1]; - if (!pageView) { - return; - } - this.#buffer.push(pageView); - }; - this.eventBus._on("pagerender", this._onBeforeDraw); - this._onAfterDraw = evt => { - if (evt.cssTransform) { - return; - } - this._onePageRenderedCapability.resolve({ - timestamp: evt.timestamp - }); - this.eventBus._off("pagerendered", this._onAfterDraw); - this._onAfterDraw = null; - }; - this.eventBus._on("pagerendered", this._onAfterDraw); - Promise.all([firstPagePromise, permissionsPromise]).then(([firstPdfPage, permissions]) => { - if (pdfDocument !== this.pdfDocument) { - return; - } - this._firstPageCapability.resolve(firstPdfPage); - this._optionalContentConfigPromise = optionalContentConfigPromise; - const { - annotationEditorMode, - annotationMode, - textLayerMode - } = this.#initializePermissions(permissions); - if (textLayerMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.TextLayerMode.DISABLE) { - const element = this.#hiddenCopyElement = document.createElement("div"); - element.id = "hiddenCopyElement"; - this.viewer.before(element); - } - if (annotationEditorMode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE) { - const mode = annotationEditorMode; - if (pdfDocument.isPureXfa) { - console.warn("Warning: XFA-editing is not implemented."); - } else if (isValidAnnotationEditorMode(mode)) { - this.#annotationEditorUIManager = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorUIManager(this.container, this.viewer, this.#altTextManager, this.eventBus, pdfDocument, this.pageColors, this.#annotationEditorHighlightColors, this.#enableHighlightFloatingButton, this.#mlManager); - this.eventBus.dispatch("annotationeditoruimanager", { - source: this, - uiManager: this.#annotationEditorUIManager - }); - if (mode !== pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE) { - this.#annotationEditorUIManager.updateMode(mode); - } - } else { - console.error(`Invalid AnnotationEditor mode: ${mode}`); - } - } - const viewerElement = this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE ? null : this.viewer; - const scale = this.currentScale; - const viewport = firstPdfPage.getViewport({ - scale: scale * pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS - }); - this.viewer.style.setProperty("--scale-factor", viewport.scale); - if (this.pageColors?.foreground === "CanvasText" || this.pageColors?.background === "Canvas") { - this.viewer.style.setProperty("--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight", "CanvasText", "Canvas", "HighlightText", "Highlight")); - this.viewer.style.setProperty("--hcm-highlight-selected-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight_selected", "CanvasText", "Canvas", "HighlightText", "ButtonText")); - } - for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { - const pageView = new _pdf_page_view_js__WEBPACK_IMPORTED_MODULE_3__.PDFPageView({ - container: viewerElement, - eventBus: this.eventBus, - id: pageNum, - scale, - defaultViewport: viewport.clone(), - optionalContentConfigPromise, - renderingQueue: this.renderingQueue, - textLayerMode, - annotationMode, - imageResourcesPath: this.imageResourcesPath, - maxCanvasPixels: this.maxCanvasPixels, - pageColors: this.pageColors, - l10n: this.l10n, - layerProperties: this._layerProperties - }); - this._pages.push(pageView); - } - this._pages[0]?.setPdfPage(firstPdfPage); - if (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) { - this.#ensurePageViewVisible(); - } else if (this._spreadMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE) { - this._updateSpreadMode(); - } - this.#onePageRenderedOrForceFetch().then(async () => { - this.findController?.setDocument(pdfDocument); - this._scriptingManager?.setDocument(pdfDocument); - if (this.#hiddenCopyElement) { - this.#copyCallbackBound = this.#copyCallback.bind(this, textLayerMode); - document.addEventListener("copy", this.#copyCallbackBound); - } - if (this.#annotationEditorUIManager) { - this.eventBus.dispatch("annotationeditormodechanged", { - source: this, - mode: this.#annotationEditorMode - }); - } - if (pdfDocument.loadingParams.disableAutoFetch || pagesCount > PagesCountLimit.FORCE_LAZY_PAGE_INIT) { - this._pagesCapability.resolve(); - return; - } - let getPagesLeft = pagesCount - 1; - if (getPagesLeft <= 0) { - this._pagesCapability.resolve(); - return; - } - for (let pageNum = 2; pageNum <= pagesCount; ++pageNum) { - const promise = pdfDocument.getPage(pageNum).then(pdfPage => { - const pageView = this._pages[pageNum - 1]; - if (!pageView.pdfPage) { - pageView.setPdfPage(pdfPage); - } - if (--getPagesLeft === 0) { - this._pagesCapability.resolve(); - } - }, reason => { - console.error(`Unable to get page ${pageNum} to initialize viewer`, reason); - if (--getPagesLeft === 0) { - this._pagesCapability.resolve(); - } - }); - if (pageNum % PagesCountLimit.PAUSE_EAGER_PAGE_INIT === 0) { - await promise; - } - } - }); - this.eventBus.dispatch("pagesinit", { - source: this - }); - pdfDocument.getMetadata().then(({ - info - }) => { - if (pdfDocument !== this.pdfDocument) { - return; - } - if (info.Language) { - this.viewer.lang = info.Language; - } - }); - if (this.defaultRenderingQueue) { - this.update(); - } - }).catch(reason => { - console.error("Unable to initialize viewer", reason); - this._pagesCapability.reject(reason); - }); - } - setPageLabels(labels) { - if (!this.pdfDocument) { - return; - } - if (!labels) { - this._pageLabels = null; - } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) { - this._pageLabels = null; - console.error(`setPageLabels: Invalid page labels.`); - } else { - this._pageLabels = labels; - } - for (let i = 0, ii = this._pages.length; i < ii; i++) { - this._pages[i].setPageLabel(this._pageLabels?.[i] ?? null); - } - } - _resetView() { - this._pages = []; - this._currentPageNumber = 1; - this._currentScale = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.UNKNOWN_SCALE; - this._currentScaleValue = null; - this._pageLabels = null; - this.#buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE); - this._location = null; - this._pagesRotation = 0; - this._optionalContentConfigPromise = null; - this._firstPageCapability = Promise.withResolvers(); - this._onePageRenderedCapability = Promise.withResolvers(); - this._pagesCapability = Promise.withResolvers(); - this._scrollMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.VERTICAL; - this._previousScrollMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.UNKNOWN; - this._spreadMode = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE; - this.#scrollModePageState = { - previousPageNumber: 1, - scrollDown: true, - pages: [] - }; - if (this._onBeforeDraw) { - this.eventBus._off("pagerender", this._onBeforeDraw); - this._onBeforeDraw = null; - } - if (this._onAfterDraw) { - this.eventBus._off("pagerendered", this._onAfterDraw); - this._onAfterDraw = null; - } - if (this.#onVisibilityChange) { - document.removeEventListener("visibilitychange", this.#onVisibilityChange); - this.#onVisibilityChange = null; - } - this.viewer.textContent = ""; - this._updateScrollMode(); - this.viewer.removeAttribute("lang"); - if (this.#hiddenCopyElement) { - document.removeEventListener("copy", this.#copyCallbackBound); - this.#copyCallbackBound = null; - this.#hiddenCopyElement.remove(); - this.#hiddenCopyElement = null; - } - } - #ensurePageViewVisible() { - if (this._scrollMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) { - throw new Error("#ensurePageViewVisible: Invalid scrollMode value."); - } - const pageNumber = this._currentPageNumber, - state = this.#scrollModePageState, - viewer = this.viewer; - viewer.textContent = ""; - state.pages.length = 0; - if (this._spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE && !this.isInPresentationMode) { - const pageView = this._pages[pageNumber - 1]; - viewer.append(pageView.div); - state.pages.push(pageView); - } else { - const pageIndexSet = new Set(), - parity = this._spreadMode - 1; - if (parity === -1) { - pageIndexSet.add(pageNumber - 1); - } else if (pageNumber % 2 !== parity) { - pageIndexSet.add(pageNumber - 1); - pageIndexSet.add(pageNumber); - } else { - pageIndexSet.add(pageNumber - 2); - pageIndexSet.add(pageNumber - 1); - } - const spread = document.createElement("div"); - spread.className = "spread"; - if (this.isInPresentationMode) { - const dummyPage = document.createElement("div"); - dummyPage.className = "dummyPage"; - spread.append(dummyPage); - } - for (const i of pageIndexSet) { - const pageView = this._pages[i]; - if (!pageView) { - continue; - } - spread.append(pageView.div); - state.pages.push(pageView); - } - viewer.append(spread); - } - state.scrollDown = pageNumber >= state.previousPageNumber; - state.previousPageNumber = pageNumber; - } - _scrollUpdate() { - if (this.pagesCount === 0) { - return; - } - this.update(); - } - #scrollIntoView(pageView, pageSpot = null) { - const { - div, - id - } = pageView; - if (this._currentPageNumber !== id) { - this._setCurrentPageNumber(id); - } - if (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) { - this.#ensurePageViewVisible(); - this.update(); - } - if (!pageSpot && !this.isInPresentationMode) { - const left = div.offsetLeft + div.clientLeft, - right = left + div.clientWidth; - const { - scrollLeft, - clientWidth - } = this.container; - if (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) { - pageSpot = { - left: 0, - top: 0 - }; - } - } - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.scrollIntoView)(div, pageSpot); - if (!this._currentScaleValue && this._location) { - this._location = null; - } - } - #isSameScale(newScale) { - return newScale === this._currentScale || Math.abs(newScale - this._currentScale) < 1e-15; - } - #setScaleUpdatePages(newScale, newValue, { - noScroll = false, - preset = false, - drawingDelay = -1 - }) { - this._currentScaleValue = newValue.toString(); - if (this.#isSameScale(newScale)) { - if (preset) { - this.eventBus.dispatch("scalechanging", { - source: this, - scale: newScale, - presetValue: newValue - }); - } - return; - } - this.viewer.style.setProperty("--scale-factor", newScale * pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS); - const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000; - this.refresh(true, { - scale: newScale, - drawingDelay: postponeDrawing ? drawingDelay : -1 - }); - if (postponeDrawing) { - this.#scaleTimeoutId = setTimeout(() => { - this.#scaleTimeoutId = null; - this.refresh(); - }, drawingDelay); - } - this._currentScale = newScale; - if (!noScroll) { - let page = this._currentPageNumber, - dest; - if (this._location && !(this.isInPresentationMode || this.isChangingPresentationMode)) { - page = this._location.pageNumber; - dest = [null, { - name: "XYZ" - }, this._location.left, this._location.top, null]; - } - this.scrollPageIntoView({ - pageNumber: page, - destArray: dest, - allowNegativeOffset: true - }); - } - this.eventBus.dispatch("scalechanging", { - source: this, - scale: newScale, - presetValue: preset ? newValue : undefined - }); - if (this.defaultRenderingQueue) { - this.update(); - } - } - get #pageWidthScaleFactor() { - if (this._spreadMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE && this._scrollMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL) { - return 2; - } - return 1; - } - #setScale(value, options) { - let scale = parseFloat(value); - if (scale > 0) { - options.preset = false; - this.#setScaleUpdatePages(scale, value, options); - } else { - const currentPage = this._pages[this._currentPageNumber - 1]; - if (!currentPage) { - return; - } - let hPadding = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SCROLLBAR_PADDING, - vPadding = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.VERTICAL_PADDING; - if (this.isInPresentationMode) { - hPadding = vPadding = 4; - if (this._spreadMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE) { - hPadding *= 2; - } - } else if (this.removePageBorders) { - hPadding = vPadding = 0; - } else if (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL) { - [hPadding, vPadding] = [vPadding, hPadding]; - } - const pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale / this.#pageWidthScaleFactor; - const pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale; - switch (value) { - case "page-actual": - scale = 1; - break; - case "page-width": - scale = pageWidthScale; - break; - case "page-height": - scale = pageHeightScale; - break; - case "page-fit": - scale = Math.min(pageWidthScale, pageHeightScale); - break; - case "auto": - const horizontalScale = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.isPortraitOrientation)(currentPage) ? pageWidthScale : Math.min(pageHeightScale, pageWidthScale); - scale = Math.min(_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MAX_AUTO_SCALE, horizontalScale); - break; - default: - console.error(`#setScale: "${value}" is an unknown zoom value.`); - return; - } - options.preset = true; - this.#setScaleUpdatePages(scale, value, options); - } - } - #resetCurrentPageView() { - const pageView = this._pages[this._currentPageNumber - 1]; - if (this.isInPresentationMode) { - this.#setScale(this._currentScaleValue, { - noScroll: true - }); - } - this.#scrollIntoView(pageView); - } - pageLabelToPageNumber(label) { - if (!this._pageLabels) { - return null; - } - const i = this._pageLabels.indexOf(label); - if (i < 0) { - return null; - } - return i + 1; - } - scrollPageIntoView({ - pageNumber, - destArray = null, - allowNegativeOffset = false, - ignoreDestinationZoom = false - }) { - if (!this.pdfDocument) { - return; - } - const pageView = Number.isInteger(pageNumber) && this._pages[pageNumber - 1]; - if (!pageView) { - console.error(`scrollPageIntoView: "${pageNumber}" is not a valid pageNumber parameter.`); - return; - } - if (this.isInPresentationMode || !destArray) { - // [custom] 图片视图切换 pageNumber - // console.log('test-setCurrent-2', pageNumber, destArray, this.isInPresentationMode) - this._setCurrentPageNumber(pageNumber, true); - return; - } - let x = 0, - y = 0; - let width = 0, - height = 0, - widthScale, - heightScale; - const changeOrientation = pageView.rotation % 180 !== 0; - const pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS; - const pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS; - let scale = 0; - switch (destArray[1].name) { - case "XYZ": - x = destArray[2]; - y = destArray[3]; - scale = destArray[4]; - x = x !== null ? x : 0; - y = y !== null ? y : pageHeight; - break; - case "Fit": - case "FitB": - scale = "page-fit"; - break; - case "FitH": - case "FitBH": - y = destArray[2]; - scale = "page-width"; - if (y === null && this._location) { - x = this._location.left; - y = this._location.top; - } else if (typeof y !== "number" || y < 0) { - y = pageHeight; - } - break; - case "FitV": - case "FitBV": - x = destArray[2]; - width = pageWidth; - height = pageHeight; - scale = "page-height"; - break; - case "FitR": - x = destArray[2]; - y = destArray[3]; - width = destArray[4] - x; - height = destArray[5] - y; - let hPadding = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SCROLLBAR_PADDING, - vPadding = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.VERTICAL_PADDING; - if (this.removePageBorders) { - hPadding = vPadding = 0; - } - widthScale = (this.container.clientWidth - hPadding) / width / pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS; - heightScale = (this.container.clientHeight - vPadding) / height / pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS; - scale = Math.min(Math.abs(widthScale), Math.abs(heightScale)); - break; - default: - console.error(`scrollPageIntoView: "${destArray[1].name}" is not a valid destination type.`); - return; - } - if (!ignoreDestinationZoom) { - if (scale && scale !== this._currentScale) { - this.currentScaleValue = scale; - } else if (this._currentScale === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.UNKNOWN_SCALE) { - this.currentScaleValue = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE_VALUE; - } - } - if (scale === "page-fit" && !destArray[4]) { - this.#scrollIntoView(pageView); - return; - } - const boundingRect = [pageView.viewport.convertToViewportPoint(x, y), pageView.viewport.convertToViewportPoint(x + width, y + height)]; - let left = Math.min(boundingRect[0][0], boundingRect[1][0]); - let top = Math.min(boundingRect[0][1], boundingRect[1][1]); - if (!allowNegativeOffset) { - left = Math.max(left, 0); - top = Math.max(top, 0); - } - this.#scrollIntoView(pageView, { - left, - top - }); - } - _updateLocation(firstPage) { - const currentScale = this._currentScale; - const currentScaleValue = this._currentScaleValue; - const normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue; - const pageNumber = firstPage.id; - const currentPageView = this._pages[pageNumber - 1]; - const container = this.container; - const topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y); - const intLeft = Math.round(topLeft[0]); - const intTop = Math.round(topLeft[1]); - let pdfOpenParams = `#page=${pageNumber}`; - if (!this.isInPresentationMode) { - pdfOpenParams += `&zoom=${normalizedScaleValue},${intLeft},${intTop}`; - } - this._location = { - pageNumber, - scale: normalizedScaleValue, - top: intTop, - left: intLeft, - rotation: this._pagesRotation, - pdfOpenParams - }; - } - update() { - const visible = this._getVisiblePages(); - const visiblePages = visible.views, - numVisiblePages = visiblePages.length; - if (numVisiblePages === 0) { - return; - } - const newCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * numVisiblePages + 1); - this.#buffer.resize(newCacheSize, visible.ids); - this.renderingQueue.renderHighestPriority(visible); - const isSimpleLayout = this._spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE && (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE || this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.VERTICAL); - const currentId = this._currentPageNumber; - let stillFullyVisible = false; - for (const page of visiblePages) { - if (page.percent < 100) { - break; - } - if (page.id === currentId && isSimpleLayout) { - stillFullyVisible = true; - break; - } - } - - this._setCurrentPageNumber(stillFullyVisible ? currentId : visiblePages[0].id); - this._updateLocation(visible.first); - this.eventBus.dispatch("updateviewarea", { - source: this, - location: this._location - }); - } - containsElement(element) { - return this.container.contains(element); - } - focus() { - this.container.focus(); - } - get _isContainerRtl() { - return getComputedStyle(this.container).direction === "rtl"; - } - get isInPresentationMode() { - return this.presentationModeState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.FULLSCREEN; - } - get isChangingPresentationMode() { - return this.presentationModeState === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.PresentationModeState.CHANGING; - } - get isHorizontalScrollbarEnabled() { - return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth; - } - get isVerticalScrollbarEnabled() { - return this.isInPresentationMode ? false : this.container.scrollHeight > this.container.clientHeight; - } - _getVisiblePages() { - - const views = this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE ? this.#scrollModePageState.pages : this._pages, - horizontal = this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL, - rtl = horizontal && this._isContainerRtl; - // console.log('test-views',views,horizontal, rtl ) - return (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.getVisibleElements)({ - scrollEl: this.container, - views, - sortByVisibility: true, - horizontal, - rtl - }); - } - cleanup() { - for (const pageView of this._pages) { - if (pageView.renderingState !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.RenderingStates.FINISHED) { - pageView.reset(); - } - } - } - _cancelRendering() { - for (const pageView of this._pages) { - pageView.cancelRendering(); - } - } - async #ensurePdfPageLoaded(pageView) { - if (pageView.pdfPage) { - return pageView.pdfPage; - } - try { - const pdfPage = await this.pdfDocument.getPage(pageView.id); - if (!pageView.pdfPage) { - pageView.setPdfPage(pdfPage); - } - return pdfPage; - } catch (reason) { - console.error("Unable to get page for page view", reason); - return null; - } - } - #getScrollAhead(visible) { - if (visible.first?.id === 1) { - return true; - } else if (visible.last?.id === this.pagesCount) { - return false; - } - switch (this._scrollMode) { - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE: - return this.#scrollModePageState.scrollDown; - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL: - return this.scroll.right; - } - return this.scroll.down; - } - forceRendering(currentlyVisiblePages) { - const visiblePages = currentlyVisiblePages || this._getVisiblePages(); - const scrollAhead = this.#getScrollAhead(visiblePages); - const preRenderExtra = this._spreadMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE && this._scrollMode !== _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL; - const pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead, preRenderExtra); - if (pageView) { - this.#ensurePdfPageLoaded(pageView).then(() => { - this.renderingQueue.renderView(pageView); - }); - return true; - } - return false; - } - get hasEqualPageSizes() { - const firstPageView = this._pages[0]; - for (let i = 1, ii = this._pages.length; i < ii; ++i) { - const pageView = this._pages[i]; - if (pageView.width !== firstPageView.width || pageView.height !== firstPageView.height) { - return false; - } - } - return true; - } - getPagesOverview() { - let initialOrientation; - return this._pages.map(pageView => { - const viewport = pageView.pdfPage.getViewport({ - scale: 1 - }); - const orientation = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.isPortraitOrientation)(viewport); - if (initialOrientation === undefined) { - initialOrientation = orientation; - } else if (this.enablePrintAutoRotate && orientation !== initialOrientation) { - return { - width: viewport.height, - height: viewport.width, - rotation: (viewport.rotation - 90) % 360 - }; - } - return { - width: viewport.width, - height: viewport.height, - rotation: viewport.rotation - }; - }); - } - get optionalContentConfigPromise() { - if (!this.pdfDocument) { - return Promise.resolve(null); - } - if (!this._optionalContentConfigPromise) { - console.error("optionalContentConfigPromise: Not initialized yet."); - return this.pdfDocument.getOptionalContentConfig({ - intent: "display" - }); - } - return this._optionalContentConfigPromise; - } - set optionalContentConfigPromise(promise) { - if (!(promise instanceof Promise)) { - throw new Error(`Invalid optionalContentConfigPromise: ${promise}`); - } - if (!this.pdfDocument) { - return; - } - if (!this._optionalContentConfigPromise) { - return; - } - this._optionalContentConfigPromise = promise; - this.refresh(false, { - optionalContentConfigPromise: promise - }); - this.eventBus.dispatch("optionalcontentconfigchanged", { - source: this, - promise - }); - } - get scrollMode() { - return this._scrollMode; - } - set scrollMode(mode) { - - if (this._scrollMode === mode) { - return; - } - if (!(0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.isValidScrollMode)(mode)) { - throw new Error(`Invalid scroll mode: ${mode}`); - } - if (this.pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) { - return; - } - this._previousScrollMode = this._scrollMode; - this._scrollMode = mode; - this.eventBus.dispatch("scrollmodechanged", { - source: this, - mode - }); - this._updateScrollMode(this._currentPageNumber); - } - _updateScrollMode(pageNumber = null) { - const scrollMode = this._scrollMode, - viewer = this.viewer; - viewer.classList.toggle("scrollHorizontal", scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL); - viewer.classList.toggle("scrollWrapped", scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.WRAPPED); - if (!this.pdfDocument || !pageNumber) { - return; - } - if (scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) { - this.#ensurePageViewVisible(); - } else if (this._previousScrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) { - this._updateSpreadMode(); - } - if (this._currentScaleValue && isNaN(this._currentScaleValue)) { - this.#setScale(this._currentScaleValue, { - noScroll: true - }); - } - this._setCurrentPageNumber(pageNumber, true); - this.update(); - } - get spreadMode() { - return this._spreadMode; - } - set spreadMode(mode) { - if (this._spreadMode === mode) { - return; - } - if (!(0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.isValidSpreadMode)(mode)) { - throw new Error(`Invalid spread mode: ${mode}`); - } - this._spreadMode = mode; - this.eventBus.dispatch("spreadmodechanged", { - source: this, - mode - }); - this._updateSpreadMode(this._currentPageNumber); - } - _updateSpreadMode(pageNumber = null) { - if (!this.pdfDocument) { - return; - } - const viewer = this.viewer, - pages = this._pages; - if (this._scrollMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE) { - this.#ensurePageViewVisible(); - } else { - viewer.textContent = ""; - if (this._spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE) { - for (const pageView of this._pages) { - viewer.append(pageView.div); - } - } else { - const parity = this._spreadMode - 1; - let spread = null; - for (let i = 0, ii = pages.length; i < ii; ++i) { - if (spread === null) { - spread = document.createElement("div"); - spread.className = "spread"; - viewer.append(spread); - } else if (i % 2 === parity) { - spread = spread.cloneNode(false); - viewer.append(spread); - } - spread.append(pages[i].div); - } - } - } - if (!pageNumber) { - return; - } - if (this._currentScaleValue && isNaN(this._currentScaleValue)) { - this.#setScale(this._currentScaleValue, { - noScroll: true - }); - } - this._setCurrentPageNumber(pageNumber, true); - this.update(); - } - _getPageAdvance(currentPageNumber, previous = false) { - switch (this._scrollMode) { - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.WRAPPED: - { - const { - views - } = this._getVisiblePages(), - pageLayout = new Map(); - for (const { - id, - y, - percent, - widthPercent - } of views) { - if (percent === 0 || widthPercent < 100) { - continue; - } - let yArray = pageLayout.get(y); - if (!yArray) { - pageLayout.set(y, yArray ||= []); - } - yArray.push(id); - } - for (const yArray of pageLayout.values()) { - const currentIndex = yArray.indexOf(currentPageNumber); - if (currentIndex === -1) { - continue; - } - const numPages = yArray.length; - if (numPages === 1) { - break; - } - if (previous) { - for (let i = currentIndex - 1, ii = 0; i >= ii; i--) { - const currentId = yArray[i], - expectedId = yArray[i + 1] - 1; - if (currentId < expectedId) { - return currentPageNumber - expectedId; - } - } - } else { - for (let i = currentIndex + 1, ii = numPages; i < ii; i++) { - const currentId = yArray[i], - expectedId = yArray[i - 1] + 1; - if (currentId > expectedId) { - return expectedId - currentPageNumber; - } - } - } - if (previous) { - const firstId = yArray[0]; - if (firstId < currentPageNumber) { - return currentPageNumber - firstId + 1; - } - } else { - const lastId = yArray[numPages - 1]; - if (lastId > currentPageNumber) { - return lastId - currentPageNumber + 1; - } - } - break; - } - break; - } - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.HORIZONTAL: - { - break; - } - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.PAGE: - case _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.ScrollMode.VERTICAL: - { - if (this._spreadMode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.SpreadMode.NONE) { - break; - } - const parity = this._spreadMode - 1; - if (previous && currentPageNumber % 2 !== parity) { - break; - } else if (!previous && currentPageNumber % 2 === parity) { - break; - } - const { - views - } = this._getVisiblePages(), - expectedId = previous ? currentPageNumber - 1 : currentPageNumber + 1; - for (const { - id, - percent, - widthPercent - } of views) { - if (id !== expectedId) { - continue; - } - if (percent > 0 && widthPercent === 100) { - return 2; - } - break; - } - break; - } - } - return 1; - } - nextPage() { - const currentPageNumber = this._currentPageNumber, - pagesCount = this.pagesCount; - if (currentPageNumber >= pagesCount) { - return false; - } - const advance = this._getPageAdvance(currentPageNumber, false) || 1; - this.currentPageNumber = Math.min(currentPageNumber + advance, pagesCount); - return true; - } - previousPage() { - const currentPageNumber = this._currentPageNumber; - if (currentPageNumber <= 1) { - return false; - } - const advance = this._getPageAdvance(currentPageNumber, true) || 1; - this.currentPageNumber = Math.max(currentPageNumber - advance, 1); - return true; - } - increaseScale({ - drawingDelay, - scaleFactor, - steps - } = {}) { - if (!this.pdfDocument) { - return; - } - let newScale = this._currentScale; - if (scaleFactor > 1) { - newScale = Math.round(newScale * scaleFactor * 100) / 100; - } else { - steps ??= 1; - do { - newScale = Math.ceil((newScale * _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10; - } while (--steps > 0 && newScale < _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MAX_SCALE); - } - this.#setScale(Math.min(_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MAX_SCALE, newScale), { - noScroll: false, - drawingDelay - }); - } - decreaseScale({ - drawingDelay, - scaleFactor, - steps - } = {}) { - if (!this.pdfDocument) { - return; - } - let newScale = this._currentScale; - if (scaleFactor > 0 && scaleFactor < 1) { - newScale = Math.round(newScale * scaleFactor * 100) / 100; - } else { - steps ??= 1; - do { - newScale = Math.floor((newScale / _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10; - } while (--steps > 0 && newScale > _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MIN_SCALE); - } - this.#setScale(Math.max(_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MIN_SCALE, newScale), { - noScroll: false, - drawingDelay - }); - } - #updateContainerHeightCss(height = this.container.clientHeight) { - if (height !== this.#previousContainerHeight) { - this.#previousContainerHeight = height; - _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.docStyle.setProperty("--viewer-container-height", `${height}px`); - } - } - #resizeObserverCallback(entries) { - for (const entry of entries) { - if (entry.target === this.container) { - this.#updateContainerHeightCss(Math.floor(entry.borderBoxSize[0].blockSize)); - this.#containerTopLeft = null; - break; - } - } - } - get containerTopLeft() { - return this.#containerTopLeft ||= [this.container.offsetTop, this.container.offsetLeft]; - } - get annotationEditorMode() { - return this.#annotationEditorUIManager ? this.#annotationEditorMode : pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE; - } - set annotationEditorMode({ - mode, - editId = null, - isFromKeyboard = false - }) { - if (!this.#annotationEditorUIManager) { - throw new Error(`The AnnotationEditor is not enabled.`); - } - if (this.#annotationEditorMode === mode) { - return; - } - if (!isValidAnnotationEditorMode(mode)) { - throw new Error(`Invalid AnnotationEditor mode: ${mode}`); - } - if (!this.pdfDocument) { - return; - } - this.#annotationEditorMode = mode; - this.eventBus.dispatch("annotationeditormodechanged", { - source: this, - mode - }); - this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard); - } - set annotationEditorParams({ - type, - value - }) { - if (!this.#annotationEditorUIManager) { - throw new Error(`The AnnotationEditor is not enabled.`); - } - this.#annotationEditorUIManager.updateParams(type, value); - } - refresh(noUpdate = false, updateArgs = Object.create(null)) { - if (!this.pdfDocument) { - return; - } - for (const pageView of this._pages) { - pageView.update(updateArgs); - } - if (this.#scaleTimeoutId !== null) { - clearTimeout(this.#scaleTimeoutId); - this.#scaleTimeoutId = null; - } - if (!noUpdate) { - this.update(); - } - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 2603: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AbortException: () => (/* binding */ AbortException), -/* harmony export */ AnnotationEditorLayer: () => (/* binding */ AnnotationEditorLayer), -/* harmony export */ AnnotationEditorParamsType: () => (/* binding */ AnnotationEditorParamsType), -/* harmony export */ AnnotationEditorType: () => (/* binding */ AnnotationEditorType), -/* harmony export */ AnnotationEditorUIManager: () => (/* binding */ AnnotationEditorUIManager), -/* harmony export */ AnnotationLayer: () => (/* binding */ AnnotationLayer), -/* harmony export */ AnnotationMode: () => (/* binding */ AnnotationMode), -/* harmony export */ ColorPicker: () => (/* binding */ ColorPicker), -/* harmony export */ DOMSVGFactory: () => (/* binding */ DOMSVGFactory), -/* harmony export */ DrawLayer: () => (/* binding */ DrawLayer), -/* harmony export */ GlobalWorkerOptions: () => (/* binding */ GlobalWorkerOptions), -/* harmony export */ InvalidPDFException: () => (/* binding */ InvalidPDFException), -/* harmony export */ MissingPDFException: () => (/* binding */ MissingPDFException), -/* harmony export */ PDFDateString: () => (/* binding */ PDFDateString), -/* harmony export */ PDFWorker: () => (/* binding */ PDFWorker), -/* harmony export */ PasswordResponses: () => (/* binding */ PasswordResponses), -/* harmony export */ PermissionFlag: () => (/* binding */ PermissionFlag), -/* harmony export */ PixelsPerInch: () => (/* binding */ PixelsPerInch), -/* harmony export */ RenderingCancelledException: () => (/* binding */ RenderingCancelledException), -/* harmony export */ UnexpectedResponseException: () => (/* binding */ UnexpectedResponseException), -/* harmony export */ XfaLayer: () => (/* binding */ XfaLayer), -/* harmony export */ build: () => (/* binding */ build), -/* harmony export */ createValidAbsoluteUrl: () => (/* binding */ createValidAbsoluteUrl), -/* harmony export */ fetchData: () => (/* binding */ fetchData), -/* harmony export */ getDocument: () => (/* binding */ getDocument), -/* harmony export */ getFilenameFromUrl: () => (/* binding */ getFilenameFromUrl), -/* harmony export */ getPdfFilenameFromUrl: () => (/* binding */ getPdfFilenameFromUrl), -/* harmony export */ getXfaPageViewport: () => (/* binding */ getXfaPageViewport), -/* harmony export */ isDataScheme: () => (/* binding */ isDataScheme), -/* harmony export */ isPdfFile: () => (/* binding */ isPdfFile), -/* harmony export */ noContextMenu: () => (/* binding */ noContextMenu), -/* harmony export */ normalizeUnicode: () => (/* binding */ normalizeUnicode), -/* harmony export */ renderTextLayer: () => (/* binding */ renderTextLayer), -/* harmony export */ setLayerDimensions: () => (/* binding */ setLayerDimensions), -/* harmony export */ shadow: () => (/* binding */ shadow), -/* harmony export */ updateTextLayer: () => (/* binding */ updateTextLayer), -/* harmony export */ version: () => (/* binding */ version) -/* harmony export */ }); -/* unused harmony exports CMapCompressionType, FeatureTest, ImageKind, OPS, Outliner, PDFDataRangeTransport, Util, VerbosityLevel */ -if (!globalThis.pdfjsLib) { - await globalThis.pdfjsLibPromise; -} -const { - AbortException, - AnnotationEditorLayer, - AnnotationEditorParamsType, - AnnotationEditorType, - AnnotationEditorUIManager, - AnnotationLayer, - AnnotationMode, - build, - CMapCompressionType, - ColorPicker, - createValidAbsoluteUrl, - DOMSVGFactory, - DrawLayer, - FeatureTest, - fetchData, - getDocument, - getFilenameFromUrl, - getPdfFilenameFromUrl, - getXfaPageViewport, - GlobalWorkerOptions, - ImageKind, - InvalidPDFException, - isDataScheme, - isPdfFile, - MissingPDFException, - noContextMenu, - normalizeUnicode, - OPS, - Outliner, - PasswordResponses, - PDFDataRangeTransport, - PDFDateString, - PDFWorker, - PermissionFlag, - PixelsPerInch, - RenderingCancelledException, - renderTextLayer, - setLayerDimensions, - shadow, - UnexpectedResponseException, - updateTextLayer, - Util, - VerbosityLevel, - version, - XfaLayer -} = globalThis.pdfjsLib; - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }, 1); - -/***/ }), - -/***/ 8224: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ BasePreferences: () => (/* binding */ BasePreferences) -/* harmony export */ }); -/* harmony import */ var _app_options_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9840); - -class BasePreferences { - #browserDefaults = Object.freeze({ - canvasMaxAreaInBytes: -1, - isInAutomation: false, - supportsCaretBrowsingMode: false, - supportsDocumentFonts: true, - supportsIntegratedFind: false, - supportsMouseWheelZoomCtrlKey: true, - supportsMouseWheelZoomMetaKey: true, - supportsPinchToZoom: true - }); - #defaults = Object.freeze({ - annotationEditorMode: 0, - annotationMode: 2, - cursorToolOnLoad: 0, - defaultZoomDelay: 400, - defaultZoomValue: "", - disablePageLabels: false, - enableHighlightEditor: false, - enableHighlightFloatingButton: false, - enableML: false, - enablePermissions: false, - enablePrintAutoRotate: true, - enableScripting: true, - enableStampEditor: true, - externalLinkTarget: 0, - highlightEditorColors: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F", - historyUpdateUrl: false, - ignoreDestinationZoom: false, - forcePageColors: false, - pageColorsBackground: "Canvas", - pageColorsForeground: "CanvasText", - pdfBugEnabled: false, - sidebarViewOnLoad: -1, - scrollModeOnLoad: -1, - spreadModeOnLoad: -1, - textLayerMode: 1, - viewOnLoad: 0, - disableAutoFetch: false, - disableFontFace: false, - disableRange: false, - disableStream: false, - enableXfa: true, - viewerCssTheme: 0 - }); - #prefs = Object.create(null); - #initializedPromise = null; - constructor() { - if (this.constructor === BasePreferences) { - throw new Error("Cannot initialize BasePreferences."); - } - this.#initializedPromise = this._readFromStorage(this.#defaults).then(({ - browserPrefs, - prefs - }) => { - const options = Object.create(null); - for (const [name, val] of Object.entries(this.#browserDefaults)) { - const prefVal = browserPrefs?.[name]; - options[name] = typeof prefVal === typeof val ? prefVal : val; - } - for (const [name, val] of Object.entries(this.#defaults)) { - const prefVal = prefs?.[name]; - options[name] = this.#prefs[name] = typeof prefVal === typeof val ? prefVal : val; - } - _app_options_js__WEBPACK_IMPORTED_MODULE_0__.AppOptions.setAll(options, true); - }); - } - async _writeToStorage(prefObj) { - throw new Error("Not implemented: _writeToStorage"); - } - async _readFromStorage(prefObj) { - throw new Error("Not implemented: _readFromStorage"); - } - #updatePref({ - name, - value - }) { - throw new Error("Not implemented: #updatePref"); - } - async reset() { - await this.#initializedPromise; - const oldPrefs = structuredClone(this.#prefs); - this.#prefs = Object.create(null); - try { - await this._writeToStorage(this.#defaults); - } catch (reason) { - this.#prefs = oldPrefs; - throw reason; - } - } - async set(name, value) { - await this.#initializedPromise; - const defaultValue = this.#defaults[name], - oldPrefs = structuredClone(this.#prefs); - if (defaultValue === undefined) { - throw new Error(`Set preference: "${name}" is undefined.`); - } else if (value === undefined) { - throw new Error("Set preference: no value is specified."); - } - const valueType = typeof value, - defaultType = typeof defaultValue; - if (valueType !== defaultType) { - if (valueType === "number" && defaultType === "string") { - value = value.toString(); - } else { - throw new Error(`Set preference: "${value}" is a ${valueType}, expected a ${defaultType}.`); - } - } else if (valueType === "number" && !Number.isInteger(value)) { - throw new Error(`Set preference: "${value}" must be an integer.`); - } - this.#prefs[name] = value; - try { - await this._writeToStorage(this.#prefs); - } catch (reason) { - this.#prefs = oldPrefs; - throw reason; - } - } - async get(name) { - await this.#initializedPromise; - const defaultValue = this.#defaults[name]; - if (defaultValue === undefined) { - throw new Error(`Get preference: "${name}" is undefined.`); - } - return this.#prefs[name] ?? defaultValue; - } - get initializedPromise() { - return this.#initializedPromise; - } -} - - -/***/ }), - -/***/ 659: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ getXfaHtmlForPrinting: () => (/* binding */ getXfaHtmlForPrinting) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -/* harmony import */ var _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(787); -/* harmony import */ var _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2973); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__]); -([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__, _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__); - - - -function getXfaHtmlForPrinting(printContainer, pdfDocument) { - const xfaHtml = pdfDocument.allXfaHtml; - const linkService = new _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_1__.SimpleLinkService(); - const scale = Math.round(pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.PixelsPerInch.PDF_TO_CSS_UNITS * 100) / 100; - for (const xfaPage of xfaHtml.children) { - const page = document.createElement("div"); - page.className = "xfaPrintedPage"; - printContainer.append(page); - const builder = new _xfa_layer_builder_js__WEBPACK_IMPORTED_MODULE_2__.XfaLayerBuilder({ - pdfPage: null, - annotationStorage: pdfDocument.annotationStorage, - linkService, - xfaHtml: xfaPage - }); - const viewport = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.getXfaPageViewport)(xfaPage, { - scale - }); - builder.render(viewport, "print"); - page.append(builder.div); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 1900: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ SecondaryToolbar: () => (/* binding */ SecondaryToolbar) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); -/* harmony import */ var _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6285); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_pdf_viewer_js__WEBPACK_IMPORTED_MODULE_1__]); -_pdf_viewer_js__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -class SecondaryToolbar { - #opts; - constructor(options, eventBus) { - this.#opts = options; - const buttons = [{ - element: options.presentationModeButton, - eventName: "presentationmode", - close: true - }, { - element: options.printButton, - eventName: "print", - close: true - }, { - element: options.downloadButton, - eventName: "download", - close: true - }, { - element: options.viewBookmarkButton, - eventName: null, - close: true - }, { - element: options.firstPageButton, - eventName: "firstpage", - close: true - }, { - element: options.lastPageButton, - eventName: "lastpage", - close: true - }, { - element: options.pageRotateCwButton, - eventName: "rotatecw", - close: false - }, { - element: options.pageRotateCcwButton, - eventName: "rotateccw", - close: false - }, { - element: options.cursorSelectToolButton, - eventName: "switchcursortool", - eventDetails: { - tool: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.SELECT - }, - close: true - }, { - element: options.cursorHandToolButton, - eventName: "switchcursortool", - eventDetails: { - tool: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.HAND - }, - close: true - }, { - element: options.scrollPageButton, - eventName: "switchscrollmode", - eventDetails: { - mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.PAGE - }, - close: true - }, { - element: options.scrollVerticalButton, - eventName: "switchscrollmode", - eventDetails: { - mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.VERTICAL - }, - close: true - }, { - element: options.scrollHorizontalButton, - eventName: "switchscrollmode", - eventDetails: { - mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.HORIZONTAL - }, - close: true - }, { - element: options.scrollWrappedButton, - eventName: "switchscrollmode", - eventDetails: { - mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.WRAPPED - }, - close: true - }, { - element: options.spreadNoneButton, - eventName: "switchspreadmode", - eventDetails: { - mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.NONE - }, - close: true - }, { - element: options.spreadOddButton, - eventName: "switchspreadmode", - eventDetails: { - mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.ODD - }, - close: true - }, { - element: options.spreadEvenButton, - eventName: "switchspreadmode", - eventDetails: { - mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.EVEN - }, - close: true - }, { - element: options.documentPropertiesButton, - eventName: "documentproperties", - close: true - }]; - buttons.push({ - element: options.openFileButton, - eventName: "openfile", - close: true - }); - this.eventBus = eventBus; - this.opened = false; - this.#bindListeners(buttons); - this.reset(); - } - get isOpen() { - return this.opened; - } - setPageNumber(pageNumber) { - this.pageNumber = pageNumber; - this.#updateUIState(); - } - setPagesCount(pagesCount) { - this.pagesCount = pagesCount; - this.#updateUIState(); - } - reset() { - this.pageNumber = 0; - this.pagesCount = 0; - this.#updateUIState(); - this.eventBus.dispatch("switchcursortool", { - source: this, - reset: true - }); - this.#scrollModeChanged({ - mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.VERTICAL - }); - this.#spreadModeChanged({ - mode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.NONE - }); - } - #updateUIState() { - const { - firstPageButton, - lastPageButton, - pageRotateCwButton, - pageRotateCcwButton - } = this.#opts; - firstPageButton.disabled = this.pageNumber <= 1; - lastPageButton.disabled = this.pageNumber >= this.pagesCount; - pageRotateCwButton.disabled = this.pagesCount === 0; - pageRotateCcwButton.disabled = this.pagesCount === 0; - } - #bindListeners(buttons) { - const { - eventBus - } = this; - const { - toggleButton - } = this.#opts; - toggleButton.addEventListener("click", this.toggle.bind(this)); - for (const { - element, - eventName, - close, - eventDetails - } of buttons) { - element.addEventListener("click", evt => { - if (eventName !== null) { - eventBus.dispatch(eventName, { - source: this, - ...eventDetails - }); - } - if (close) { - this.close(); - } - eventBus.dispatch("reporttelemetry", { - source: this, - details: { - type: "buttons", - data: { - id: element.id - } - } - }); - }); - } - eventBus._on("cursortoolchanged", this.#cursorToolChanged.bind(this)); - eventBus._on("scrollmodechanged", this.#scrollModeChanged.bind(this)); - eventBus._on("spreadmodechanged", this.#spreadModeChanged.bind(this)); - } - #cursorToolChanged({ - tool - }) { - const { - cursorSelectToolButton, - cursorHandToolButton - } = this.#opts; - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(cursorSelectToolButton, tool === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.SELECT); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(cursorHandToolButton, tool === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.CursorTool.HAND); - } - #scrollModeChanged({ - mode - }) { - const { - scrollPageButton, - scrollVerticalButton, - scrollHorizontalButton, - scrollWrappedButton, - spreadNoneButton, - spreadOddButton, - spreadEvenButton - } = this.#opts; - - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(scrollPageButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.PAGE); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(scrollVerticalButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.VERTICAL); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(scrollHorizontalButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.HORIZONTAL); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(scrollWrappedButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.WRAPPED); - const forceScrollModePage = this.pagesCount > _pdf_viewer_js__WEBPACK_IMPORTED_MODULE_1__.PagesCountLimit.FORCE_SCROLL_MODE_PAGE; - scrollPageButton.disabled = forceScrollModePage; - scrollVerticalButton.disabled = forceScrollModePage; - scrollHorizontalButton.disabled = forceScrollModePage; - scrollWrappedButton.disabled = forceScrollModePage; - const isHorizontal = mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.ScrollMode.HORIZONTAL; - spreadNoneButton.disabled = isHorizontal; - spreadOddButton.disabled = isHorizontal; - spreadEvenButton.disabled = isHorizontal; - } - #spreadModeChanged({ - mode - }) { - const { - spreadNoneButton, - spreadOddButton, - spreadEvenButton - } = this.#opts; - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(spreadNoneButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.NONE); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(spreadOddButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.ODD); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleCheckedBtn)(spreadEvenButton, mode === _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode.EVEN); - } - open() { - if (this.opened) { - return; - } - this.opened = true; - const { - toggleButton, - toolbar - } = this.#opts; - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleExpandedBtn)(toggleButton, true, toolbar); - } - close() { - if (!this.opened) { - return; - } - this.opened = false; - const { - toggleButton, - toolbar - } = this.#opts; - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.toggleExpandedBtn)(toggleButton, false, toolbar); - } - toggle() { - if (this.opened) { - this.close(); - } else { - this.open(); - } - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 6698: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ StructTreeLayerBuilder: () => (/* binding */ StructTreeLayerBuilder) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); - -const PDF_ROLE_TO_HTML_ROLE = { - Document: null, - DocumentFragment: null, - Part: "group", - Sect: "group", - Div: "group", - Aside: "note", - NonStruct: "none", - P: null, - H: "heading", - Title: null, - FENote: "note", - Sub: "group", - Lbl: null, - Span: null, - Em: null, - Strong: null, - Link: "link", - Annot: "note", - Form: "form", - Ruby: null, - RB: null, - RT: null, - RP: null, - Warichu: null, - WT: null, - WP: null, - L: "list", - LI: "listitem", - LBody: null, - Table: "table", - TR: "row", - TH: "columnheader", - TD: "cell", - THead: "columnheader", - TBody: null, - TFoot: null, - Caption: null, - Figure: "figure", - Formula: null, - Artifact: null -}; -const HEADING_PATTERN = /^H(\d+)$/; -class StructTreeLayerBuilder { - #treeDom = undefined; - get renderingDone() { - return this.#treeDom !== undefined; - } - render(structTree) { - if (this.#treeDom !== undefined) { - return this.#treeDom; - } - const treeDom = this.#walk(structTree); - treeDom?.classList.add("structTree"); - return this.#treeDom = treeDom; - } - hide() { - if (this.#treeDom && !this.#treeDom.hidden) { - this.#treeDom.hidden = true; - } - } - show() { - if (this.#treeDom?.hidden) { - this.#treeDom.hidden = false; - } - } - #setAttributes(structElement, htmlElement) { - const { - alt, - id, - lang - } = structElement; - if (alt !== undefined) { - htmlElement.setAttribute("aria-label", (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.removeNullCharacters)(alt)); - } - if (id !== undefined) { - htmlElement.setAttribute("aria-owns", id); - } - if (lang !== undefined) { - htmlElement.setAttribute("lang", (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.removeNullCharacters)(lang, true)); - } - } - #walk(node) { - if (!node) { - return null; - } - const element = document.createElement("span"); - if ("role" in node) { - const { - role - } = node; - const match = role.match(HEADING_PATTERN); - if (match) { - element.setAttribute("role", "heading"); - element.setAttribute("aria-level", match[1]); - } else if (PDF_ROLE_TO_HTML_ROLE[role]) { - element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]); - } - } - this.#setAttributes(node, element); - if (node.children) { - if (node.children.length === 1 && "id" in node.children[0]) { - this.#setAttributes(node.children[0], element); - } else { - for (const kid of node.children) { - element.append(this.#walk(kid)); - } - } - } - return element; - } -} - - -/***/ }), - -/***/ 5860: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ TextAccessibilityManager: () => (/* binding */ TextAccessibilityManager) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); - -class TextAccessibilityManager { - #enabled = false; - #textChildren = null; - #textNodes = new Map(); - #waitingElements = new Map(); - setTextMapping(textDivs) { - this.#textChildren = textDivs; - } - static #compareElementPositions(e1, e2) { - const rect1 = e1.getBoundingClientRect(); - const rect2 = e2.getBoundingClientRect(); - if (rect1.width === 0 && rect1.height === 0) { - return +1; - } - if (rect2.width === 0 && rect2.height === 0) { - return -1; - } - const top1 = rect1.y; - const bot1 = rect1.y + rect1.height; - const mid1 = rect1.y + rect1.height / 2; - const top2 = rect2.y; - const bot2 = rect2.y + rect2.height; - const mid2 = rect2.y + rect2.height / 2; - if (mid1 <= top2 && mid2 >= bot1) { - return -1; - } - if (mid2 <= top1 && mid1 >= bot2) { - return +1; - } - const centerX1 = rect1.x + rect1.width / 2; - const centerX2 = rect2.x + rect2.width / 2; - return centerX1 - centerX2; - } - enable() { - if (this.#enabled) { - throw new Error("TextAccessibilityManager is already enabled."); - } - if (!this.#textChildren) { - throw new Error("Text divs and strings have not been set."); - } - this.#enabled = true; - this.#textChildren = this.#textChildren.slice(); - this.#textChildren.sort(TextAccessibilityManager.#compareElementPositions); - if (this.#textNodes.size > 0) { - const textChildren = this.#textChildren; - for (const [id, nodeIndex] of this.#textNodes) { - const element = document.getElementById(id); - if (!element) { - this.#textNodes.delete(id); - continue; - } - this.#addIdToAriaOwns(id, textChildren[nodeIndex]); - } - } - for (const [element, isRemovable] of this.#waitingElements) { - this.addPointerInTextLayer(element, isRemovable); - } - this.#waitingElements.clear(); - } - disable() { - if (!this.#enabled) { - return; - } - this.#waitingElements.clear(); - this.#textChildren = null; - this.#enabled = false; - } - removePointerInTextLayer(element) { - if (!this.#enabled) { - this.#waitingElements.delete(element); - return; - } - const children = this.#textChildren; - if (!children || children.length === 0) { - return; - } - const { - id - } = element; - const nodeIndex = this.#textNodes.get(id); - if (nodeIndex === undefined) { - return; - } - const node = children[nodeIndex]; - this.#textNodes.delete(id); - let owns = node.getAttribute("aria-owns"); - if (owns?.includes(id)) { - owns = owns.split(" ").filter(x => x !== id).join(" "); - if (owns) { - node.setAttribute("aria-owns", owns); - } else { - node.removeAttribute("aria-owns"); - node.setAttribute("role", "presentation"); - } - } - } - #addIdToAriaOwns(id, node) { - const owns = node.getAttribute("aria-owns"); - if (!owns?.includes(id)) { - node.setAttribute("aria-owns", owns ? `${owns} ${id}` : id); - } - node.removeAttribute("role"); - } - addPointerInTextLayer(element, isRemovable) { - const { - id - } = element; - if (!id) { - return null; - } - if (!this.#enabled) { - this.#waitingElements.set(element, isRemovable); - return null; - } - if (isRemovable) { - this.removePointerInTextLayer(element); - } - const children = this.#textChildren; - if (!children || children.length === 0) { - return null; - } - const index = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.binarySearchFirstItem)(children, node => TextAccessibilityManager.#compareElementPositions(element, node) < 0); - const nodeIndex = Math.max(0, index - 1); - const child = children[nodeIndex]; - this.#addIdToAriaOwns(id, child); - this.#textNodes.set(id, nodeIndex); - const parent = child.parentNode; - return parent?.classList.contains("markedContent") ? parent.id : null; - } - moveElementInDOM(container, element, contentElement, isRemovable) { - const id = this.addPointerInTextLayer(contentElement, isRemovable); - if (!container.hasChildNodes()) { - container.append(element); - return id; - } - const children = Array.from(container.childNodes).filter(node => node !== element); - if (children.length === 0) { - return id; - } - const elementToCompare = contentElement || element; - const index = (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.binarySearchFirstItem)(children, node => TextAccessibilityManager.#compareElementPositions(elementToCompare, node) < 0); - if (index === 0) { - children[0].before(element); - } else { - children[index - 1].after(element); - } - return id; - } -} - - -/***/ }), - -/***/ 2027: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ TextHighlighter: () => (/* binding */ TextHighlighter) -/* harmony export */ }); -class TextHighlighter { - #eventAbortController = null; - constructor({ - findController, - eventBus, - pageIndex - }) { - this.findController = findController; - this.matches = []; - this.eventBus = eventBus; - this.pageIdx = pageIndex; - this.textDivs = null; - this.textContentItemsStr = null; - this.enabled = false; - } - setTextMapping(divs, texts) { - this.textDivs = divs; - this.textContentItemsStr = texts; - } - enable() { - if (!this.textDivs || !this.textContentItemsStr) { - throw new Error("Text divs and strings have not been set."); - } - if (this.enabled) { - throw new Error("TextHighlighter is already enabled."); - } - this.enabled = true; - if (!this.#eventAbortController) { - this.#eventAbortController = new AbortController(); - this.eventBus._on("updatetextlayermatches", evt => { - if (evt.pageIndex === this.pageIdx || evt.pageIndex === -1) { - this._updateMatches(); - } - }, { - signal: this.#eventAbortController.signal - }); - } - this._updateMatches(); - } - disable() { - if (!this.enabled) { - return; - } - this.enabled = false; - this.#eventAbortController?.abort(); - this.#eventAbortController = null; - this._updateMatches(true); - } - _convertMatches(matches, matchesLength) { - if (!matches) { - return []; - } - const { - textContentItemsStr - } = this; - let i = 0, - iIndex = 0; - const end = textContentItemsStr.length - 1; - const result = []; - for (let m = 0, mm = matches.length; m < mm; m++) { - let matchIdx = matches[m]; - while (i !== end && matchIdx >= iIndex + textContentItemsStr[i].length) { - iIndex += textContentItemsStr[i].length; - i++; - } - if (i === textContentItemsStr.length) { - console.error("Could not find a matching mapping"); - } - const match = { - begin: { - divIdx: i, - offset: matchIdx - iIndex - } - }; - matchIdx += matchesLength[m]; - while (i !== end && matchIdx > iIndex + textContentItemsStr[i].length) { - iIndex += textContentItemsStr[i].length; - i++; - } - match.end = { - divIdx: i, - offset: matchIdx - iIndex - }; - result.push(match); - } - return result; - } - _renderMatches(matches) { - if (matches.length === 0) { - return; - } - const { - findController, - pageIdx - } = this; - const { - textContentItemsStr, - textDivs - } = this; - const isSelectedPage = pageIdx === findController.selected.pageIdx; - const selectedMatchIdx = findController.selected.matchIdx; - const highlightAll = findController.state.highlightAll; - let prevEnd = null; - const infinity = { - divIdx: -1, - offset: undefined - }; - function beginText(begin, className) { - const divIdx = begin.divIdx; - textDivs[divIdx].textContent = ""; - return appendTextToDiv(divIdx, 0, begin.offset, className); - } - function appendTextToDiv(divIdx, fromOffset, toOffset, className) { - let div = textDivs[divIdx]; - if (div.nodeType === Node.TEXT_NODE) { - const span = document.createElement("span"); - div.before(span); - span.append(div); - textDivs[divIdx] = span; - div = span; - } - const content = textContentItemsStr[divIdx].substring(fromOffset, toOffset); - const node = document.createTextNode(content); - if (className) { - const span = document.createElement("span"); - span.className = `${className} appended`; - span.append(node); - div.append(span); - return className.includes("selected") ? span.offsetLeft : 0; - } - div.append(node); - return 0; - } - let i0 = selectedMatchIdx, - i1 = i0 + 1; - if (highlightAll) { - i0 = 0; - i1 = matches.length; - } else if (!isSelectedPage) { - return; - } - let lastDivIdx = -1; - let lastOffset = -1; - for (let i = i0; i < i1; i++) { - const match = matches[i]; - const begin = match.begin; - if (begin.divIdx === lastDivIdx && begin.offset === lastOffset) { - continue; - } - lastDivIdx = begin.divIdx; - lastOffset = begin.offset; - const end = match.end; - const isSelected = isSelectedPage && i === selectedMatchIdx; - const highlightSuffix = isSelected ? " selected" : ""; - let selectedLeft = 0; - if (!prevEnd || begin.divIdx !== prevEnd.divIdx) { - if (prevEnd !== null) { - appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset); - } - beginText(begin); - } else { - appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset); - } - if (begin.divIdx === end.divIdx) { - selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, end.offset, "highlight" + highlightSuffix); - } else { - selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, "highlight begin" + highlightSuffix); - for (let n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) { - textDivs[n0].className = "highlight middle" + highlightSuffix; - } - beginText(end, "highlight end" + highlightSuffix); - } - prevEnd = end; - if (isSelected) { - findController.scrollMatchIntoView({ - element: textDivs[begin.divIdx], - selectedLeft, - pageIndex: pageIdx, - matchIndex: selectedMatchIdx - }); - } - } - if (prevEnd) { - appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset); - } - } - _updateMatches(reset = false) { - if (!this.enabled && !reset) { - return; - } - const { - findController, - matches, - pageIdx - } = this; - const { - textContentItemsStr, - textDivs - } = this; - let clearedUntilDivIdx = -1; - for (const match of matches) { - const begin = Math.max(clearedUntilDivIdx, match.begin.divIdx); - for (let n = begin, end = match.end.divIdx; n <= end; n++) { - const div = textDivs[n]; - div.textContent = textContentItemsStr[n]; - div.className = ""; - } - clearedUntilDivIdx = match.end.divIdx + 1; - } - if (!findController?.highlightMatches || reset) { - return; - } - const pageMatches = findController.pageMatches[pageIdx] || null; - const pageMatchesLength = findController.pageMatchesLength[pageIdx] || null; - this.matches = this._convertMatches(pageMatches, pageMatchesLength); - this._renderMatches(this.matches); - } -} - - -/***/ }), - -/***/ 7765: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ TextLayerBuilder: () => (/* binding */ TextLayerBuilder) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -class TextLayerBuilder { - #enablePermissions = false; - #onAppend = null; - #rotation = 0; - #scale = 0; - #textContentSource = null; - constructor({ - highlighter = null, - accessibilityManager = null, - enablePermissions = false, - onAppend = null - }) { - this.textContentItemsStr = []; - this.renderingDone = false; - this.textDivs = []; - this.textDivProperties = new WeakMap(); - this.textLayerRenderTask = null; - this.highlighter = highlighter; - this.accessibilityManager = accessibilityManager; - this.#enablePermissions = enablePermissions === true; - this.#onAppend = onAppend; - this.div = document.createElement("div"); - this.div.tabIndex = 0; - this.div.className = "textLayer"; - } - #finishRendering() { - this.renderingDone = true; - const endOfContent = document.createElement("div"); - endOfContent.className = "endOfContent"; - this.div.append(endOfContent); - this.#bindMouse(); - } - get numTextDivs() { - return this.textDivs.length; - } - async render(viewport) { - if (!this.#textContentSource) { - throw new Error('No "textContentSource" parameter specified.'); - } - const scale = viewport.scale * (globalThis.devicePixelRatio || 1); - const { - rotation - } = viewport; - if (this.renderingDone) { - const mustRotate = rotation !== this.#rotation; - const mustRescale = scale !== this.#scale; - if (mustRotate || mustRescale) { - this.hide(); - (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.updateTextLayer)({ - container: this.div, - viewport, - textDivs: this.textDivs, - textDivProperties: this.textDivProperties, - mustRescale, - mustRotate - }); - this.#scale = scale; - this.#rotation = rotation; - } - this.show(); - return; - } - this.cancel(); - this.highlighter?.setTextMapping(this.textDivs, this.textContentItemsStr); - this.accessibilityManager?.setTextMapping(this.textDivs); - this.textLayerRenderTask = (0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.renderTextLayer)({ - textContentSource: this.#textContentSource, - container: this.div, - viewport, - textDivs: this.textDivs, - textDivProperties: this.textDivProperties, - textContentItemsStr: this.textContentItemsStr - }); - await this.textLayerRenderTask.promise; - this.#finishRendering(); - this.#scale = scale; - this.#rotation = rotation; - this.#onAppend?.(this.div); - this.highlighter?.enable(); - this.accessibilityManager?.enable(); - } - hide() { - if (!this.div.hidden && this.renderingDone) { - this.highlighter?.disable(); - this.div.hidden = true; - } - } - show() { - if (this.div.hidden && this.renderingDone) { - this.div.hidden = false; - this.highlighter?.enable(); - } - } - cancel() { - if (this.textLayerRenderTask) { - this.textLayerRenderTask.cancel(); - this.textLayerRenderTask = null; - } - this.highlighter?.disable(); - this.accessibilityManager?.disable(); - this.textContentItemsStr.length = 0; - this.textDivs.length = 0; - this.textDivProperties = new WeakMap(); - } - setTextContentSource(source) { - this.cancel(); - this.#textContentSource = source; - } - #bindMouse() { - const { - div - } = this; - div.addEventListener("mousedown", evt => { - const end = div.querySelector(".endOfContent"); - if (!end) { - return; - } - let adjustTop = evt.target !== div; - adjustTop &&= getComputedStyle(end).getPropertyValue("-moz-user-select") !== "none"; - if (adjustTop) { - const divBounds = div.getBoundingClientRect(); - const r = Math.max(0, (evt.pageY - divBounds.top) / divBounds.height); - end.style.top = (r * 100).toFixed(2) + "%"; - } - end.classList.add("active"); - }); - div.addEventListener("mouseup", () => { - const end = div.querySelector(".endOfContent"); - if (!end) { - return; - } - end.style.top = ""; - end.classList.remove("active"); - }); - div.addEventListener("copy", event => { - if (!this.#enablePermissions) { - const selection = document.getSelection(); - event.clipboardData.setData("text/plain", (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.removeNullCharacters)((0,pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.normalizeUnicode)(selection.toString()))); - } - event.preventDefault(); - event.stopPropagation(); - }); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 6297: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ Toolbar: () => (/* binding */ Toolbar) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7256); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -class Toolbar { - #opts; - constructor(options, eventBus) { - // console.log('test-option', options) - this.#opts = options; - this.eventBus = eventBus; - const buttons = [{ - element: options.previous, - eventName: "previouspage" - }, { - element: options.next, - eventName: "nextpage" - }, { - element: options.zoomIn, - eventName: "zoomin" - }, { - element: options.zoomOut, - eventName: "zoomout" - }, { - element: options.print, - eventName: "print" - }, { - element: options.download, - eventName: "download" - }, { - element: options.editorFreeTextButton, - eventName: "switchannotationeditormode", - eventDetails: { - get mode() { - const { - classList - } = options.editorFreeTextButton; - return classList.contains("toggled") ? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE : pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.FREETEXT; - } - } - }, { - element: options.editorHighlightButton, - eventName: "switchannotationeditormode", - eventDetails: { - get mode() { - const { - classList - } = options.editorHighlightButton; - return classList.contains("toggled") ? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE : pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT; - } - } - }, { - element: options.editorInkButton, - eventName: "switchannotationeditormode", - eventDetails: { - get mode() { - const { - classList - } = options.editorInkButton; - return classList.contains("toggled") ? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE : pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.INK; - } - } - }, { - element: options.editorStampButton, - eventName: "switchannotationeditormode", - eventDetails: { - get mode() { - const { - classList - } = options.editorStampButton; - return classList.contains("toggled") ? pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.NONE : pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.STAMP; - } - } - }]; - this.#bindListeners(buttons); - if (options.editorHighlightColorPicker) { - eventBus._on("annotationeditoruimanager", ({ - uiManager - }) => { - this.#setAnnotationEditorUIManager(uiManager, options.editorHighlightColorPicker); - }, { - once: true - }); - } - eventBus._on("showannotationeditorui", ({ - mode - }) => { - switch (mode) { - case pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT: - options.editorHighlightButton.click(); - break; - } - }); - this.reset(); - } - #setAnnotationEditorUIManager(uiManager, parentContainer) { - const colorPicker = new pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.ColorPicker({ - uiManager - }); - uiManager.setMainHighlightColorPicker(colorPicker); - parentContainer.append(colorPicker.renderMainDropdown()); - } - setPageNumber(pageNumber, pageLabel) { - this.pageNumber = pageNumber; - this.pageLabel = pageLabel; - this.#updateUIState(false); - } - setPagesCount(pagesCount, hasPageLabels) { - this.pagesCount = pagesCount; - this.hasPageLabels = hasPageLabels; - this.#updateUIState(true); - } - setPageScale(pageScaleValue, pageScale) { - this.pageScaleValue = (pageScaleValue || pageScale).toString(); - this.pageScale = pageScale; - this.#updateUIState(false); - } - reset() { - this.pageNumber = 0; - this.pageLabel = null; - this.hasPageLabels = false; - this.pagesCount = 0; - this.pageScaleValue = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE_VALUE; - this.pageScale = _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_SCALE; - this.#updateUIState(true); - this.updateLoadingIndicatorState(); - this.#editorModeChanged({ - mode: pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE - }); - } - #bindListeners(buttons) { - const { - eventBus - } = this; - const { - pageNumber, - scaleSelect - } = this.#opts; - const self = this; - for (const { - element, - eventName, - eventDetails - } of buttons) { - element.addEventListener("click", evt => { - if (eventName !== null) { - eventBus.dispatch(eventName, { - source: this, - ...eventDetails, - isFromKeyboard: evt.detail === 0 - }); - } - }); - } - pageNumber.addEventListener("click", function () { - this.select(); - }); - pageNumber.addEventListener("change", function () { - eventBus.dispatch("pagenumberchanged", { - source: self, - value: this.value - }); - }); - scaleSelect.addEventListener("change", function () { - if (this.value === "custom") { - return; - } - eventBus.dispatch("scalechanged", { - source: self, - value: this.value - }); - }); - scaleSelect.addEventListener("click", function ({ - target - }) { - if (this.value === self.pageScaleValue && target.tagName.toUpperCase() === "OPTION") { - this.blur(); - } - }); - scaleSelect.oncontextmenu = pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.noContextMenu; - eventBus._on("annotationeditormodechanged", this.#editorModeChanged.bind(this)); - } - #editorModeChanged({ - mode - }) { - const { - editorFreeTextButton, - editorFreeTextParamsToolbar, - editorHighlightButton, - editorHighlightParamsToolbar, - editorInkButton, - editorInkParamsToolbar, - editorStampButton, - editorStampParamsToolbar - } = this.#opts; - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleCheckedBtn)(editorFreeTextButton, mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.FREETEXT, editorFreeTextParamsToolbar); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleCheckedBtn)(editorHighlightButton, mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.HIGHLIGHT, editorHighlightParamsToolbar); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleCheckedBtn)(editorInkButton, mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.INK, editorInkParamsToolbar); - (0,_ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.toggleCheckedBtn)(editorStampButton, mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.STAMP, editorStampParamsToolbar); - const isDisable = mode === pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.AnnotationEditorType.DISABLE; - editorFreeTextButton.disabled = isDisable; - editorHighlightButton.disabled = isDisable; - editorInkButton.disabled = isDisable; - editorStampButton.disabled = isDisable; - } - #updateUIState(resetNumPages = false) { - const { - pageNumber, - pagesCount, - pageScaleValue, - pageScale - } = this; - const opts = this.#opts; - if (resetNumPages) { - if (this.hasPageLabels) { - opts.pageNumber.type = "text"; - opts.numPages.setAttribute("data-l10n-id", "pdfjs-page-of-pages"); - } else { - opts.pageNumber.type = "number"; - opts.numPages.setAttribute("data-l10n-id", "pdfjs-of-pages"); - opts.numPages.setAttribute("data-l10n-args", JSON.stringify({ - pagesCount - })); - } - opts.pageNumber.max = pagesCount; - } - if (this.hasPageLabels) { - opts.pageNumber.value = this.pageLabel; - opts.numPages.setAttribute("data-l10n-args", JSON.stringify({ - pageNumber, - pagesCount - })); - } else { - // console.log('test-pageNumber-dd', pageNumber) - // [custome] 比page Changing 更精确 - window.parent.postMessage({pageNumDetail: pageNumber}, '*'); - opts.pageNumber.value = pageNumber; - } - opts.previous.disabled = pageNumber <= 1; - opts.next.disabled = pageNumber >= pagesCount; - opts.zoomOut.disabled = pageScale <= _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MIN_SCALE; - opts.zoomIn.disabled = pageScale >= _ui_utils_js__WEBPACK_IMPORTED_MODULE_1__.MAX_SCALE; - let predefinedValueFound = false; - for (const option of opts.scaleSelect.options) { - if (option.value !== pageScaleValue) { - option.selected = false; - continue; - } - option.selected = true; - predefinedValueFound = true; - } - if (!predefinedValueFound) { - opts.customScaleOption.selected = true; - opts.customScaleOption.setAttribute("data-l10n-args", JSON.stringify({ - scale: Math.round(pageScale * 10000) / 100 - })); - } - - if(opts?.odlScale) { - opts.odlScale.innerText = `${ Math.round(pageScale * 10000) / 100}%` - } - } - updateLoadingIndicatorState(loading = false) { - const { - pageNumber - } = this.#opts; - pageNumber.classList.toggle("loading", loading); - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 7256: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ AutoPrintRegExp: () => (/* binding */ AutoPrintRegExp), -/* harmony export */ CursorTool: () => (/* binding */ CursorTool), -/* harmony export */ DEFAULT_SCALE: () => (/* binding */ DEFAULT_SCALE), -/* harmony export */ DEFAULT_SCALE_DELTA: () => (/* binding */ DEFAULT_SCALE_DELTA), -/* harmony export */ DEFAULT_SCALE_VALUE: () => (/* binding */ DEFAULT_SCALE_VALUE), -/* harmony export */ MAX_AUTO_SCALE: () => (/* binding */ MAX_AUTO_SCALE), -/* harmony export */ MAX_SCALE: () => (/* binding */ MAX_SCALE), -/* harmony export */ MIN_SCALE: () => (/* binding */ MIN_SCALE), -/* harmony export */ OutputScale: () => (/* binding */ OutputScale), -/* harmony export */ PresentationModeState: () => (/* binding */ PresentationModeState), -/* harmony export */ ProgressBar: () => (/* binding */ ProgressBar), -/* harmony export */ RenderingStates: () => (/* binding */ RenderingStates), -/* harmony export */ SCROLLBAR_PADDING: () => (/* binding */ SCROLLBAR_PADDING), -/* harmony export */ ScrollMode: () => (/* binding */ ScrollMode), -/* harmony export */ SidebarView: () => (/* binding */ SidebarView), -/* harmony export */ SpreadMode: () => (/* binding */ SpreadMode), -/* harmony export */ TextLayerMode: () => (/* binding */ TextLayerMode), -/* harmony export */ UNKNOWN_SCALE: () => (/* binding */ UNKNOWN_SCALE), -/* harmony export */ VERTICAL_PADDING: () => (/* binding */ VERTICAL_PADDING), -/* harmony export */ animationStarted: () => (/* binding */ animationStarted), -/* harmony export */ apiPageLayoutToViewerModes: () => (/* binding */ apiPageLayoutToViewerModes), -/* harmony export */ apiPageModeToSidebarView: () => (/* binding */ apiPageModeToSidebarView), -/* harmony export */ approximateFraction: () => (/* binding */ approximateFraction), -/* harmony export */ binarySearchFirstItem: () => (/* binding */ binarySearchFirstItem), -/* harmony export */ docStyle: () => (/* binding */ docStyle), -/* harmony export */ getActiveOrFocusedElement: () => (/* binding */ getActiveOrFocusedElement), -/* harmony export */ getPageSizeInches: () => (/* binding */ getPageSizeInches), -/* harmony export */ getVisibleElements: () => (/* binding */ getVisibleElements), -/* harmony export */ isPortraitOrientation: () => (/* binding */ isPortraitOrientation), -/* harmony export */ isValidRotation: () => (/* binding */ isValidRotation), -/* harmony export */ isValidScrollMode: () => (/* binding */ isValidScrollMode), -/* harmony export */ isValidSpreadMode: () => (/* binding */ isValidSpreadMode), -/* harmony export */ normalizeWheelEventDelta: () => (/* binding */ normalizeWheelEventDelta), -/* harmony export */ normalizeWheelEventDirection: () => (/* binding */ normalizeWheelEventDirection), -/* harmony export */ parseQueryString: () => (/* binding */ parseQueryString), -/* harmony export */ removeNullCharacters: () => (/* binding */ removeNullCharacters), -/* harmony export */ roundToDivide: () => (/* binding */ roundToDivide), -/* harmony export */ scrollIntoView: () => (/* binding */ scrollIntoView), -/* harmony export */ toggleCheckedBtn: () => (/* binding */ toggleCheckedBtn), -/* harmony export */ toggleExpandedBtn: () => (/* binding */ toggleExpandedBtn), -/* harmony export */ watchScroll: () => (/* binding */ watchScroll) -/* harmony export */ }); -/* unused harmony export backtrackBeforeAllVisibleElements */ -const DEFAULT_SCALE_VALUE = "auto"; -const DEFAULT_SCALE = 1.0; -const DEFAULT_SCALE_DELTA = 1.1; -const MIN_SCALE = 0.1; -const MAX_SCALE = 10.0; -const UNKNOWN_SCALE = 0; -const MAX_AUTO_SCALE = 1.25; -const SCROLLBAR_PADDING = 40; -const VERTICAL_PADDING = 5; -const RenderingStates = { - INITIAL: 0, - RUNNING: 1, - PAUSED: 2, - FINISHED: 3 -}; -const PresentationModeState = { - UNKNOWN: 0, - NORMAL: 1, - CHANGING: 2, - FULLSCREEN: 3 -}; -const SidebarView = { - UNKNOWN: -1, - NONE: 0, - THUMBS: 1, - OUTLINE: 2, - ATTACHMENTS: 3, - LAYERS: 4 -}; -const TextLayerMode = { - DISABLE: 0, - ENABLE: 1, - ENABLE_PERMISSIONS: 2 -}; -const ScrollMode = { - UNKNOWN: -1, - VERTICAL: 0, - HORIZONTAL: 1, - WRAPPED: 2, - PAGE: 3 -}; -const SpreadMode = { - UNKNOWN: -1, - NONE: 0, - ODD: 1, - EVEN: 2 -}; -const CursorTool = { - SELECT: 0, - HAND: 1, - ZOOM: 2 -}; -const AutoPrintRegExp = /\bprint\s*\(/; -class OutputScale { - constructor() { - const pixelRatio = window.devicePixelRatio || 1; - this.sx = pixelRatio; - this.sy = pixelRatio; - } - get scaled() { - return this.sx !== 1 || this.sy !== 1; - } -} -function scrollIntoView(element, spot, scrollMatches = false) { - let parent = element.offsetParent; - if (!parent) { - console.error("offsetParent is not set -- cannot scroll"); - return; - } - let offsetY = element.offsetTop + element.clientTop; - let offsetX = element.offsetLeft + element.clientLeft; - while (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth || scrollMatches && (parent.classList.contains("markedContent") || getComputedStyle(parent).overflow === "hidden")) { - offsetY += parent.offsetTop; - offsetX += parent.offsetLeft; - parent = parent.offsetParent; - if (!parent) { - return; - } - } - if (spot) { - if (spot.top !== undefined) { - offsetY += spot.top; - } - if (spot.left !== undefined) { - offsetX += spot.left; - parent.scrollLeft = offsetX; - } - } - parent.scrollTop = offsetY; -} -function watchScroll(viewAreaElement, callback) { - const debounceScroll = function (evt) { - if (rAF) { - return; - } - rAF = window.requestAnimationFrame(function viewAreaElementScrolled() { - rAF = null; - const currentX = viewAreaElement.scrollLeft; - const lastX = state.lastX; - if (currentX !== lastX) { - state.right = currentX > lastX; - } - state.lastX = currentX; - const currentY = viewAreaElement.scrollTop; - const lastY = state.lastY; - if (currentY !== lastY) { - state.down = currentY > lastY; - } - state.lastY = currentY; - callback(state); - }); - }; - const state = { - right: true, - down: true, - lastX: viewAreaElement.scrollLeft, - lastY: viewAreaElement.scrollTop, - _eventHandler: debounceScroll - }; - let rAF = null; - viewAreaElement.addEventListener("scroll", debounceScroll, true); - return state; -} -function parseQueryString(query) { - const params = new Map(); - for (const [key, value] of new URLSearchParams(query)) { - params.set(key.toLowerCase(), value); - } - return params; -} -const InvisibleCharsRegExp = /[\x00-\x1F]/g; -function removeNullCharacters(str, replaceInvisible = false) { - if (!InvisibleCharsRegExp.test(str)) { - return str; - } - if (replaceInvisible) { - return str.replaceAll(InvisibleCharsRegExp, m => m === "\x00" ? "" : " "); - } - return str.replaceAll("\x00", ""); -} -function binarySearchFirstItem(items, condition, start = 0) { - let minIndex = start; - let maxIndex = items.length - 1; - if (maxIndex < 0 || !condition(items[maxIndex])) { - return items.length; - } - if (condition(items[minIndex])) { - return minIndex; - } - while (minIndex < maxIndex) { - const currentIndex = minIndex + maxIndex >> 1; - const currentItem = items[currentIndex]; - if (condition(currentItem)) { - maxIndex = currentIndex; - } else { - minIndex = currentIndex + 1; - } - } - return minIndex; -} -function approximateFraction(x) { - if (Math.floor(x) === x) { - return [x, 1]; - } - const xinv = 1 / x; - const limit = 8; - if (xinv > limit) { - return [1, limit]; - } else if (Math.floor(xinv) === xinv) { - return [1, xinv]; - } - const x_ = x > 1 ? xinv : x; - let a = 0, - b = 1, - c = 1, - d = 1; - while (true) { - const p = a + c, - q = b + d; - if (q > limit) { - break; - } - if (x_ <= p / q) { - c = p; - d = q; - } else { - a = p; - b = q; - } - } - let result; - if (x_ - a / b < c / d - x_) { - result = x_ === x ? [a, b] : [b, a]; - } else { - result = x_ === x ? [c, d] : [d, c]; - } - return result; -} -function roundToDivide(x, div) { - const r = x % div; - return r === 0 ? x : Math.round(x - r + div); -} -function getPageSizeInches({ - view, - userUnit, - rotate -}) { - const [x1, y1, x2, y2] = view; - const changeOrientation = rotate % 180 !== 0; - const width = (x2 - x1) / 72 * userUnit; - const height = (y2 - y1) / 72 * userUnit; - return { - width: changeOrientation ? height : width, - height: changeOrientation ? width : height - }; -} -function backtrackBeforeAllVisibleElements(index, views, top) { - if (index < 2) { - return index; - } - let elt = views[index].div; - let pageTop = elt.offsetTop + elt.clientTop; - if (pageTop >= top) { - elt = views[index - 1].div; - pageTop = elt.offsetTop + elt.clientTop; - } - for (let i = index - 2; i >= 0; --i) { - elt = views[i].div; - if (elt.offsetTop + elt.clientTop + elt.clientHeight <= pageTop) { - break; - } - index = i; - } - return index; -} -function getVisibleElements({ - scrollEl, - views, - sortByVisibility = false, - horizontal = false, - rtl = false -}) { - const top = scrollEl.scrollTop, - bottom = top + scrollEl.clientHeight; - const left = scrollEl.scrollLeft, - right = left + scrollEl.clientWidth; - function isElementBottomAfterViewTop(view) { - const element = view.div; - const elementBottom = element.offsetTop + element.clientTop + element.clientHeight; - return elementBottom > top; - } - function isElementNextAfterViewHorizontally(view) { - const element = view.div; - const elementLeft = element.offsetLeft + element.clientLeft; - const elementRight = elementLeft + element.clientWidth; - return rtl ? elementLeft < right : elementRight > left; - } - const visible = [], - ids = new Set(), - numViews = views.length; - let firstVisibleElementInd = binarySearchFirstItem(views, horizontal ? isElementNextAfterViewHorizontally : isElementBottomAfterViewTop); - if (firstVisibleElementInd > 0 && firstVisibleElementInd < numViews && !horizontal) { - firstVisibleElementInd = backtrackBeforeAllVisibleElements(firstVisibleElementInd, views, top); - } - let lastEdge = horizontal ? right : -1; - for (let i = firstVisibleElementInd; i < numViews; i++) { - const view = views[i], - element = view.div; - const currentWidth = element.offsetLeft + element.clientLeft; - const currentHeight = element.offsetTop + element.clientTop; - const viewWidth = element.clientWidth, - viewHeight = element.clientHeight; - const viewRight = currentWidth + viewWidth; - const viewBottom = currentHeight + viewHeight; - if (lastEdge === -1) { - if (viewBottom >= bottom) { - lastEdge = viewBottom; - } - } else if ((horizontal ? currentWidth : currentHeight) > lastEdge) { - break; - } - if (viewBottom <= top || currentHeight >= bottom || viewRight <= left || currentWidth >= right) { - continue; - } - const hiddenHeight = Math.max(0, top - currentHeight) + Math.max(0, viewBottom - bottom); - const hiddenWidth = Math.max(0, left - currentWidth) + Math.max(0, viewRight - right); - const fractionHeight = (viewHeight - hiddenHeight) / viewHeight, - fractionWidth = (viewWidth - hiddenWidth) / viewWidth; - const percent = fractionHeight * fractionWidth * 100 | 0; - visible.push({ - id: view.id, - x: currentWidth, - y: currentHeight, - view, - percent, - widthPercent: fractionWidth * 100 | 0 - }); - ids.add(view.id); - } - const first = visible[0], - last = visible.at(-1); - if (sortByVisibility) { - visible.sort(function (a, b) { - const pc = a.percent - b.percent; - if (Math.abs(pc) > 0.001) { - return -pc; - } - return a.id - b.id; - }); - } - return { - first, - last, - views: visible, - ids - }; -} -function normalizeWheelEventDirection(evt) { - let delta = Math.hypot(evt.deltaX, evt.deltaY); - const angle = Math.atan2(evt.deltaY, evt.deltaX); - if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) { - delta = -delta; - } - return delta; -} -function normalizeWheelEventDelta(evt) { - const deltaMode = evt.deltaMode; - let delta = normalizeWheelEventDirection(evt); - const MOUSE_PIXELS_PER_LINE = 30; - const MOUSE_LINES_PER_PAGE = 30; - if (deltaMode === WheelEvent.DOM_DELTA_PIXEL) { - delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE; - } else if (deltaMode === WheelEvent.DOM_DELTA_LINE) { - delta /= MOUSE_LINES_PER_PAGE; - } - return delta; -} -function isValidRotation(angle) { - return Number.isInteger(angle) && angle % 90 === 0; -} -function isValidScrollMode(mode) { - return Number.isInteger(mode) && Object.values(ScrollMode).includes(mode) && mode !== ScrollMode.UNKNOWN; -} -function isValidSpreadMode(mode) { - return Number.isInteger(mode) && Object.values(SpreadMode).includes(mode) && mode !== SpreadMode.UNKNOWN; -} -function isPortraitOrientation(size) { - return size.width <= size.height; -} -const animationStarted = new Promise(function (resolve) { - window.requestAnimationFrame(resolve); -}); -const docStyle = document.documentElement.style; -function clamp(v, min, max) { - return Math.min(Math.max(v, min), max); -} -class ProgressBar { - #classList = null; - #disableAutoFetchTimeout = null; - #percent = 0; - #style = null; - #visible = true; - constructor(bar) { - this.#classList = bar.classList; - this.#style = bar.style; - } - get percent() { - return this.#percent; - } - set percent(val) { - this.#percent = clamp(val, 0, 100); - if (isNaN(val)) { - this.#classList.add("indeterminate"); - return; - } - this.#classList.remove("indeterminate"); - this.#style.setProperty("--progressBar-percent", `${this.#percent}%`); - } - setWidth(viewer) { - if (!viewer) { - return; - } - const container = viewer.parentNode; - const scrollbarWidth = container.offsetWidth - viewer.offsetWidth; - if (scrollbarWidth > 0) { - this.#style.setProperty("--progressBar-end-offset", `${scrollbarWidth}px`); - } - } - setDisableAutoFetch(delay = 5000) { - if (isNaN(this.#percent)) { - return; - } - if (this.#disableAutoFetchTimeout) { - clearTimeout(this.#disableAutoFetchTimeout); - } - this.show(); - this.#disableAutoFetchTimeout = setTimeout(() => { - this.#disableAutoFetchTimeout = null; - this.hide(); - }, delay); - } - hide() { - if (!this.#visible) { - return; - } - this.#visible = false; - this.#classList.add("hidden"); - } - show() { - if (this.#visible) { - return; - } - this.#visible = true; - this.#classList.remove("hidden"); - } -} -function getActiveOrFocusedElement() { - let curRoot = document; - let curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus"); - while (curActiveOrFocused?.shadowRoot) { - curRoot = curActiveOrFocused.shadowRoot; - curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus"); - } - return curActiveOrFocused; -} -function apiPageLayoutToViewerModes(layout) { - let scrollMode = ScrollMode.VERTICAL, - spreadMode = SpreadMode.NONE; - switch (layout) { - case "SinglePage": - scrollMode = ScrollMode.PAGE; - break; - case "OneColumn": - break; - case "TwoPageLeft": - scrollMode = ScrollMode.PAGE; - case "TwoColumnLeft": - spreadMode = SpreadMode.ODD; - break; - case "TwoPageRight": - scrollMode = ScrollMode.PAGE; - case "TwoColumnRight": - spreadMode = SpreadMode.EVEN; - break; - } - return { - scrollMode, - spreadMode - }; -} -function apiPageModeToSidebarView(mode) { - switch (mode) { - case "UseNone": - return SidebarView.NONE; - case "UseThumbs": - return SidebarView.THUMBS; - case "UseOutlines": - return SidebarView.OUTLINE; - case "UseAttachments": - return SidebarView.ATTACHMENTS; - case "UseOC": - return SidebarView.LAYERS; - } - return SidebarView.NONE; -} -function toggleCheckedBtn(button, toggle, view = null) { - button.classList.toggle("toggled", toggle); - button.setAttribute("aria-checked", toggle); - view?.classList.toggle("hidden", !toggle); -} -function toggleExpandedBtn(button, toggle, view = null) { - button.classList.toggle("toggled", toggle); - button.setAttribute("aria-expanded", toggle); - view?.classList.toggle("hidden", !toggle); -} - - -/***/ }), - -/***/ 9226: -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ ViewHistory: () => (/* binding */ ViewHistory) -/* harmony export */ }); -const DEFAULT_VIEW_HISTORY_CACHE_SIZE = 20; -class ViewHistory { - constructor(fingerprint, cacheSize = DEFAULT_VIEW_HISTORY_CACHE_SIZE) { - this.fingerprint = fingerprint; - this.cacheSize = cacheSize; - this._initializedPromise = this._readFromStorage().then(databaseStr => { - const database = JSON.parse(databaseStr || "{}"); - let index = -1; - if (!Array.isArray(database.files)) { - database.files = []; - } else { - while (database.files.length >= this.cacheSize) { - database.files.shift(); - } - for (let i = 0, ii = database.files.length; i < ii; i++) { - const branch = database.files[i]; - if (branch.fingerprint === this.fingerprint) { - index = i; - break; - } - } - } - if (index === -1) { - index = database.files.push({ - fingerprint: this.fingerprint - }) - 1; - } - this.file = database.files[index]; - this.database = database; - }); - } - async _writeToStorage() { - const databaseStr = JSON.stringify(this.database); - localStorage.setItem("pdfjs.history", databaseStr); - } - async _readFromStorage() { - // 屏蔽本地存储的pageNum字段 [custom] - const history = localStorage.getItem("pdfjs.history"); - return !!history ? {...history} : {}; - } - async set(name, val) { - await this._initializedPromise; - this.file[name] = val; - return this._writeToStorage(); - } - async setMultiple(properties) { - await this._initializedPromise; - for (const name in properties) { - this.file[name] = properties[name]; - } - return this._writeToStorage(); - } - async get(name, defaultValue) { - await this._initializedPromise; - const val = this.file[name]; - return val !== undefined ? val : defaultValue; - } - async getMultiple(properties) { - await this._initializedPromise; - const values = Object.create(null); - for (const name in properties) { - const val = this.file[name]; - values[name] = val !== undefined ? val : properties[name]; - } - return values; - } -} - - -/***/ }), - -/***/ 2030: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ PDFViewerApplication: () => (/* reexport safe */ _app_js__WEBPACK_IMPORTED_MODULE_3__.PDFViewerApplication), -/* harmony export */ PDFViewerApplicationConstants: () => (/* binding */ AppConstants), -/* harmony export */ PDFViewerApplicationOptions: () => (/* reexport safe */ _app_options_js__WEBPACK_IMPORTED_MODULE_1__.AppOptions) -/* harmony export */ }); -/* harmony import */ var _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7256); -/* harmony import */ var _app_options_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9840); -/* harmony import */ var _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(787); -/* harmony import */ var _app_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1621); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_app_js__WEBPACK_IMPORTED_MODULE_3__]); -_app_js__WEBPACK_IMPORTED_MODULE_3__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - - -const pdfjsVersion = "4.2.67"; -const pdfjsBuild = "49b388101"; -const AppConstants = { - LinkTarget: _pdf_link_service_js__WEBPACK_IMPORTED_MODULE_2__.LinkTarget, - RenderingStates: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.RenderingStates, - // 初始化模式设置为3 - ScrollMode: 3, - SpreadMode: _ui_utils_js__WEBPACK_IMPORTED_MODULE_0__.SpreadMode -}; -// console.log('test-init') -window.PDFViewerApplication = _app_js__WEBPACK_IMPORTED_MODULE_3__.PDFViewerApplication; -window.PDFViewerApplicationConstants = AppConstants; -window.PDFViewerApplicationOptions = _app_options_js__WEBPACK_IMPORTED_MODULE_1__.AppOptions; -function getViewerConfiguration() { - const odlCustomToolBarDomList = window.getOdlViewDom ? window.getOdlViewDom(window.odlIdDomToolbarList) : {}; - const odlCustomSiderDomList = window.getOdlViewDom ? window.getOdlViewDom(window.odlCustomSiderDomList) : {}; - - return { - appContainer: document.body, - mainContainer: document.getElementById("viewerContainer"), - viewerContainer: document.getElementById("viewer"), - toolbar: { - container: document.getElementById("toolbarViewer"), - numPages: document.getElementById("numPages"), - pageNumber: document.getElementById("pageNumber"), - scaleSelect: document.getElementById("scaleSelect"), - customScaleOption: document.getElementById("customScaleOption"), - previous: document.getElementById("previous"), - next: document.getElementById("next"), - zoomIn: document.getElementById("zoomIn"), - zoomOut: document.getElementById("zoomOut"), - viewFind: document.getElementById("viewFind"), - print: document.getElementById("print"), - editorFreeTextButton: document.getElementById("editorFreeText"), - editorFreeTextParamsToolbar: document.getElementById("editorFreeTextParamsToolbar"), - editorHighlightButton: document.getElementById("editorHighlight"), - editorHighlightParamsToolbar: document.getElementById("editorHighlightParamsToolbar"), - editorHighlightColorPicker: document.getElementById("editorHighlightColorPicker"), - editorInkButton: document.getElementById("editorInk"), - editorInkParamsToolbar: document.getElementById("editorInkParamsToolbar"), - editorStampButton: document.getElementById("editorStamp"), - editorStampParamsToolbar: document.getElementById("editorStampParamsToolbar"), - download: document.getElementById("download"), - ...odlCustomToolBarDomList, - }, - secondaryToolbar: { - toolbar: document.getElementById("secondaryToolbar"), - toggleButton: document.getElementById("secondaryToolbarToggle"), - presentationModeButton: document.getElementById("presentationMode"), - openFileButton: document.getElementById("secondaryOpenFile"), - printButton: document.getElementById("secondaryPrint"), - downloadButton: document.getElementById("secondaryDownload"), - viewBookmarkButton: document.getElementById("viewBookmark"), - firstPageButton: document.getElementById("firstPage"), - lastPageButton: document.getElementById("lastPage"), - pageRotateCwButton: document.getElementById("pageRotateCw"), - pageRotateCcwButton: document.getElementById("pageRotateCcw"), - cursorSelectToolButton: document.getElementById("cursorSelectTool"), - cursorHandToolButton: document.getElementById("cursorHandTool"), - scrollPageButton: document.getElementById("scrollPage"), - scrollVerticalButton: document.getElementById("scrollVertical"), - scrollHorizontalButton: document.getElementById("scrollHorizontal"), - scrollWrappedButton: document.getElementById("scrollWrapped"), - spreadNoneButton: document.getElementById("spreadNone"), - spreadOddButton: document.getElementById("spreadOdd"), - spreadEvenButton: document.getElementById("spreadEven"), - documentPropertiesButton: document.getElementById("documentProperties") - }, - sidebar: { - outerContainer: document.getElementById("outerContainer"), - sidebarContainer: document.getElementById("sidebarContainer"), - toggleButton: document.getElementById("sidebarToggle"), - resizer: document.getElementById("sidebarResizer"), - thumbnailButton: document.getElementById("viewThumbnail"), - outlineButton: document.getElementById("viewOutline"), - attachmentsButton: document.getElementById("viewAttachments"), - layersButton: document.getElementById("viewLayers"), - thumbnailView: document.getElementById("thumbnailView"), - outlineView: document.getElementById("outlineView"), - attachmentsView: document.getElementById("attachmentsView"), - layersView: document.getElementById("layersView"), - currentOutlineItemButton: document.getElementById("currentOutlineItem"), - ...odlCustomSiderDomList - }, - findBar: { - bar: document.getElementById("findbar"), - toggleButton: document.getElementById("viewFind"), - findField: document.getElementById("findInput"), - highlightAllCheckbox: document.getElementById("findHighlightAll"), - caseSensitiveCheckbox: document.getElementById("findMatchCase"), - matchDiacriticsCheckbox: document.getElementById("findMatchDiacritics"), - entireWordCheckbox: document.getElementById("findEntireWord"), - findMsg: document.getElementById("findMsg"), - findResultsCount: document.getElementById("findResultsCount"), - findPreviousButton: document.getElementById("findPrevious"), - findNextButton: document.getElementById("findNext") - }, - passwordOverlay: { - dialog: document.getElementById("passwordDialog"), - label: document.getElementById("passwordText"), - input: document.getElementById("password"), - submitButton: document.getElementById("passwordSubmit"), - cancelButton: document.getElementById("passwordCancel") - }, - documentProperties: { - dialog: document.getElementById("documentPropertiesDialog"), - closeButton: document.getElementById("documentPropertiesClose"), - fields: { - fileName: document.getElementById("fileNameField"), - fileSize: document.getElementById("fileSizeField"), - title: document.getElementById("titleField"), - author: document.getElementById("authorField"), - subject: document.getElementById("subjectField"), - keywords: document.getElementById("keywordsField"), - creationDate: document.getElementById("creationDateField"), - modificationDate: document.getElementById("modificationDateField"), - creator: document.getElementById("creatorField"), - producer: document.getElementById("producerField"), - version: document.getElementById("versionField"), - pageCount: document.getElementById("pageCountField"), - pageSize: document.getElementById("pageSizeField"), - linearized: document.getElementById("linearizedField") - } - }, - altTextDialog: { - dialog: document.getElementById("altTextDialog"), - optionDescription: document.getElementById("descriptionButton"), - optionDecorative: document.getElementById("decorativeButton"), - textarea: document.getElementById("descriptionTextarea"), - cancelButton: document.getElementById("altTextCancel"), - saveButton: document.getElementById("altTextSave") - }, - annotationEditorParams: { - editorFreeTextFontSize: document.getElementById("editorFreeTextFontSize"), - editorFreeTextColor: document.getElementById("editorFreeTextColor"), - editorInkColor: document.getElementById("editorInkColor"), - editorInkThickness: document.getElementById("editorInkThickness"), - editorInkOpacity: document.getElementById("editorInkOpacity"), - editorStampAddImage: document.getElementById("editorStampAddImage"), - editorFreeHighlightThickness: document.getElementById("editorFreeHighlightThickness"), - editorHighlightShowAll: document.getElementById("editorHighlightShowAll") - }, - printContainer: document.getElementById("printContainer") - }; -} -function webViewerLoad() { - const config = getViewerConfiguration(); - const event = new CustomEvent("webviewerloaded", { - bubbles: true, - cancelable: true, - detail: { - source: window - } - }); - try { - parent.document.dispatchEvent(event); - } catch (ex) { - console.error(`webviewerloaded: ${ex}`); - document.dispatchEvent(event); - } - _app_js__WEBPACK_IMPORTED_MODULE_3__.PDFViewerApplication.run(config); -} -document.blockUnblockOnload?.(true); -if (document.readyState === "interactive" || document.readyState === "complete") { - webViewerLoad(); -} else { - document.addEventListener("DOMContentLoaded", webViewerLoad, true); -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }), - -/***/ 2973: -/***/ ((__webpack_module__, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try { -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ XfaLayerBuilder: () => (/* binding */ XfaLayerBuilder) -/* harmony export */ }); -/* harmony import */ var pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2603); -var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__]); -pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0]; - -class XfaLayerBuilder { - constructor({ - pdfPage, - annotationStorage = null, - linkService, - xfaHtml = null - }) { - this.pdfPage = pdfPage; - this.annotationStorage = annotationStorage; - this.linkService = linkService; - this.xfaHtml = xfaHtml; - this.div = null; - this._cancelled = false; - } - async render(viewport, intent = "display") { - if (intent === "print") { - const parameters = { - viewport: viewport.clone({ - dontFlip: true - }), - div: this.div, - xfaHtml: this.xfaHtml, - annotationStorage: this.annotationStorage, - linkService: this.linkService, - intent - }; - this.div = document.createElement("div"); - parameters.div = this.div; - return pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.XfaLayer.render(parameters); - } - const xfaHtml = await this.pdfPage.getXfa(); - if (this._cancelled || !xfaHtml) { - return { - textDivs: [] - }; - } - const parameters = { - viewport: viewport.clone({ - dontFlip: true - }), - div: this.div, - xfaHtml, - annotationStorage: this.annotationStorage, - linkService: this.linkService, - intent - }; - if (this.div) { - return pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.XfaLayer.update(parameters); - } - this.div = document.createElement("div"); - parameters.div = this.div; - return pdfjs_lib__WEBPACK_IMPORTED_MODULE_0__.XfaLayer.render(parameters); - } - cancel() { - this._cancelled = true; - } - hide() { - if (!this.div) { - return; - } - this.div.hidden = true; - } -} - -__webpack_async_result__(); -} catch(e) { __webpack_async_result__(e); } }); - -/***/ }) - -/******/ }); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/async module */ -/******/ (() => { -/******/ var webpackQueues = typeof Symbol === "function" ? Symbol("webpack queues") : "__webpack_queues__"; -/******/ var webpackExports = typeof Symbol === "function" ? Symbol("webpack exports") : "__webpack_exports__"; -/******/ var webpackError = typeof Symbol === "function" ? Symbol("webpack error") : "__webpack_error__"; -/******/ var resolveQueue = (queue) => { -/******/ if(queue && queue.d < 1) { -/******/ queue.d = 1; -/******/ queue.forEach((fn) => (fn.r--)); -/******/ queue.forEach((fn) => (fn.r-- ? fn.r++ : fn())); -/******/ } -/******/ } -/******/ var wrapDeps = (deps) => (deps.map((dep) => { -/******/ if(dep !== null && typeof dep === "object") { -/******/ if(dep[webpackQueues]) return dep; -/******/ if(dep.then) { -/******/ var queue = []; -/******/ queue.d = 0; -/******/ dep.then((r) => { -/******/ obj[webpackExports] = r; -/******/ resolveQueue(queue); -/******/ }, (e) => { -/******/ obj[webpackError] = e; -/******/ resolveQueue(queue); -/******/ }); -/******/ var obj = {}; -/******/ obj[webpackQueues] = (fn) => (fn(queue)); -/******/ return obj; -/******/ } -/******/ } -/******/ var ret = {}; -/******/ ret[webpackQueues] = x => {}; -/******/ ret[webpackExports] = dep; -/******/ return ret; -/******/ })); -/******/ __webpack_require__.a = (module, body, hasAwait) => { -/******/ var queue; -/******/ hasAwait && ((queue = []).d = -1); -/******/ var depQueues = new Set(); -/******/ var exports = module.exports; -/******/ var currentDeps; -/******/ var outerResolve; -/******/ var reject; -/******/ var promise = new Promise((resolve, rej) => { -/******/ reject = rej; -/******/ outerResolve = resolve; -/******/ }); -/******/ promise[webpackExports] = exports; -/******/ promise[webpackQueues] = (fn) => (queue && fn(queue), depQueues.forEach(fn), promise["catch"](x => {})); -/******/ module.exports = promise; -/******/ body((deps) => { -/******/ currentDeps = wrapDeps(deps); -/******/ var fn; -/******/ var getResult = () => (currentDeps.map((d) => { -/******/ if(d[webpackError]) throw d[webpackError]; -/******/ return d[webpackExports]; -/******/ })) -/******/ var promise = new Promise((resolve) => { -/******/ fn = () => (resolve(getResult)); -/******/ fn.r = 0; -/******/ var fnQueue = (q) => (q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn)))); -/******/ currentDeps.map((dep) => (dep[webpackQueues](fnQueue))); -/******/ }); -/******/ return fn.r ? promise : getResult(); -/******/ }, (err) => ((err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue))); -/******/ queue && queue.d < 0 && (queue.d = 0); -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/define property getters */ -/******/ (() => { -/******/ // define getter functions for harmony exports -/******/ __webpack_require__.d = (exports, definition) => { -/******/ for(var key in definition) { -/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); -/******/ } -/******/ } -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ (() => { -/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) -/******/ })(); -/******/ -/************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module used 'module' so it can't be inlined -/******/ var __webpack_exports__ = __webpack_require__(2030); -/******/ __webpack_exports__ = await __webpack_exports__; -/******/ var __webpack_exports__PDFViewerApplication = __webpack_exports__.PDFViewerApplication; -/******/ var __webpack_exports__PDFViewerApplicationConstants = __webpack_exports__.PDFViewerApplicationConstants; -/******/ var __webpack_exports__PDFViewerApplicationOptions = __webpack_exports__.PDFViewerApplicationOptions; -/******/ export { __webpack_exports__PDFViewerApplication as PDFViewerApplication, __webpack_exports__PDFViewerApplicationConstants as PDFViewerApplicationConstants, __webpack_exports__PDFViewerApplicationOptions as PDFViewerApplicationOptions }; -/******/ - -//# sourceMappingURL=viewer.mjs.map diff --git a/projects/web/src/App.css b/projects/web/src/App.css deleted file mode 100644 index 3d97481ad0156a96ab99055d31bbbdb410858444..0000000000000000000000000000000000000000 --- a/projects/web/src/App.css +++ /dev/null @@ -1,41 +0,0 @@ -body,html, #root { - width: 100%; - height: 100vh; - background: white; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} diff --git a/projects/web/src/App.tsx b/projects/web/src/App.tsx deleted file mode 100644 index 4cbbb0dfe7f38402771f3e0aac55a910fe63ecb5..0000000000000000000000000000000000000000 --- a/projects/web/src/App.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Home } from "./pages/home"; -import "./App.css"; -import QueryProvider from "./context/query-provider"; - -function App() { - return ( - - - - ); -} - -export default App; diff --git a/projects/web/src/api/extract.ts b/projects/web/src/api/extract.ts deleted file mode 100644 index 7e1e309129ef2fc63a80d1a0792430c9e82b7a73..0000000000000000000000000000000000000000 --- a/projects/web/src/api/extract.ts +++ /dev/null @@ -1,196 +0,0 @@ -import axios from "./http"; -import { message } from "antd"; -import { ExtractTaskType } from "@/types/extract-task-type"; -import { getLocale } from "@/utils/locale"; - -export interface PdfExtractTaskReq { - fileKey: string; - fileName: string; - taskType: ExtractTaskType; - isOcr?: boolean; -} - -export interface SubmitRes { - filename: string; - url: string; - id: string; -} - -export const handleErrorMsg = (res: any) => { - const isCN = getLocale() === "zh-CN"; - const msg = isCN ? res?.data?.error?.msg : res?.data?.error?.msgZh; - message.error(msg); - return { data: null, error: res.data?.error }; -}; - -export const postExtractTask = ( - params: PdfExtractTaskReq -): Promise => { - return axios - .post(`/api/v2/extract/task/submit`, params) - .then((res) => { - if (!res?.data?.error) { - return res.data.data; - } else { - handleErrorMsg(res); - return null; - } - }); -}; - -export const postReUploadExtractTask = ( - id: string -): Promise => { - return axios - .put(`/api/v2/extract/task/submit`, { - id: Number(id), - }) - .then((res) => { - if (!res?.data?.error) { - return res.data.data; - } else { - handleErrorMsg(res); - return null; - } - }); -}; - -export interface TaskIdProgress { - state: "running" | "done" | "pending" | "failed" | "unknown"; - markdownUrl: string[] | []; - fullMdLink: string; - content: string[] | []; - url: string; - fileName: string; - thumb: string; - type: ExtractTaskType | "unknown"; - isTemplate?: boolean; - fileInfo?: { - pages: number; - width: number; - height: number; - }; -} - -export const getExtractTaskIdProgress = async ( - jobID: string | number -): Promise => { - return axios - .get(`/api/v2/extract/task/progress?id=${jobID}`) - .then((res) => { - if (res?.data?.error) { - handleErrorMsg(res); - } - return res.data.data; - }); -}; - -export interface TaskIdResItem { - queues: number; - rank: number; - id?: number; - url: string; - fileName?: string; - fullMdLink?: string; - type: ExtractTaskType | "unknown"; - state: "running" | "done" | "pending" | "failed" | "unknown"; - markdownUrl: string[]; - file_key?: string; -} - -export type TaskIdRes = TaskIdResItem[]; - -// Get ongoing tasks -export const getPdfExtractQueue = async (): Promise => { - return axios.get(`/api/v2/extract/taskQueue`).then((res) => { - if (!res?.data?.error) { - return res.data.data; - } else { - handleErrorMsg(res); - return null; - } - }); -}; - -interface TaskHistoryResponse { - list: TaskItem[]; - total: number; - pageNo: number; - pageSize: number; -} - -interface TaskItem { - fileName: string; - id: string; - type: string; - thumb: string; - state: string; // 提取状态 -} - -export const getExtractorHistory = ({ - pageNo, - pageSize, -}: { - pageNo?: number; - pageSize?: number; -}): Promise => { - return axios - .get( - `/api/v2/extract/list?pageNo=${pageNo || 1}&pageSize=${pageSize || 10}` - ) - .then((res) => { - if (!res?.data?.error) { - return res.data.data; - } else { - handleErrorMsg(res); - return null; - } - }); -}; - -export const deleteExtractJob = (jobId: string) => { - return axios.delete(`/api/v2/extract/task/${jobId}`); -}; - -interface UploadResponse { - file_key: string; - url: string; -} - -export const localUpload = (file: File) => { - const formData = new FormData(); - formData.append("file", file); - - return axios.post("/api/v2/analysis/upload_pdf", formData, { - headers: { - "Content-Type": "multipart/form-data", - }, - }); -}; - -export interface UpdateMarkdownRequest { - file_key: string; - data: { - [pageNumber: string]: string; - }; -} - -export interface UpdateMarkdownResponse { - success: boolean; - message?: string; -} - -export const updateMarkdownContent = async ( - params: UpdateMarkdownRequest -): Promise => { - return axios - .put("/api/v2/extract/markdown", params) - .then((res) => { - if (!res?.data?.error) { - return res.data.data; - } else { - handleErrorMsg(res); - return null; - } - }); -}; diff --git a/projects/web/src/api/http.ts b/projects/web/src/api/http.ts deleted file mode 100644 index a71f974675886ed3f4c4ff55d7995f4cf58a965f..0000000000000000000000000000000000000000 --- a/projects/web/src/api/http.ts +++ /dev/null @@ -1,92 +0,0 @@ -import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"; -import Cookies from "js-cookie"; -import { message } from "antd"; - -interface ApiResponse { - code: number; - msg: string; - data: T; -} - -interface ErrorResponse { - code: number; - msg: string; - msgZh: string; -} - -export interface ProcessedResponse { - data: T; - error: null | Pick; -} - -interface CustomAxiosInstance - extends Omit { - get>>( - url: string, - config?: AxiosRequestConfig - ): Promise; - post>>( - url: string, - data?: unknown, - config?: AxiosRequestConfig - ): Promise; - put>>( - url: string, - data?: unknown, - config?: AxiosRequestConfig - ): Promise; - delete>>( - url: string, - config?: AxiosRequestConfig - ): Promise; -} - -const instance: CustomAxiosInstance = axios.create({ - baseURL: "", - timeout: 10000, - headers: { - "Content-Type": "application/json", - }, -}); - -const processResponse = ( - response: AxiosResponse> -): ProcessedResponse => { - if (response.data.code === 200) { - return { - data: response.data.data, - error: null, - }; - } else { - return { - data: response.data.data || ({} as T), - error: { - msg: response.data.msg, - msgZh: (response.data as unknown as ErrorResponse).msgZh, - }, - }; - } -}; - -instance.interceptors.request.use( - (config) => { - return config; - }, - (error) => { - return Promise.reject(error); - } -); - -instance.interceptors.response.use( - ( - response: AxiosResponse> - ): AxiosResponse> => { - return { ...response, data: processResponse(response) }; - }, - (error) => { - message.error(error?.response?.data?.msg || "Error"); - return Promise.reject(error); - } -); - -export default instance; diff --git a/projects/web/src/api/oss.ts b/projects/web/src/api/oss.ts deleted file mode 100644 index b2d15b0b445b5635e87903a1aecd0c0286f80cf6..0000000000000000000000000000000000000000 --- a/projects/web/src/api/oss.ts +++ /dev/null @@ -1,95 +0,0 @@ -import http from "./http"; -import { UploadFile } from "antd/es/upload/interface"; -import { stringify } from "qs"; -import { localUpload } from "./extract"; - -interface IUploadRes { - downloadUrl: string; - headers: any; - key: string; - previewUrl: string; - putUrl: string; -} - -/** - * 获取上传链接的接口 - * openRead 是否返回公开链接 - */ -export const uploadUrl = ( - fileName: string, - openRead: boolean, - fileType = "" -): Promise => - http - .post( - `/datasets/api/v2/file?${stringify({ fileName, openRead, fileType })}` - ) - .then((res) => res.data.data); - -export interface IFile extends UploadFile { - url?: string; - thumbUrl?: string; - objectKey?: string; -} - -// 获取 阿里云上传链接 -export const uploadToOss = async ( - file: IFile, - openRead: boolean, - fileType = "" -): Promise => { - const { downloadUrl, previewUrl, key, putUrl, headers } = await uploadUrl( - file.name, - openRead, - fileType - ); - file.url = downloadUrl; - file.thumbUrl = previewUrl; - file.objectKey = key; - // 上传文件 - await http.put(putUrl, file, { headers: { ...headers } }); - return { - downloadUrl, - objectKey: key, - thumbUrl: previewUrl, - url: downloadUrl, - }; -}; - -interface IUploadOptions { - openRead: boolean; - fileType: string; - uploadType?: "local" | "oss"; -} - -// 可覆盖 antd customUpload 的上传逻辑 -export const customUploadToOss = async ( - options: any, - otherUploadOptions: IUploadOptions -) => { - const { openRead, fileType, uploadType = "local" } = otherUploadOptions; - const uploadFile = async () => { - switch (uploadType) { - case "oss": - return await uploadToOss(options.file, openRead, fileType) - .then((res) => { - options?.onSuccess({ ...res, ...options.file }); - return res; - }) - .catch((error) => { - options?.onError(error); - return {}; - }); - case "local": - return await localUpload(options.file); - default: - throw new Error(`Unsupported upload type: ${uploadType}`); - } - }; - try { - const res = await uploadFile(); - options?.onSuccess({ ...res, ...options.file }); - } catch (error) { - options?.onError(error); - } -}; diff --git a/projects/web/src/assets/imgs/online.experience/EmbedOutlined-active.svg b/projects/web/src/assets/imgs/online.experience/EmbedOutlined-active.svg deleted file mode 100644 index 39faacc59129acdc3f59d15c1e9162e72ca12bdb..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/imgs/online.experience/EmbedOutlined-active.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/projects/web/src/assets/imgs/online.experience/EmbedOutlined.svg b/projects/web/src/assets/imgs/online.experience/EmbedOutlined.svg deleted file mode 100644 index 6419c6366ca6482333af2e64db708ad93c82db28..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/imgs/online.experience/EmbedOutlined.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/projects/web/src/assets/imgs/online.experience/GradientGitHub.svg b/projects/web/src/assets/imgs/online.experience/GradientGitHub.svg deleted file mode 100644 index 0d52a1881775ee2963d34adf72e1f22afab57e84..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/imgs/online.experience/GradientGitHub.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/projects/web/src/assets/imgs/online.experience/PdfOutlined-active.svg b/projects/web/src/assets/imgs/online.experience/PdfOutlined-active.svg deleted file mode 100644 index 5502e4e081c4f1b2b68e974f57267a1cc69d66df..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/imgs/online.experience/PdfOutlined-active.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/projects/web/src/assets/imgs/online.experience/PdfOutlined.svg b/projects/web/src/assets/imgs/online.experience/PdfOutlined.svg deleted file mode 100644 index 1a91c03dc3fe50fa6ad074e5794e86753a1717b9..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/imgs/online.experience/PdfOutlined.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/projects/web/src/assets/imgs/online.experience/UploadingOutlined.svg b/projects/web/src/assets/imgs/online.experience/UploadingOutlined.svg deleted file mode 100644 index 16dfdee7f0e345ab08db4d47bf8af309a83c14f8..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/imgs/online.experience/UploadingOutlined.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/projects/web/src/assets/imgs/online.experience/file-upload-bg.svg b/projects/web/src/assets/imgs/online.experience/file-upload-bg.svg deleted file mode 100644 index f27c192513cec4243b87d9f259b0402a68787a66..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/imgs/online.experience/file-upload-bg.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/comingSoonLayer.svg b/projects/web/src/assets/pdf/comingSoonLayer.svg deleted file mode 100644 index 52fd4b8d08b794ca177222157c1e858a8bfe3bf9..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/comingSoonLayer.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/exitFullScreen.svg b/projects/web/src/assets/pdf/exitFullScreen.svg deleted file mode 100644 index ddeaa684fcd990cc1aa49bf8c4a334d705d1e31a..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/exitFullScreen.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/projects/web/src/assets/pdf/extractor-formula.svg b/projects/web/src/assets/pdf/extractor-formula.svg deleted file mode 100644 index b3fb750e22cc33c61c798b216c52797c4968b346..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/extractor-formula.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/extractor-hidden-layer.svg b/projects/web/src/assets/pdf/extractor-hidden-layer.svg deleted file mode 100644 index cb6af13c4cc75cf85a35c6bbd99215f0b4a9be23..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/extractor-hidden-layer.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/extractor-pdf.svg b/projects/web/src/assets/pdf/extractor-pdf.svg deleted file mode 100644 index b2f5f35f0c20fc23895439d570bd24f411ff4873..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/extractor-pdf.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/extractor-queue.svg b/projects/web/src/assets/pdf/extractor-queue.svg deleted file mode 100644 index 2a4835dd3d0f8e2e1dfa8aab04a54d2b3f181ce7..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/extractor-queue.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/extractor-show-layer.svg b/projects/web/src/assets/pdf/extractor-show-layer.svg deleted file mode 100644 index fc4582a966f39d22d81b4aedda5e4956e85cc2f6..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/extractor-show-layer.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/extractor-table.svg b/projects/web/src/assets/pdf/extractor-table.svg deleted file mode 100644 index 010de17735c283cab2c1f2350dfab28d74495c4c..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/extractor-table.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/fullScreen.svg b/projects/web/src/assets/pdf/fullScreen.svg deleted file mode 100644 index 24f4a8db9de5ce597d84745ad86d51f03f8c6bbc..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/fullScreen.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/projects/web/src/assets/pdf/github.svg b/projects/web/src/assets/pdf/github.svg deleted file mode 100644 index 10a6144e767ef2989ec854ef34946955e9f8f940..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/github.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/projects/web/src/assets/pdf/guideTools.svg b/projects/web/src/assets/pdf/guideTools.svg deleted file mode 100644 index e6a2943837b2c414f0e87b6fd63b25cf0db4a71e..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/guideTools.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/label-llm.svg b/projects/web/src/assets/pdf/label-llm.svg deleted file mode 100644 index 3e6aaf3c76b97796f40787182327948fd06232ca..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/label-llm.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/labelU.svg b/projects/web/src/assets/pdf/labelU.svg deleted file mode 100644 index 75c1e9cbcfcad02bf35f4eb38112d0334ba2c12d..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/labelU.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/lang-change.svg b/projects/web/src/assets/pdf/lang-change.svg deleted file mode 100644 index dc08142389185d93dbc864c37d6563471fad5174..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/lang-change.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/projects/web/src/assets/pdf/odl-logo.svg b/projects/web/src/assets/pdf/odl-logo.svg deleted file mode 100644 index e81c8bfd68a5cefd775b3fc88b44fb6097406438..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/odl-logo.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/pdf-upload-item-1.svg b/projects/web/src/assets/pdf/pdf-upload-item-1.svg deleted file mode 100644 index f03c27e4cea1f9151551cb126b92038844a6f1a2..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/pdf-upload-item-1.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/pdf-upload-item-2.svg b/projects/web/src/assets/pdf/pdf-upload-item-2.svg deleted file mode 100644 index 16076f479216c878b171862d3a69f3115029f37e..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/pdf-upload-item-2.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/pdf-upload-item-3.svg b/projects/web/src/assets/pdf/pdf-upload-item-3.svg deleted file mode 100644 index 84874476f2bd6a5f0cf9041ec07e26038009c438..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/pdf/pdf-upload-item-3.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/web/src/assets/pdf/pdf-upload.png b/projects/web/src/assets/pdf/pdf-upload.png deleted file mode 100644 index 1aced014cd7438d17e72fb5c26669078d11ceab6..0000000000000000000000000000000000000000 Binary files a/projects/web/src/assets/pdf/pdf-upload.png and /dev/null differ diff --git a/projects/web/src/assets/react.svg b/projects/web/src/assets/react.svg deleted file mode 100644 index 6c87de9bb3358469122cc991d5cf578927246184..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/projects/web/src/assets/svg/empty.svg b/projects/web/src/assets/svg/empty.svg deleted file mode 100644 index 2407ee65b83beda4e1f5584037f0a240576ada02..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/svg/empty.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/projects/web/src/assets/svg/logo.svg b/projects/web/src/assets/svg/logo.svg deleted file mode 100644 index c98fd8622b704542b1c77f4f8523f05e177dbbcf..0000000000000000000000000000000000000000 --- a/projects/web/src/assets/svg/logo.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/web/src/components/SaveStatus.tsx b/projects/web/src/components/SaveStatus.tsx deleted file mode 100644 index 75c8a3ee05f4d47ba94adccaa1aed14fdd761a16..0000000000000000000000000000000000000000 --- a/projects/web/src/components/SaveStatus.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import React, { - useState, - useEffect, - useImperativeHandle, - forwardRef, -} from "react"; -import cls from "classnames"; - -interface SaveStatusProps { - className?: string; -} - -export interface SaveStatusRef { - triggerSave: () => void; - reset: () => void; // 新增的重置方法 -} - -const SaveStatus = forwardRef( - ({ className }, ref) => { - const [lastSaveTime, setLastSaveTime] = useState(null); - const [showSaved, setShowSaved] = useState(false); - const [timeSinceLastSave, setTimeSinceLastSave] = useState(0); - - useImperativeHandle(ref, () => ({ - triggerSave: () => { - setLastSaveTime(new Date()); - setShowSaved(true); - }, - reset: () => { - // 新增的重置方法 - setLastSaveTime(null); - setShowSaved(false); - setTimeSinceLastSave(0); - }, - })); - - useEffect(() => { - if (showSaved) { - const timer = setTimeout(() => { - setShowSaved(false); - }, 10000); - return () => clearTimeout(timer); - } - }, [showSaved]); - - useEffect(() => { - const updateTimeSinceLastSave = () => { - if (lastSaveTime) { - const now = new Date(); - const diffInMinutes = Math.floor( - (now.getTime() - lastSaveTime.getTime()) / 60000 - ); - if (diffInMinutes > 0) { - setTimeSinceLastSave(diffInMinutes); - } - } - }; - - const timer = setInterval(updateTimeSinceLastSave, 60000); - updateTimeSinceLastSave(); // 立即更新一次 - return () => clearInterval(timer); - }, [lastSaveTime]); - - return ( -
    - {showSaved && ( - - 已保存 - - )} - {timeSinceLastSave > 0 && !showSaved && lastSaveTime && ( - - 最近修改:{timeSinceLastSave} 分钟前 - - )} - {(showSaved || - (timeSinceLastSave > 0 && !showSaved && lastSaveTime)) && ( - - )} -
    - ); - } -); - -export default SaveStatus; diff --git a/projects/web/src/components/code-mirror/index.module.scss b/projects/web/src/components/code-mirror/index.module.scss deleted file mode 100644 index cf19f6e2438584ed7abdf0bfc1bd6a95d2aa004b..0000000000000000000000000000000000000000 --- a/projects/web/src/components/code-mirror/index.module.scss +++ /dev/null @@ -1,11 +0,0 @@ -.code-mirror { - :global { - .ͼ1 .cm-scroller { - overflow-x: visible !important; - border: none !important; - } - .cm-editor.cm-focused { - outline: none !important; - } - } -} \ No newline at end of file diff --git a/projects/web/src/components/code-mirror/index.tsx b/projects/web/src/components/code-mirror/index.tsx deleted file mode 100644 index e911a53990c05ecbdf168659607bf6338a243c3b..0000000000000000000000000000000000000000 --- a/projects/web/src/components/code-mirror/index.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React, { PropsWithChildren } from "react"; -import ReactCodeMirror, { EditorView, Extension } from "@uiw/react-codemirror"; -import { loadLanguage } from "@uiw/codemirror-extensions-langs"; -import cls from "classnames"; -import style from "./index.module.scss"; -// import { scrollPastEnd } from "@codemirror/view"; - -interface IProps { - className?: string; - editable?: boolean; - language?: "json" | "markdown" | "yaml"; - value: string; - onChange?: (value: string) => void; - lineWrapping?: boolean; - onBeforeChange?: (editor: any, data: any, value: any) => void; -} - -const CodeMirror: React.FC> = ({ - language = "markdown", - value, - className, - onChange, - lineWrapping, - onBeforeChange, - editable, -}) => { - // const noScrollPastEnd = scrollPastEnd(); - const extensions = [ - { - ext: EditorView.lineWrapping, - on: lineWrapping, - }, - { - ext: loadLanguage(language), - on: true, - }, - ] - .map((i) => (i.on ? i.ext : null)) - .filter(Boolean) as Extension[]; - - return ( - { - onChange?.(v); - }} - /> - ); -}; -export default React.memo(CodeMirror); diff --git a/projects/web/src/components/error-boundary.tsx b/projects/web/src/components/error-boundary.tsx deleted file mode 100644 index e4b598f7fbdd05ba6912062e12deada99ab2fe83..0000000000000000000000000000000000000000 --- a/projects/web/src/components/error-boundary.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Component, ErrorInfo, ReactNode } from "react"; - -interface Props { - children: ReactNode; - fallback?: ReactNode; -} - -interface State { - hasError: boolean; -} - -class ErrorBoundary extends Component { - constructor(props: Props) { - super(props); - this.state = { hasError: false }; - } - - static getDerivedStateFromError(_: Error): State { - return { hasError: true }; - } - - componentDidCatch(error: Error, errorInfo: ErrorInfo) { - console.error("ErrorBoundary caught an error:", error, errorInfo); - } - - render() { - if (this.state.hasError) { - return ( - this.props.children || ( -

    - Error -

    - ) - ); - } - - return this.props.children; - } -} - -export default ErrorBoundary; diff --git a/projects/web/src/components/icon-font.tsx b/projects/web/src/components/icon-font.tsx deleted file mode 100644 index ab41235bfb2a464fe5b9c7cd43aa4de87854558d..0000000000000000000000000000000000000000 --- a/projects/web/src/components/icon-font.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { createFromIconfontCN } from "@ant-design/icons"; - -const IconFont = createFromIconfontCN({ - scriptUrl: `/iconfont.js`, -}); - -export default IconFont; diff --git a/projects/web/src/components/loading-animation/index.tsx b/projects/web/src/components/loading-animation/index.tsx deleted file mode 100644 index 8331ee52331be9afbf23f55294d113dccd281a6b..0000000000000000000000000000000000000000 --- a/projects/web/src/components/loading-animation/index.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import styles from './loadingAnimation.module.scss'; - -interface ILoadingAnimationProps { - className?: string; -} - -const LoadingAnimation = (props: ILoadingAnimationProps) => { - const { className } = props; - return
    ; -}; - -export default LoadingAnimation; diff --git a/projects/web/src/components/loading-animation/loadingAnimation.module.scss b/projects/web/src/components/loading-animation/loadingAnimation.module.scss deleted file mode 100644 index 1ad6a664d9ad9002be2fcc7c869e4103ab699a22..0000000000000000000000000000000000000000 --- a/projects/web/src/components/loading-animation/loadingAnimation.module.scss +++ /dev/null @@ -1,29 +0,0 @@ -.loader { - width: 14px; - height: 14px; - border-radius: 50%; - display: inline-block; - position: relative; - /* stylelint-disable-next-line alpha-value-notation */ - background: linear-gradient(0deg, rgba(13,83,222,1) 0%, rgba(43,105,226,1) 30%, rgba(13, 20, 222, 0) 100%); - box-sizing: border-box; - animation: rotation 1.5s linear infinite; -} - -.loader::after { - content: ''; - box-sizing: border-box; - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - width: 10px; - height: 10px; - border-radius: 50%; - background: #fff; -} - -@keyframes rotation { - 0% { transform: rotate(0deg) } - 100% { transform: rotate(360deg)} -} diff --git a/projects/web/src/components/text-tooltip/index.module.scss b/projects/web/src/components/text-tooltip/index.module.scss deleted file mode 100644 index 75c8134768715efbd24c1ed9d038504685597854..0000000000000000000000000000000000000000 --- a/projects/web/src/components/text-tooltip/index.module.scss +++ /dev/null @@ -1,12 +0,0 @@ -.textTooltip { - :global { - .ant-tooltip-arrow { - // display: none !important; - } - .ant-tooltip-inner, .ant-tooltip-content, .ant-tooltip-inner-content { - padding: 0px !important; - border-radius: 4px !important; - overflow: hidden; - } - } -} diff --git a/projects/web/src/components/text-tooltip/index.tsx b/projects/web/src/components/text-tooltip/index.tsx deleted file mode 100644 index 5505732bc5d9887e1dcbf466a3fe05e6f278c96d..0000000000000000000000000000000000000000 --- a/projects/web/src/components/text-tooltip/index.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { Popover, Tooltip } from 'antd'; -import React, { useRef, useState } from 'react'; -import styles from './index.module.scss'; - -import { RefObject } from 'react'; -import { useIsomorphicLayoutEffect, useMemoizedFn } from 'ahooks'; - -export function useResizeEffect(effect: (target: T) => void, targetRef: RefObject) { - const fn = useMemoizedFn(effect); - useIsomorphicLayoutEffect(() => { - const target = targetRef.current; - if (!target) return; - if (window.ResizeObserver) { - let animationFrame: number; - const observer = new ResizeObserver(() => { - animationFrame = window.requestAnimationFrame(() => fn(target)); - }); - observer.observe(target); - return () => { - window.cancelAnimationFrame(animationFrame); - observer.disconnect(); - }; - } else { - fn(target); - } - }, [targetRef]); -} - -interface ITextTooltip { - style?: React.CSSProperties; - str: string; - suffix?: React.ReactNode | string; - trigger?: 'hover' | 'click'; - handleClick?: () => void; -} - -export const TextTooltip = (props: ITextTooltip) => { - const { style = {}, str, trigger = 'click', suffix, handleClick } = props; - const rootRef = useRef(null); - const tooltipRef = useRef(null); - const [clickable, setClickable] = useState(false); - function calcEllipsised() { - // 没有被截断 - if (tooltipRef!?.current!?.scrollWidth > tooltipRef!?.current!?.clientWidth) { - setClickable(true); - } else { - setClickable(false); - } - } - useResizeEffect(calcEllipsised, rootRef); - - return ( - {str}} - trigger={clickable ? trigger : ('' as 'click')} - overlayClassName={styles.textTooltip} - style={{ width: '100%' }} - zIndex={999999} - placement="right" - align={{ - offset: [72, 0] - }} - > -
    -
    - handleClick?.()}>{str} -
    - {suffix} -
    -
    - ); -}; diff --git a/projects/web/src/components/upload/index.tsx b/projects/web/src/components/upload/index.tsx deleted file mode 100644 index c287c6e7816cf43c2e56a208664bbe2fb2b83500..0000000000000000000000000000000000000000 --- a/projects/web/src/components/upload/index.tsx +++ /dev/null @@ -1,34 +0,0 @@ -// cl 2022/4/21 18:22 -import { customUploadToOss } from "@/api/oss"; -import { Upload as AntdUpload } from "antd"; -import { DraggerProps, UploadProps } from "antd/es/upload"; -import React from "react"; - -interface IProps extends UploadProps, DraggerProps { - isDragger?: boolean; - openRead?: boolean; - taskType?: string; - changeOption?: (option: any) => any; -} - -const Upload: React.FC = (props) => { - const { isDragger, openRead, taskType, changeOption, ...rest } = props; - const Component = isDragger ? AntdUpload.Dragger : AntdUpload; - - return ( - - customUploadToOss(changeOption ? changeOption?.(options) : options, { - openRead: openRead || false, - fileType: taskType || "pdf", - uploadType: "local", - }) - } - > - {props.children} - - ); -}; - -export default Upload; diff --git a/projects/web/src/constant/event.ts b/projects/web/src/constant/event.ts deleted file mode 100644 index d4d3596e7ed4fe26a8737c2ca7e68a333d78ca87..0000000000000000000000000000000000000000 --- a/projects/web/src/constant/event.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const PDF_DRIVE_MD = "pdf-drive-md"; -export const MD_DRIVE_PDF = "pdf-drive-md"; - -export const ADD_TASK_LIST = "add-task-list"; - -export const UPDATE_TASK_LIST = "update-task-list"; diff --git a/projects/web/src/constant/index.tsx b/projects/web/src/constant/index.tsx deleted file mode 100644 index 94294addd8207f828d0a36b3fc57b6feec527686..0000000000000000000000000000000000000000 --- a/projects/web/src/constant/index.tsx +++ /dev/null @@ -1,4 +0,0 @@ -export enum Language { - ZH_CN = "zh-CN", - EN_US = "en-US", -} diff --git a/projects/web/src/constant/pdf-color-picker.ts b/projects/web/src/constant/pdf-color-picker.ts deleted file mode 100644 index ddcdd7bf148530f3c44d3cf129495db1393641b1..0000000000000000000000000000000000000000 --- a/projects/web/src/constant/pdf-color-picker.ts +++ /dev/null @@ -1,38 +0,0 @@ -export const PDF_COLOR_PICKER = { - title: { - line: 'rgba(121, 124, 255, 1)', - fill: 'rgba(121, 124, 255, 0.4)' - }, - text: { - line: 'rgba(230, 122, 171, 1)', - fill: 'rgba(230, 122, 171, 0.4)' - }, - interline_equation: { - line: 'rgba(240, 240, 124, 1)', - fill: 'rgba(240, 240, 124, 0.4)' - }, - discarded: { - line: 'rgba(164,164,164,1)', - fill: 'rgba(164,164,164,0.4)' - }, - image: { - line: 'rgba(149, 226, 115, 1)', - fill: 'rgba(149, 226, 115, 0.4)' - }, - table: { - line: 'rgba(230, 113, 230, 1)', - fill: 'rgba(230, 113, 230, 0.4)' - }, - inline_equation: { - line: 'rgba(150, 232, 172, 1)', - fill: 'rgba(150, 232, 172, 0.4)' - } - }; - - export const DEFAULT_COLOR_SECTION = { - line: 'rgba(166, 113, 230, 1)', - fill: 'rgba(166, 113, 230, 0.4)' - }; - - export const PDF_TEMPLATE_URL_KEY = 't'; - \ No newline at end of file diff --git a/projects/web/src/constant/route.ts b/projects/web/src/constant/route.ts deleted file mode 100644 index eba3e053984bcba115f6cb8495244859aad5df92..0000000000000000000000000000000000000000 --- a/projects/web/src/constant/route.ts +++ /dev/null @@ -1,8 +0,0 @@ -export enum Path { - Home = "/", - Settings = "/settings", -} - -export enum SlotID { - AppBody = "app-body", -} diff --git a/projects/web/src/constant/storage.ts b/projects/web/src/constant/storage.ts deleted file mode 100644 index eb179c95cc8134ef246a21fb72d6dcdccb1e0cb6..0000000000000000000000000000000000000000 --- a/projects/web/src/constant/storage.ts +++ /dev/null @@ -1 +0,0 @@ -export const LOCALE_STORAGE_KEY = "locale-minerU" \ No newline at end of file diff --git a/projects/web/src/context/language-provider.tsx b/projects/web/src/context/language-provider.tsx deleted file mode 100644 index 45da0e443a0116b68f9e702d5331b631ed16b8e3..0000000000000000000000000000000000000000 --- a/projects/web/src/context/language-provider.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React from "react"; -import { IntlProvider } from "react-intl"; -import { useLanguageStore } from "@/store/languageStore"; -import contentEn from "@/locale/en.json"; -import contentZh from "@/locale/zh.json"; -import sideEn from "@/locale/side/en.ts"; -import sideZh from "@/locale/side/zh.ts"; -import commonEn from "@/locale/common/en.json"; -import commonZh from "@/locale/common/zh.json"; -import { Language } from "@/constant"; - -const messages = { - [Language.EN_US]: { - ...contentEn, - ...sideEn, - ...commonEn, - }, - [Language.ZH_CN]: { - ...contentZh, - ...sideZh, - ...commonZh, - }, -}; - -export const LanguageProvider: React.FC<{ children: React.ReactNode }> = ({ - children, -}) => { - const { language } = useLanguageStore(); - - return ( - } - locale={language} - defaultLocale="en" - > - {children} - - ); -}; diff --git a/projects/web/src/context/query-provider.tsx b/projects/web/src/context/query-provider.tsx deleted file mode 100644 index f49680ea3519e2ef8fbdeb1315a6656a6f934c9a..0000000000000000000000000000000000000000 --- a/projects/web/src/context/query-provider.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// QueryProvider.tsx -import React from "react"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; - -const defaultQueryClientConfig = { - defaultOptions: { - queries: { - retry: false, - refetchOnWindowFocus: false, - staleTime: 5 * 60 * 1000, // 5 minutes - }, - }, -}; - -interface QueryProviderProps { - children: React.ReactNode; -} - -const QueryProvider: React.FC = ({ children }) => { - const queryClient = new QueryClient({ - ...defaultQueryClientConfig, - }); - - return ( - {children} - ); -}; - -export default QueryProvider; diff --git a/projects/web/src/index.css b/projects/web/src/index.css deleted file mode 100644 index d02814cc52975ddb56a2d7e51280e7ccadfce878..0000000000000000000000000000000000000000 --- a/projects/web/src/index.css +++ /dev/null @@ -1,74 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - - -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(0, 0, 0, 0.87); - background-color: white; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} - diff --git a/projects/web/src/locale/common/en.json b/projects/web/src/locale/common/en.json deleted file mode 100644 index e9d5d11de88be13da3f1ffb12697bc04ea79f7c2..0000000000000000000000000000000000000000 --- a/projects/web/src/locale/common/en.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "common.cancel": "Cancel", - "common.confirm": "Confirm", - "common.retry": "retry" -} \ No newline at end of file diff --git a/projects/web/src/locale/common/zh.json b/projects/web/src/locale/common/zh.json deleted file mode 100644 index 65cf5ec8fb809a4377625172891415e0161aa73b..0000000000000000000000000000000000000000 --- a/projects/web/src/locale/common/zh.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "common.cancel": "取消", - "common.confirm": "确定", - "common.retry": "retry" -} \ No newline at end of file diff --git a/projects/web/src/locale/en.json b/projects/web/src/locale/en.json deleted file mode 100644 index 77b71f14651af5f95d1f58e76317d1eef020140f..0000000000000000000000000000000000000000 --- a/projects/web/src/locale/en.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "extractor.common.upload": "Click to upload file", - "extractor.common.try": "Try:", - "extractor.home": "Home", - "extractor.button.download": "Download", - "extractor.button.lineWrap": "Line Wrap", - "extractor.button.fullScreen": "Fullscreen", - "extractor.button.exitFullScreen": "Exit Fullscreen", - "extractor.button.showLayer": "Display recognition results", - "extractor.button.hiddenLayer": "Hide recognition results", - "extractor.error": "Extraction failed", - "extractor.law": "Please ensure that the documents you upload are legal and compliant, and we do not assume legal responsibility for the content of the documents. Data Protection Policy Children's Information Protection Policy Service Agreement | © All Rights Reserved.Shanghai ICP 2021009351-21", - "extractor.button.reUpload": "Re-Upload", - "extractor.failed": "Unable to extract, no data to display yet", - "extractor.common.extracting": "Extracting, please wait", - "extractor.common.extracting.queue": "Queuing for extraction, currently ranked at {id}", - "extractor.common.loading": "Loading", - "extractor.common.pdf.demo1": "Example1.pdf", - "extractor.common.pdf.demo2": "Example2.pdf", - "extractor.common.formula.detect.demo1": "FormulaDetail1.jpg", - "extractor.common.formula.extract.demo1": "FormulaExtract1.jpg", - "extractor.common.login.desc": "Functionality available after login", - "extractor.markdown.preview": "Preview", - "extractor.markdown.code": "Code", - "extractor.home.title": "Welcome to Miner U", - "extractor.home.subTitle": "Upload documents and intelligently extract them into Markdown format", - "extractor.side.extractTask": "Extraction Tasks", - "extractor.side.extractTask.title": "Please upload a PDF document within 5M (within 10 pages) or a JPG/PNG image", - "extractor.pdf.title": "PDF Document Extraction", - "extractor.pdf.subTitle": "Supports text/scanned PDF parsing, identifies various layout elements and converts them into multimodal Markdown format", - "extractor.common.pdf.upload.tip": "Please upload a PDF document", - "extractor.pdf.ocr": "OCR Identify Pattern", - "extractor.pdf.ocr.popover": "By default, PDF types (text-based, scanned) will be automatically recognized, and based on the recognition results, you can choose to use text recognition or OCR recognition. If enabled, all types of PDF will be recognized by OCR.", - "extractor.formula.title2": "Recognize mathematical formulas in images as LaTex format, support multi-line formulas and handwritten formula recognition", - "extractor.formula.title": "Locate the formulas within and between rows in the image and generate bounding boxes", - "extractor.formula.upload.text": "Click to upload an image", - "extractor.formula.popover.extract": "In order to obtain the best formula recognition effect, please crop the image, focus on the formula part, and upload a clear, watermark-free image of the mathematical formula, as shown below", - "extractor.formula.popover.detect": "In order to get the best formula recognition effect, please upload clear, non-watermarked images containing mathematical formulas, as shown below", - "extractor.formula.upload.accept": "Please upload a JPG/PNG image within 5M", - "extractor.formula.upload.try": "Please upload an image containing a mathematical formula Example: ", - "extractor.guide.title": "Welcome to use more open source products 🎉", - "extractor.queue": "Extract records", - "extractor.queue.delete": "Confirm to delete this file?", - "extractor.queue.extracting": "Extracting", - "extractor.feedback.title1": "Are you satisfied with the overall extraction performance?", - "extractor.feedback.title3": "Look forward to your suggestions to help us better optimize", - "extractor.feedback.up.title": "What improvements are you expecting to see?", - "extractor.feedback.down.title": "What is the reason for your dissatisfaction? ", - "extractor.feedback.up": "Satisfied", - "extractor.feedback.down": "Dissatisfied", - "extractor.feedback.input.placeholder": "Please enter your suggestions for improvement", - "extractor.feedback.input.submit": "Submit", - "extractor.feedback.success": "Thank you for the feedback", - "extractor.queue.delete.success": "Delete successfully" -} \ No newline at end of file diff --git a/projects/web/src/locale/side/en.ts b/projects/web/src/locale/side/en.ts deleted file mode 100644 index 1c8e3fc66a5ecc716ac33023d9285e9e9d85e54f..0000000000000000000000000000000000000000 --- a/projects/web/src/locale/side/en.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { EXTRACTOR_TYPE_LIST } from "@/types/extract-task-type"; -import odlLogo from "@/assets/pdf/odl-logo.svg"; -import labelLLMLogo from "@/assets/pdf/label-llm.svg"; -import labelULogo from "@/assets/pdf/labelU.svg"; - -export default { - "extractor.side.tabList": [ - { - label: "PDF Extraction", - type: EXTRACTOR_TYPE_LIST.pdf, - }, - // { - // label: "Formula Extraction", - // type: EXTRACTOR_TYPE_LIST.formula, - // }, - ], - "extractor.side.guide_list": [ - { - type: "odl", - icon: odlLogo, - title: "OpenDataLab", - desc: "Covers a huge amount of high-quality, multimodal datasets", - goToText: "Go Now", - link: "https://opendatalab.com", - }, - { - type: "labelU", - icon: labelULogo, - title: "Label U Labeling Tool", - desc: "Lightweight open source annotation tools", - goToText: "github", - link: "https://github.com/opendatalab/labelU", - }, - { - type: "labelLLM", - icon: labelLLMLogo, - [`zh-CN-title`]: "LabelLLM Labeling Tool", - title: "LabelLLM Labeling Tool", - desc: "Specializing in dialogue annotation for large language models", - goToText: "github", - link: "https://github.com/opendatalab/LabelLLM", - }, - ], -}; diff --git a/projects/web/src/locale/side/zh.ts b/projects/web/src/locale/side/zh.ts deleted file mode 100644 index 7b243fb62838369827bfb37ca87669ed649c6794..0000000000000000000000000000000000000000 --- a/projects/web/src/locale/side/zh.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { EXTRACTOR_TYPE_LIST } from "@/types/extract-task-type"; -import odlLogo from "@/assets/pdf/odl-logo.svg"; -import labelLLMLogo from "@/assets/pdf/label-llm.svg"; -import labelULogo from "@/assets/pdf/labelU.svg"; - -export default { - "extractor.side.tabList": [ - { - label: "PDF文档提取", - type: EXTRACTOR_TYPE_LIST.pdf, - }, - // { - // label: "公式检测与识别", - // type: EXTRACTOR_TYPE_LIST.formula, - // }, - ], - "extractor.side.guide_list": [ - { - type: "odl", - icon: odlLogo, - title: "OpenDataLab", - desc: "涵盖海量优质、多模态数据集", - goToText: "立即前往", - link: "https://opendatalab.com", - }, - { - type: "labelU", - icon: labelULogo, - title: "Label U 标注工具", - desc: "轻量级开源标注工具", - goToText: "github", - link: "https://github.com/opendatalab/labelU", - }, - { - type: "labelLLM", - icon: labelLLMLogo, - title: "LabelLLM 标注工具", - desc: "专攻于大模型的对话标注", - goToText: "github", - link: "https://github.com/opendatalab/LabelLLM", - }, - ], -}; diff --git a/projects/web/src/locale/zh.json b/projects/web/src/locale/zh.json deleted file mode 100644 index 1c7c7d2ca48dc378d6bbcbfc6d2e5496ff237a38..0000000000000000000000000000000000000000 --- a/projects/web/src/locale/zh.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "extractor.common.upload": "点击上传文件", - "extractor.common.try": "试一试:", - "extractor.home": "首页", - "extractor.button.download": "下载", - "extractor.button.lineWrap": "换行", - "extractor.button.fullScreen": "全屏", - "extractor.button.exitFullScreen": "退出全屏", - "extractor.button.showLayer": "显示识别结果", - "extractor.button.hiddenLayer": "隐藏识别结果", - "extractor.button.reUpload": "重新上传", - "extractor.error": "提取失败", - "extractor.common.loading": "加载中", - "extractor.law": "请确保您上传的文件合法合规,我们不承担因文件内容产生的法律责任。《信息保护政策》 《儿童信息保护政策》《服务协议》|© All Rights Reserved.沪ICP备2021009351号-21", - "extractor.failed": "不可提取,暂无可展示数据", - "extractor.common.extracting": "提取中,请稍等", - "extractor.common.extracting.queue": "正在排队提取,当前排在第 {id} 位", - "extractor.common.pdf.demo1": "示例1.pdf", - "extractor.common.pdf.demo2": "示例2.pdf", - "extractor.common.formula.detect.demo1": "公式检测1.jpg", - "extractor.common.formula.extract.demo1": "公式识别1.jpg", - "extractor.common.login.desc": "登录后可使用完整功能", - "extractor.markdown.preview": "预览", - "extractor.markdown.code": "代码", - "extractor.home.title": "欢迎使用 Miner U", - "extractor.home.subTitle": "上传文档,智能提取为 Markdown 格式", - "extractor.side.extractTask": "提取任务", - "extractor.side.extractTask.title": "请上传 5M 以内的 PDF 文档 ( 10 页以内)或 JPG/PNG 图片", - "extractor.pdf.title": "PDF文档提取", - "extractor.pdf.subTitle": "支持文本/扫描型 PDF 解析,识别各类版面元素并转换为多模态 Markdown 格式", - "extractor.common.pdf.upload.tip": "请上传 PDF 文档", - "extractor.pdf.ocr": "OCR 识别模式", - "extractor.pdf.ocr.popover": " 默认将自动识别PDF类型(文本型、扫描型),并根据识别结果选择采用文本识别或者OCR识别方式。 如开启,将对所有类型PDF采用OCR识别方式。", - "extractor.formula.title": "定位图片中的行内、行间公式,生成边界框", - "extractor.formula.title2": "将图片中的数学公式识别为 laTex 格式,支持多行公式、手写公式识别", - "extractor.formula.upload.text": "点击上传图片", - "extractor.formula.popover.extract": "为获得最佳的公式识别效果,请上传清晰、无水印的包含数学公式的图片,如下图", - "extractor.formula.popover.detect": "为获得最佳的公式识别效果,请裁剪图片,聚焦公式部分,上传清晰、无水印的数学公式图片,如下图", - "extractor.formula.upload.accept": "请上传 5M 以内的JPG/PNG 图片", - "extractor.formula.upload.try": "请上传包含数学公式的图片 示例:", - "extractor.guide.title": "欢迎使用更多开源产品 🎉", - "extractor.queue": "提取记录", - "extractor.queue.delete": "确认删除此文件?", - "extractor.queue.extracting": "提取中", - "extractor.feedback.title1": "您对整体提取效果是否满意 ?", - "extractor.feedback.title3": "期待您的建议,帮助我们更好的优化", - "extractor.feedback.up.title": "您期望看到哪些改进?", - "extractor.feedback.down.title": "您感到不满意的原因是?", - "extractor.feedback.up": "满意", - "extractor.feedback.down": "不满意", - "extractor.feedback.input.placeholder": "请输入您的改进建议", - "extractor.feedback.input.submit": "提交", - "extractor.feedback.success": "感谢你的反馈", - "extractor.queue.delete.success": "删除成功" -} \ No newline at end of file diff --git a/projects/web/src/main.tsx b/projects/web/src/main.tsx deleted file mode 100644 index 6f4ac9bcca823100838b88e0b570a28d2fbde6b1..0000000000000000000000000000000000000000 --- a/projects/web/src/main.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import App from './App.tsx' -import './index.css' - -createRoot(document.getElementById('root')!).render( - - - , -) diff --git a/projects/web/src/pages/extract-side/index.module.scss b/projects/web/src/pages/extract-side/index.module.scss deleted file mode 100644 index 8252101b1740ee6e0b6fbe9db2109bd54cf0afdf..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract-side/index.module.scss +++ /dev/null @@ -1,38 +0,0 @@ -@import '@/styles/variable.scss'; - -.gradientBtn { - width: 179px; - height: 37px; - border-radius: 4px; - font-size: 14px; - color: rgba(255, 255, 255, 0.95); - // background: linear-gradient(110deg, #38A0FF -33.56%, #0D53DE 32.84%, #5246FF 102.05%); - background: #3477EB; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - &:hover { - background: #3477EB; - } - } - - .linearBlue { - // TIP: 这里为啥用bg呢,因为ui稿给的参数是假的 - background: url('@/assets/pdf/pdf-upload.png'); - background-size: cover; - } - - .tryText { - font-size: 13px; - line-height: 20px; - background: linear-gradient(107deg, #38A0FF -24.14%, #0D53DE 30.09%, #5246FF 86.61%); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - } - - .extractorContainer { - min-width: $page-min-witch; - } - \ No newline at end of file diff --git a/projects/web/src/pages/extract-side/index.tsx b/projects/web/src/pages/extract-side/index.tsx deleted file mode 100644 index 2ef9c9f6fd21b7ef421bc0efa2e8dcad39bf2507..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract-side/index.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import DarkLogo from "@/assets/svg/logo.svg"; - -import { useLocation, useNavigate, useParams } from "react-router-dom"; -import commonStyles from "./index.module.scss"; - -import { EXTRACTOR_TYPE_LIST } from "@/types/extract-task-type"; - -import extractorPdfIcon from "@/assets/pdf/extractor-pdf.svg"; -import extractorTableIcon from "@/assets/pdf/extractor-table.svg"; -import extractorFormulaIcon from "@/assets/pdf/extractor-formula.svg"; -import { useIntl } from "react-intl"; -import cls from "classnames"; -import ExtractorGuide from "@/pages/extract/components/extractor-guide"; -import ExtractorQueue from "@/pages/extract/components/extractor-queue"; -import ExtractorLang from "@/pages/extract/components/extractor-lang"; - -interface IExtractorSideProps { - className?: string; -} - -interface TabItem { - label: string; - type: string; -} - -export const ExtractorSide = ({ className = "" }: IExtractorSideProps) => { - const navigate = useNavigate(); - - const params = useParams(); - const location = useLocation(); - const { messages } = useIntl(); - - const menuClass = - "px-2 py-2.5 mb-1 text-[0.875rem] text-[#121316]/[0.8] font-semibold rounded h-10 flex items-center cursor-pointer hover:bg-[#0d53de]/[0.05]"; - - const handleMenuClick = (type: string) => { - navigate(`/OpenSourceTools/Extractor/${type}`); - }; - const goToOpenSource = () => { - navigate("/OpenSourceTools/Extractor/"); - }; - - const tabList = - (messages?.["extractor.side.tabList"] as unknown[] as TabItem[]) || []; - - const getIconStyle = (type: string) => { - const activeClassName = "!bg-[#0d53de]/[0.05] !text-[#0D53DE]"; - const path = location.pathname; - const regex = /\/Extractor\/([^/]+)(\/|$)/; - - const match = params?.jobID ? "" : path.match(regex)?.[1] || "/"; - - const getIcon = () => { - switch (type) { - case EXTRACTOR_TYPE_LIST.pdf: - return extractorPdfIcon; - case EXTRACTOR_TYPE_LIST.table: - return extractorTableIcon; - case EXTRACTOR_TYPE_LIST.formula: - return extractorFormulaIcon; - } - }; - return { - icon: getIcon(), - tabClassName: match === type ? activeClassName : "", - }; - }; - - return ( -
    -
    -
    - - -
    - - {/* tab-list */} -
    - {tabList.map((i) => ( -
    handleMenuClick(i.type)} - > - - {i.label} -
    - ))} -
    -
    -
    - - -
    - ); -}; diff --git a/projects/web/src/pages/extract/components/extractor-guide/index.module.scss b/projects/web/src/pages/extract/components/extractor-guide/index.module.scss deleted file mode 100644 index ccd28644b51d28ec87dbe0c57eae9eba1b96ffa1..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/extractor-guide/index.module.scss +++ /dev/null @@ -1,18 +0,0 @@ -.extractorGuide { - :global { - - .ant-popover-content, .ant-popover-inner { - border-radius: 12px !important; - overflow: hidden; - box-shadow: 0px 8px 26px 0px rgba(0, 0, 0, 0.12); - } - - .ant-popover-inner-content { - padding: 24px !important; - } - - .ant-popover-arrow { - display: none !important; - } - } -} diff --git a/projects/web/src/pages/extract/components/extractor-guide/index.tsx b/projects/web/src/pages/extract/components/extractor-guide/index.tsx deleted file mode 100644 index 3be5b3639ccf06c75d45b20b6644941170a24247..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/extractor-guide/index.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { Popover } from "antd"; -import guideToolsSvg from "@/assets/pdf/guideTools.svg"; -import style from "./index.module.scss"; -import { useIntl } from "react-intl"; -import IconFont from "@/components/icon-font"; -import { windowOpen } from "@/utils/windowOpen"; - -interface GuideItem { - type: string; - icon: string; - "zh-CN-title": string; - title: string; - desc: string; - goToText: string; - link: string; -} - -const ExtractorGuide = () => { - const { formatMessage, messages } = useIntl(); - - const EXTRACTOR_GUIDE_ITEM_LIST = (messages?.["extractor.side.guide_list"] || - []) as unknown as GuideItem[]; - - const content = ( -
    -
    - {formatMessage({ - id: "extractor.guide.title", - })} -
    -
    - {EXTRACTOR_GUIDE_ITEM_LIST?.map((i) => { - return ( -
    windowOpen(i.link)} - > - -
    -
    - {i.title} -
    -
    - {i.desc} -
    -
    - {i.goToText} - -
    -
    -
    - ); - })} -
    -
    - ); - return ( - - guideToolsSvg - - ); -}; - -export default ExtractorGuide; diff --git a/projects/web/src/pages/extract/components/extractor-lang/index.tsx b/projects/web/src/pages/extract/components/extractor-lang/index.tsx deleted file mode 100644 index 8fc3ac04ca0554b288e746c628c69e5698186707..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/extractor-lang/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import LangChangeIcon from "@/assets/pdf/lang-change.svg"; -import { useLanguageStore } from "@/store/languageStore"; -import cls from "classnames"; - -interface ExtractorLangProps { - className?: string; -} - -const ExtractorLang: React.FC = ({ className }) => { - const { toggleLanguage } = useLanguageStore(); - const changeLang = () => { - toggleLanguage?.(); - }; - return ( - <> - changeLang()} - src={LangChangeIcon} - alt="LangChangeIcon" - className={cls( - "w-[1.5rem] h-[1.5rem] cursor-pointer object-cover hover:bg-[#0D53DE]/[0.1] rounded cursor-pointer", - className - )} - /> - - ); -}; - -export default ExtractorLang; diff --git a/projects/web/src/pages/extract/components/extractor-queue/index.tsx b/projects/web/src/pages/extract/components/extractor-queue/index.tsx deleted file mode 100644 index cd557c90fb3e80d5e2c9f24b884196d53a52c1c7..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/extractor-queue/index.tsx +++ /dev/null @@ -1,201 +0,0 @@ -import IconFont from "@/components/icon-font"; -import { useIntl } from "react-intl"; -import extractorQueueSvg from "@/assets/pdf/extractor-queue.svg"; -import { useNavigate, useParams } from "react-router-dom"; -import { - EXTRACTOR_TYPE_LIST, - ExtractTaskType, -} from "@/types/extract-task-type"; -import cls from "classnames"; -import { useLatest, useRequest } from "ahooks"; -import { deleteExtractJob, getExtractorHistory } from "@/api/extract"; -import { message, Popconfirm, Tooltip } from "antd"; -import { useEffect } from "react"; -import { ADD_TASK_LIST, UPDATE_TASK_LIST } from "@/constant/event"; -import { findIndex } from "lodash"; -import { TextTooltip } from "@/components/text-tooltip"; - -interface ExtractorQueueProps { - className?: string; -} - -const ExtractorQueue: React.FC = ({ className }) => { - const { formatMessage, locale } = useIntl(); - const navigate = useNavigate(); - - const params = useParams(); - - const { data: taskList, mutate } = useRequest(() => { - return getExtractorHistory({ - pageNo: 1, - pageSize: 100, - }).then((res) => { - return res?.list?.filter((i) => !!i.id && !!i.type) || []; - }); - }); - - let timeout: NodeJS.Timeout | null = null; - - const activeClassName = "!bg-[#0d53de]/[0.05] !text-[#0D53DE]"; - const handleExtractor = (originType: ExtractTaskType, id: string) => { - const type = originType?.split("-")[0]; - const detailType = originType?.split("-")[1]; - - if (type === EXTRACTOR_TYPE_LIST.formula.toLowerCase()) { - navigate(`/OpenSourceTools/Extractor/formula/${id}?type=${detailType}`); - } else if (type === EXTRACTOR_TYPE_LIST.pdf.toLowerCase()) { - navigate(`/OpenSourceTools/Extractor/PDF/${id}`); - } else if (type === EXTRACTOR_TYPE_LIST.table.toLocaleLowerCase()) { - navigate(`/OpenSourceTools/Extractor/table/${id}`); - } - return; - }; - - const cancel = (e?: React.MouseEvent) => { - e?.stopPropagation(); - e?.preventDefault(); - }; - - const confirm = (id: string) => { - const deleteIndex = findIndex(taskList, (i) => i.id === id); - const nextJob = taskList?.[deleteIndex + 1] - ? taskList?.[deleteIndex + 1] - : taskList?.[deleteIndex - 1]; - mutate(taskList?.filter((i) => i.id !== id)); - deleteExtractJob(id).then(() => { - message.success(formatMessage({ id: "extractor.queue.delete.success" })); - }); - if (timeout) { - clearTimeout(timeout); - } - timeout = setTimeout(() => { - if (nextJob?.id) { - handleExtractor(nextJob?.type as any, nextJob?.id); - } else { - navigate("/OpenSourceTools/Extractor"); - } - }, 10); - }; - const taskListRef = useLatest(taskList); - const handleAddList = ({ detail }: CustomEvent) => { - const taskData = detail as any; - mutate( - [ - { - fileName: taskData?.fileName, - id: taskData?.id, - type: taskData?.type, - state: taskData?.state, // 提取状态 - } as any, - ].concat(taskListRef?.current) - ); - }; - - useEffect(() => { - const handleUpdateList = ({ detail }: CustomEvent) => { - const taskData = detail as any; - taskListRef?.current?.forEach((i) => { - if (i.id === taskData?.id) { - i.state = taskData?.state || taskData?.state; - } - }); - - mutate(taskListRef?.current); - }; - document.addEventListener( - UPDATE_TASK_LIST, - handleUpdateList as EventListener - ); - document.addEventListener(ADD_TASK_LIST, handleAddList as EventListener); - return () => { - document.removeEventListener( - UPDATE_TASK_LIST, - handleUpdateList as EventListener - ); - document.removeEventListener( - ADD_TASK_LIST, - handleAddList as EventListener - ); - }; - }, []); - - useEffect(() => { - mutate(taskListRef?.current); - }, [locale]); - - return ( -
    -
    - extractorQueueSvg - {formatMessage({ - id: "extractor.queue", - })} -
    -
    - {taskList?.map((i, index) => { - return ( -
    handleExtractor(i.type as any, i.id)} - > - - - - <> - {i?.state === "failed" && ( - - - - )} - -
    } - onConfirm={(e) => { - e?.stopPropagation(); - e?.preventDefault(); - confirm(i.id); - }} - onCancel={cancel} - okText={formatMessage({ id: "common.confirm" })} - cancelText={formatMessage({ id: "common.cancel" })} - okButtonProps={{ - style: { - backgroundColor: "#F5483B", - }, - }} - > - { - e.stopPropagation(); - e.preventDefault(); - }} - type="icon-shanchu" - className="hidden ml-auto text-[1rem] text-[#121316]/[0.8] hover:text-[#0D53DE] group-hover:block" - /> - - -
    - ); - })} - - - ); -}; - -export default ExtractorQueue; diff --git a/projects/web/src/pages/extract/components/extractor-repo/index.module.scss b/projects/web/src/pages/extract/components/extractor-repo/index.module.scss deleted file mode 100644 index e7b88e63643a46db2a9fa0567694b352fbaa8c69..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/extractor-repo/index.module.scss +++ /dev/null @@ -1,62 +0,0 @@ -.githubBtn { - position: relative; - width: 100%; - cursor: pointer; - height: 2.5rem; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 1.25rem; - overflow: hidden; - border-radius: 8px; - cursor: pointer; - - - filter: blur(0px); - - z-index: 0; - &::before { - width: 100%; - height: 100%; - display: block; - content: ""; - position: absolute; - top: 0; - left: 0; - background: linear-gradient(to bottom, rgba(185,214,246,1) -100%, rgba(244,247,254,) 100%); - z-index: 0; - } - - - & > span { - border-radius: 7px; - display:inline-flex; - width: calc(100% - 2px); - height: calc(100% - 2px); - background: linear-gradient(180deg, #5C93FF1F -160.94%, rgba(255, 255, 255, 1) 80%); - z-index: 1; - filter: blur(0px); - justify-content: center; - align-items: center; - font-size: 16px; - &:hover { - background: linear-gradient(180deg, #5C93FF1F -60.94%, rgba(255, 255, 255, 1) 80%); - filter: blur(0px); - } - span:nth-child(3){ - color: var(--80-text-4, rgba(18, 19, 22, 0.80)); - -webkit-background-clip: text; - background-clip: text; - } - } -} - -.githubText { - /* 正文/加粗text-1-semibold */ - font-family: "PingFang SC"; - font-size: 14px; - font-style: normal; - font-weight: 600; - line-height: 21px; /* 150% */ - color: #121316; -} diff --git a/projects/web/src/pages/extract/components/extractor-repo/index.tsx b/projects/web/src/pages/extract/components/extractor-repo/index.tsx deleted file mode 100644 index 4c54610a1ca28110e7d9c8d003186ae1fe178449..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/extractor-repo/index.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import githubSvg from "@/assets/pdf/github.svg"; -import { windowOpen } from "@/utils/windowOpen"; -import styles from "./index.module.scss"; -import cls from "classnames"; - -const ExtractorRepo = () => { - return ( -
    - windowOpen("https://github.com/opendatalab/MinerU", "_blank") - } - > - - - 🎉 - -
    - ); -}; - -export default ExtractorRepo; diff --git a/projects/web/src/pages/extract/components/iframe-loading/index.tsx b/projects/web/src/pages/extract/components/iframe-loading/index.tsx deleted file mode 100644 index 91d90bd451679c9af9a4e6b445afa7e97cc6051c..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/iframe-loading/index.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import LoadingAnimation from "@/components/loading-animation"; -import { ExclamationCircleFilled } from "@ant-design/icons"; -import cls from "classnames"; - -export const IframeLoading = ({ - filename, - type, - text, - errorElement, - classNameTitle = "", - showHeader, -}: { - filename?: string; - type: "loading" | "error"; - text?: string; - errorElement?: React.ReactElement; - classNameTitle?: string; - showHeader?: boolean; -}) => { - return ( -
    - {showHeader && ( -
    - {filename} -
    - )} - -
    - {type === "error" ? ( - errorElement ? ( - errorElement - ) : ( - <> - - 上传失败,请 - - 重新上传 - - - ) - ) : ( - <> - - {text || "PDF 上传中,请稍等..."} - - )} -
    -
    - ); -}; diff --git a/projects/web/src/pages/extract/components/image-layer-viwer/index.tsx b/projects/web/src/pages/extract/components/image-layer-viwer/index.tsx deleted file mode 100644 index 66ba37e98f2663f420c33293b976eb010e32064c..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/image-layer-viwer/index.tsx +++ /dev/null @@ -1,378 +0,0 @@ -import React, { - useEffect, - useRef, - useState, - useMemo, - forwardRef, - useImperativeHandle, - useCallback, -} from "react"; -import cls from "classnames"; -import { isObjEqual } from "@/utils/render"; -import { useSize } from "ahooks"; - -interface IImageLayersViewerProps { - imageUrl: string; - imageWidth: number; - imageHeight: number; - layout: Array<{ - category_id: number; - poly: number[]; - score: number; - latex?: string; - }>; - layerVisible?: boolean; - disableZoom?: boolean; - className?: string; - onChange?: (data: { scale: number }) => void; -} - -export interface ImageLayerViewerRef { - containerRef: HTMLDivElement | null; - zoomIn: () => void; - zoomOut: () => void; - scale: number; - updateScaleAndPosition: () => void; -} - -const ImageLayerViewer = forwardRef< - ImageLayerViewerRef, - IImageLayersViewerProps ->( - ( - { - imageUrl, - imageHeight, - imageWidth, - onChange, - layout, - disableZoom, - className = "", - layerVisible = true, - }, - ref - ) => { - const containerRef = useRef(null); - const imageCanvasRef = useRef(null); - const overlayCanvasRef = useRef(null); - const rafRef = useRef(null); - const containerSize = useSize(containerRef); - - const [scale, setScale] = useState(1); - const [position, setPosition] = useState({ x: 0, y: 0 }); - const [padding, setPadding] = useState({ left: 0, top: 0 }); - - const minZoom = 0.1; - const maxZoom = 3; - const zoomSensitivity = 0.001; - const zoomStep = 0.1; - - const dpr = useMemo(() => window.devicePixelRatio || 1, []); - - const image = useMemo(() => { - const img = new Image(); - img.src = imageUrl; - return img; - }, [imageUrl]); - - const calculateInitialScaleAndPosition = useCallback(() => { - if (!containerRef.current) - return { initialScale: 1, initialPosition: { x: 0, y: 0 } }; - const containerWidth = containerRef.current.clientWidth; - const containerHeight = containerRef.current.clientHeight; - - const scaleX = containerWidth / imageWidth; - const scaleY = containerHeight / imageHeight; - const initialScale = Math.min(scaleX, scaleY, 1); // Ensure it doesn't scale up initially - - const scaledWidth = imageWidth * initialScale; - const scaledHeight = imageHeight * initialScale; - - const initialPosition = { - x: (containerWidth - scaledWidth) / 2, - y: (containerHeight - scaledHeight) / 2, - }; - - return { initialScale, initialPosition }; - }, [imageWidth, imageHeight]); - - const updateScaleAndPosition = useCallback(() => { - const { initialScale, initialPosition } = - calculateInitialScaleAndPosition(); - setScale(initialScale); - setPosition(initialPosition); - setPadding({ left: 0, top: 0 }); - }, [calculateInitialScaleAndPosition]); - - useEffect(() => { - updateScaleAndPosition(); - }, [imageWidth, imageHeight]); - - const drawImage = useCallback(() => { - const ctx = imageCanvasRef.current?.getContext("2d"); - if (!ctx || !image.complete) return; - - const scaledWidth = imageWidth * scale; - const scaledHeight = imageHeight * scale; - - ctx.canvas.width = scaledWidth * dpr; - ctx.canvas.height = scaledHeight * dpr; - ctx.canvas.style.width = `${scaledWidth}px`; - ctx.canvas.style.height = `${scaledHeight}px`; - - ctx.scale(dpr, dpr); - - ctx.clearRect(0, 0, scaledWidth, scaledHeight); - ctx.drawImage(image, 0, 0, scaledWidth, scaledHeight); - }, [image, imageWidth, imageHeight, scale, dpr]); - - const drawLayout = useCallback(() => { - const ctx = overlayCanvasRef.current?.getContext("2d"); - if (!ctx) return; - - const scaledWidth = imageWidth * scale; - const scaledHeight = imageHeight * scale; - - ctx.canvas.width = scaledWidth * dpr; - ctx.canvas.height = scaledHeight * dpr; - ctx.canvas.style.width = `${scaledWidth}px`; - ctx.canvas.style.height = `${scaledHeight}px`; - - ctx.scale(dpr, dpr); - - ctx.clearRect(0, 0, scaledWidth, scaledHeight); - - layout?.forEach((item) => { - const [x1, y1, x2, y2, x3, y3, x4, y4] = item.poly.map( - (coord) => coord * scale - ); - - switch (item.category_id) { - case 9: - ctx.fillStyle = "rgba(230, 113, 230, 0.4)"; - ctx.strokeStyle = "rgba(230, 113, 230, 1)"; - break; - case 8: - ctx.fillStyle = "rgba(240, 240, 124, 0.4)"; - ctx.strokeStyle = "rgba(240, 240, 124, 1)"; - break; - case 13: - ctx.fillStyle = "rgba(150, 232, 172, 0.4)"; - ctx.strokeStyle = "rgba(150, 232, 172, 1)"; - break; - case 14: - ctx.fillStyle = "rgba(230, 122, 171, 0.4)"; - ctx.strokeStyle = "rgba(230, 122, 171, 1)"; - break; - default: - ctx.fillStyle = "transparent"; - ctx.strokeStyle = "transparent"; - } - - ctx.beginPath(); - ctx.moveTo(x1, y1); - ctx.lineTo(x2, y2); - ctx.lineTo(x3, y3); - ctx.lineTo(x4, y4); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - }); - }, [layout, scale, dpr]); - - const updateScale = useCallback( - (newScale: number, clientX: number, clientY: number) => { - if (containerRef.current) { - const rect = containerRef.current.getBoundingClientRect(); - const containerWidth = rect.width; - const containerHeight = rect.height; - const x = clientX - rect.left; - const y = clientY - rect.top; - - const prevScaledWidth = imageWidth * scale; - const prevScaledHeight = imageHeight * scale; - const newScaledWidth = imageWidth * newScale; - const newScaledHeight = imageHeight * newScale; - - let newPosition = { - x: - position.x - - ((x - position.x) * (newScaledWidth - prevScaledWidth)) / - prevScaledWidth, - y: - position.y - - ((y - position.y) * (newScaledHeight - prevScaledHeight)) / - prevScaledHeight, - }; - - // Center the image if it's smaller than the container - if (newScaledWidth < containerWidth) { - newPosition.x = (containerWidth - newScaledWidth) / 2; - } - if (newScaledHeight < containerHeight) { - newPosition.y = (containerHeight - newScaledHeight) / 2; - } - - setScale(newScale); - setPosition(newPosition); - - // Calculate new padding - const newPadding = { - left: Math.max(0, -newPosition.x), - top: Math.max(0, -newPosition.y), - }; - setPadding(newPadding); - } - }, - [scale, position, imageWidth, imageHeight] - ); - - const handleZoom = useCallback( - (delta: number, clientX: number, clientY: number) => { - const newScale = scale * Math.exp(-delta * zoomSensitivity); - const boundedNewScale = Math.max(minZoom, Math.min(newScale, maxZoom)); - - if (rafRef.current !== null) { - cancelAnimationFrame(rafRef.current); - } - - rafRef.current = requestAnimationFrame(() => { - updateScale(boundedNewScale, clientX, clientY); - }); - }, - [scale, updateScale] - ); - - const handleCenterZoom = useCallback( - (zoomIn: boolean) => { - const newScale = zoomIn - ? scale * (1 + zoomStep) - : scale / (1 + zoomStep); - const boundedNewScale = Math.max(minZoom, Math.min(newScale, maxZoom)); - - if (containerRef.current) { - const rect = containerRef.current.getBoundingClientRect(); - const centerX = rect.width / 2; - const centerY = rect.height / 2; - - updateScale(boundedNewScale, centerX, centerY); - } - }, - [scale, updateScale] - ); - - const zoomIn = useCallback(() => { - handleCenterZoom(true); - }, [handleCenterZoom]); - - const zoomOut = useCallback(() => { - handleCenterZoom(false); - }, [handleCenterZoom]); - - useImperativeHandle( - ref, - () => ({ - containerRef: containerRef.current, - zoomIn, - zoomOut, - scale, - updateScaleAndPosition, - }), - [zoomIn, zoomOut, scale] - ); - - useEffect(() => { - const container = containerRef.current; - if (!container) return; - - const handleWheel = (e: WheelEvent) => { - if (e.ctrlKey || e.metaKey) { - e.preventDefault(); - handleZoom(e.deltaY * 4.8, e.clientX, e.clientY); - } - }; - - container.addEventListener("wheel", handleWheel, { passive: false }); - - return () => { - container.removeEventListener("wheel", handleWheel); - }; - }, [handleZoom]); - - useEffect(() => { - if (containerRef?.current) { - containerRef.current?.scrollTo({ - left: padding.left, - top: padding.top, - }); - } - }, [padding]); - - useEffect(() => { - const draw = () => { - drawImage(); - drawLayout(); - }; - - if (image.complete) { - draw(); - } else { - image.onload = draw; - } - }, [image, drawImage, drawLayout]); - - useEffect(() => { - if (overlayCanvasRef.current) { - overlayCanvasRef.current.style.opacity = layerVisible ? "1" : "0"; - } - }, [layerVisible]); - - useEffect(() => { - onChange?.({ scale }); - }, [scale]); - - return ( -
    -
    -
    - - -
    -
    -
    - ); - } -); - -export default React.memo(ImageLayerViewer, isObjEqual); diff --git a/projects/web/src/pages/extract/components/latex-renderer/index.module.scss b/projects/web/src/pages/extract/components/latex-renderer/index.module.scss deleted file mode 100644 index 9231f6c674932d9be925fd0f47634f4332801171..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/latex-renderer/index.module.scss +++ /dev/null @@ -1,15 +0,0 @@ -// @import '../../../../global.scss'; - -.customStyle { - padding: 2rem; - padding-top: 0rem; - & > div { - max-width: 100%; - max-height: 100%; - // @include scrollBar(red); - } - .katex-display { - margin-top: 0px !important; - // @include scrollBar(red); - } -} diff --git a/projects/web/src/pages/extract/components/latex-renderer/index.tsx b/projects/web/src/pages/extract/components/latex-renderer/index.tsx deleted file mode 100644 index f1157f24726dd6d3632e98bfb3b10122bcb6b6f4..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/latex-renderer/index.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import 'katex/dist/katex.min.css'; -import { BlockMath } from 'react-katex'; -import style from './index.module.scss'; -import classNames from 'classnames'; - -interface LatexRendererProps { - formula: string; - className?: string; - 'aria-label'?: string; - title?: string; -} - -function LatexRenderer({ formula, className = '', 'aria-label': ariaLabel, title }: LatexRendererProps) { - try { - return ( -
    - -
    - ); - } catch (error) { - console.error('Error rendering Latex:', error); - return
    Unable to render Latex formula.
    ; - } -} - -export default LatexRenderer; diff --git a/projects/web/src/pages/extract/components/loading-icon/index.module.scss b/projects/web/src/pages/extract/components/loading-icon/index.module.scss deleted file mode 100644 index 46c15f056e584b75da7e2edd79131c426dee1edb..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/loading-icon/index.module.scss +++ /dev/null @@ -1,93 +0,0 @@ - -$circle-width: 16px; - -.container { - position: relative; - width:4 * $circle-width; - height: 20px; - display: flex; - align-items: center; - justify-content: center; -} -.dot-pulse { - position: relative; - left: -9999px; - width: $circle-width; - height: $circle-width; - border-radius: 50%; - background-color: var(--color); - color: var(--color); - box-shadow: 9999px 0 0 -3px; - animation: dot-pulse 1.5s infinite linear; - animation-delay: 0.25s; -} - -.dot-pulse::before, -.dot-pulse::after { - content: ''; - display: inline-block; - position: absolute; - top: 0; - width: $circle-width; - height: $circle-width; - border-radius: 50%; - background-color: var(--color); - color: var(--color); -} - -.dot-pulse::before { - box-shadow: 9974px 0 0 -3px; - animation: dot-pulse-before 1.5s infinite linear; - animation-delay: 0s; -} - -.dot-pulse::after { - box-shadow: 10024px 0 0 -3px; - animation: dot-pulse-after 1.5s infinite linear; - animation-delay: 0.5s; -} - -@keyframes dot-pulse-before { - 0% { - box-shadow: 9974px 0 0 -3px; - } - - 30% { - box-shadow: 9974px 0 0 2px; - } - - 60%, - 100% { - box-shadow: 9974px 0 0 -3px; - } -} - -@keyframes dot-pulse { - 0% { - box-shadow: 9999px 0 0 -3px; - } - - 30% { - box-shadow: 9999px 0 0 3px; - } - - 60%, - 100% { - box-shadow: 9999px 0 0 -3px; - } -} - -@keyframes dot-pulse-after { - 0% { - box-shadow: 10024px 0 0 -3px; - } - - 30% { - box-shadow: 10024px 0 0 2px; - } - - 60%, - 100% { - box-shadow: 10024px 0 0 -3px; - } -} diff --git a/projects/web/src/pages/extract/components/loading-icon/index.tsx b/projects/web/src/pages/extract/components/loading-icon/index.tsx deleted file mode 100644 index 1093eea588277892744b9f13e6ec3daeda1ae14d..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/loading-icon/index.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import classNames from "classnames"; -import style from "./index.module.scss"; - -const LoadingIcon = ({ - color, - className, -}: { - color: string; - className?: string; -}) => { - return ( -
    -
    -
    - ); -}; - -export default LoadingIcon; diff --git a/projects/web/src/pages/extract/components/md-viewer/index.module.scss b/projects/web/src/pages/extract/components/md-viewer/index.module.scss deleted file mode 100644 index 130a1f7c862a27ffca29adbeda50407e02171a0f..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/md-viewer/index.module.scss +++ /dev/null @@ -1,1141 +0,0 @@ -/*light*/ - -// 自定义滚动跳 -.scrollBar { - // 火狐 - scrollbar-color: #EBECF0 transparent; - scrollbar-width: thin; - - // 定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸 - &::-webkit-scrollbar { - width: 4px; - height: 6px; - background-color: transparent; - } - - // 定义滚动条轨道 内阴影+圆角 - &::-webkit-scrollbar-track { - background-color: #fff; - border-radius: 10px; - box-shadow: transparent; - } - - // 定义滑块 内阴影+圆角 - &::-webkit-scrollbar-thumb { - background: #EBECF0; - border-radius: 10px; - box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.6); - } -} - -.mdViewerWrap { - font-size: 10px; -} - -.mdViewerWrap { - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; - margin: 0; - color: #1f2328; - background-color: #ffffff; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", - Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; - font-size: 16px; - line-height: 1.5; - word-wrap: break-word; - scroll-behavior: auto; -} - -.mdViewerWrap .octicon { - display: inline-block; - fill: currentColor; - vertical-align: text-bottom; -} - -.mdViewerWrap h1:hover .anchor .octicon-link:before, -.mdViewerWrap h2:hover .anchor .octicon-link:before, -.mdViewerWrap h3:hover .anchor .octicon-link:before, -.mdViewerWrap h4:hover .anchor .octicon-link:before, -.mdViewerWrap h5:hover .anchor .octicon-link:before, -.mdViewerWrap h6:hover .anchor .octicon-link:before { - width: 16px; - height: 16px; - content: " "; - display: inline-block; - background-color: currentColor; - -webkit-mask-image: url("data:image/svg+xml,"); - mask-image: url("data:image/svg+xml,"); -} - -.mdViewerWrap details, -.mdViewerWrap figcaption, -.mdViewerWrap figure { - display: block; -} - -.mdViewerWrap summary { - display: list-item; -} - -.mdViewerWrap [hidden] { - display: none !important; -} - -.mdViewerWrap a { - background-color: transparent; - color: #0969da; - text-decoration: none; -} - -.mdViewerWrap abbr[title] { - border-bottom: none; - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; -} - -.mdViewerWrap b, -.mdViewerWrap strong { - font-weight: 600; -} - -.mdViewerWrap dfn { - font-style: italic; -} - -.mdViewerWrap h1 { - margin: 0.67em 0; - font-weight: 600; - padding-bottom: 0.3em; - font-size: 2em; - border-bottom: 1px solid #d0d7deb3; -} - -.mdViewerWrap mark { - background-color: #fff8c5; - color: #1f2328; -} - -.mdViewerWrap small { - font-size: 90%; -} - -.mdViewerWrap sub, -.mdViewerWrap sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -.mdViewerWrap sub { - bottom: -0.25em; -} - -.mdViewerWrap sup { - top: -0.5em; -} - -.mdViewerWrap img { - border-style: none; - max-width: 100%; - box-sizing: content-box; - background-color: #ffffff; -} - -.mdViewerWrap code, -.mdViewerWrap kbd, -.mdViewerWrap pre, -.mdViewerWrap samp { - font-family: monospace; - font-size: 1em; -} - -.mdViewerWrap figure { - margin: 1em 40px; -} - -.mdViewerWrap hr { - box-sizing: content-box; - overflow: hidden; - background: transparent; - border-bottom: 1px solid #d0d7deb3; - height: 0.25em; - padding: 0; - margin: 24px 0; - background-color: #d0d7de; - border: 0; -} - -.mdViewerWrap input { - font: inherit; - margin: 0; - overflow: visible; - font-family: inherit; - font-size: inherit; - line-height: inherit; -} - -.mdViewerWrap [type="button"], -.mdViewerWrap [type="reset"], -.mdViewerWrap [type="submit"] { - -webkit-appearance: button; - appearance: button; -} - -.mdViewerWrap [type="checkbox"], -.mdViewerWrap [type="radio"] { - box-sizing: border-box; - padding: 0; -} - -.mdViewerWrap [type="number"]::-webkit-inner-spin-button, -.mdViewerWrap [type="number"]::-webkit-outer-spin-button { - height: auto; -} - -.mdViewerWrap [type="search"]::-webkit-search-cancel-button, -.mdViewerWrap [type="search"]::-webkit-search-decoration { - -webkit-appearance: none; - appearance: none; -} - -.mdViewerWrap ::-webkit-input-placeholder { - color: inherit; - opacity: 0.54; -} - -.mdViewerWrap ::-webkit-file-upload-button { - -webkit-appearance: button; - appearance: button; - font: inherit; -} - -.mdViewerWrap a:hover { - text-decoration: underline; -} - -.mdViewerWrap ::placeholder { - color: #636c76; - opacity: 1; -} - -.mdViewerWrap hr::before { - display: table; - content: ""; -} - -.mdViewerWrap hr::after { - display: table; - clear: both; - content: ""; -} - -.mdViewerWrap table { - border-spacing: 0; - border-collapse: collapse; - display: block; - width: max-content; - max-width: 100%; - overflow: auto; -} - -.mdViewerWrap td, -.mdViewerWrap th { - padding: 0; -} - -.mdViewerWrap details summary { - cursor: pointer; -} - -.mdViewerWrap details:not([open]) > *:not(summary) { - display: none; -} - -.mdViewerWrap a:focus, -.mdViewerWrap [role="button"]:focus, -.mdViewerWrap input[type="radio"]:focus, -.mdViewerWrap input[type="checkbox"]:focus { - outline: 2px solid #0969da; - outline-offset: -2px; - box-shadow: none; -} - -.mdViewerWrap a:focus:not(:focus-visible), -.mdViewerWrap [role="button"]:focus:not(:focus-visible), -.mdViewerWrap input[type="radio"]:focus:not(:focus-visible), -.mdViewerWrap input[type="checkbox"]:focus:not(:focus-visible) { - outline: solid 1px transparent; -} - -.mdViewerWrap a:focus-visible, -.mdViewerWrap [role="button"]:focus-visible, -.mdViewerWrap input[type="radio"]:focus-visible, -.mdViewerWrap input[type="checkbox"]:focus-visible { - outline: 2px solid #0969da; - outline-offset: -2px; - box-shadow: none; -} - -.mdViewerWrap a:not([class]):focus, -.mdViewerWrap a:not([class]):focus-visible, -.mdViewerWrap input[type="radio"]:focus, -.mdViewerWrap input[type="radio"]:focus-visible, -.mdViewerWrap input[type="checkbox"]:focus, -.mdViewerWrap input[type="checkbox"]:focus-visible { - outline-offset: 0; -} - -.mdViewerWrap kbd { - display: inline-block; - padding: 3px 5px; - font: 11px ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, - Liberation Mono, monospace; - line-height: 10px; - color: #1f2328; - vertical-align: middle; - background-color: #f6f8fa; - border: solid 1px #afb8c133; - border-bottom-color: #afb8c133; - border-radius: 6px; - box-shadow: inset 0 -1px 0 #afb8c133; -} - -.mdViewerWrap h1, -.mdViewerWrap h2, -.mdViewerWrap h3, -.mdViewerWrap h4, -.mdViewerWrap h5, -.mdViewerWrap h6 { - margin-top: 24px; - margin-bottom: 16px; - font-weight: 600; - line-height: 1.25; -} - -.mdViewerWrap h2 { - font-weight: 600; - padding-bottom: 0.3em; - font-size: 1.5em; - border-bottom: 1px solid #d0d7deb3; -} - -.mdViewerWrap h3 { - font-weight: 600; - font-size: 1.25em; -} - -.mdViewerWrap h4 { - font-weight: 600; - font-size: 1em; -} - -.mdViewerWrap h5 { - font-weight: 600; - font-size: 0.875em; -} - -.mdViewerWrap h6 { - font-weight: 600; - font-size: 0.85em; - color: #636c76; -} - -.mdViewerWrap p { - margin-top: 0; - margin-bottom: 10px; - font-size: 1.25em; -} - -.mdViewerWrap blockquote { - margin: 0; - padding: 0 1em; - color: #636c76; - border-left: 0.25em solid #d0d7de; -} - -.mdViewerWrap ul, -.mdViewerWrap ol { - margin-top: 0; - margin-bottom: 0; - padding-left: 2em; -} - -.mdViewerWrap ol ol, -.mdViewerWrap ul ol { - list-style-type: lower-roman; -} - -.mdViewerWrap ul ul ol, -.mdViewerWrap ul ol ol, -.mdViewerWrap ol ul ol, -.mdViewerWrap ol ol ol { - list-style-type: lower-alpha; -} - -.mdViewerWrap dd { - margin-left: 0; -} - -.mdViewerWrap tt, -.mdViewerWrap code, -.mdViewerWrap samp { - font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, - Liberation Mono, monospace; - font-size: 12px; -} - -.mdViewerWrap pre { - margin-top: 0; - margin-bottom: 0; - font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, - Liberation Mono, monospace; - font-size: 12px; - word-wrap: normal; -} - -.mdViewerWrap .octicon { - display: inline-block; - overflow: visible !important; - vertical-align: text-bottom; - fill: currentColor; -} - -.mdViewerWrap input::-webkit-outer-spin-button, -.mdViewerWrap input::-webkit-inner-spin-button { - margin: 0; - -webkit-appearance: none; - appearance: none; -} - -.mdViewerWrap .mr-2 { - margin-right: 0.5rem !important; -} - -.mdViewerWrap::before { - display: table; - content: ""; -} - -.mdViewerWrap::after { - display: table; - clear: both; - content: ""; -} - -.mdViewerWrap > *:first-child { - margin-top: 0 !important; -} - -.mdViewerWrap > *:last-child { - margin-bottom: 0 !important; -} - -.mdViewerWrap a:not([href]) { - color: inherit; - text-decoration: none; -} - -.mdViewerWrap .absent { - color: #d1242f; -} - -.mdViewerWrap .anchor { - float: left; - padding-right: 4px; - margin-left: -20px; - line-height: 1; -} - -.mdViewerWrap .anchor:focus { - outline: none; -} - -.mdViewerWrap p, -.mdViewerWrap blockquote, -.mdViewerWrap ul, -.mdViewerWrap ol, -.mdViewerWrap dl, -.mdViewerWrap table, -.mdViewerWrap pre, -.mdViewerWrap details { - margin-top: 0; - margin-bottom: 16px; -} - -.mdViewerWrap blockquote > :first-child { - margin-top: 0; -} - -.mdViewerWrap blockquote > :last-child { - margin-bottom: 0; -} - -.mdViewerWrap h1 .octicon-link, -.mdViewerWrap h2 .octicon-link, -.mdViewerWrap h3 .octicon-link, -.mdViewerWrap h4 .octicon-link, -.mdViewerWrap h5 .octicon-link, -.mdViewerWrap h6 .octicon-link { - color: #1f2328; - vertical-align: middle; - visibility: hidden; -} - -.mdViewerWrap h1:hover .anchor, -.mdViewerWrap h2:hover .anchor, -.mdViewerWrap h3:hover .anchor, -.mdViewerWrap h4:hover .anchor, -.mdViewerWrap h5:hover .anchor, -.mdViewerWrap h6:hover .anchor { - text-decoration: none; -} - -.mdViewerWrap h1:hover .anchor .octicon-link, -.mdViewerWrap h2:hover .anchor .octicon-link, -.mdViewerWrap h3:hover .anchor .octicon-link, -.mdViewerWrap h4:hover .anchor .octicon-link, -.mdViewerWrap h5:hover .anchor .octicon-link, -.mdViewerWrap h6:hover .anchor .octicon-link { - visibility: visible; -} - -.mdViewerWrap h1 tt, -.mdViewerWrap h1 code, -.mdViewerWrap h2 tt, -.mdViewerWrap h2 code, -.mdViewerWrap h3 tt, -.mdViewerWrap h3 code, -.mdViewerWrap h4 tt, -.mdViewerWrap h4 code, -.mdViewerWrap h5 tt, -.mdViewerWrap h5 code, -.mdViewerWrap h6 tt, -.mdViewerWrap h6 code { - padding: 0 0.2em; - font-size: inherit; -} - -.mdViewerWrap summary h1, -.mdViewerWrap summary h2, -.mdViewerWrap summary h3, -.mdViewerWrap summary h4, -.mdViewerWrap summary h5, -.mdViewerWrap summary h6 { - display: inline-block; -} - -.mdViewerWrap summary h1 .anchor, -.mdViewerWrap summary h2 .anchor, -.mdViewerWrap summary h3 .anchor, -.mdViewerWrap summary h4 .anchor, -.mdViewerWrap summary h5 .anchor, -.mdViewerWrap summary h6 .anchor { - margin-left: -40px; -} - -.mdViewerWrap summary h1, -.mdViewerWrap summary h2 { - padding-bottom: 0; - border-bottom: 0; -} - -.mdViewerWrap ul.no-list, -.mdViewerWrap ol.no-list { - padding: 0; - list-style-type: none; -} - -.mdViewerWrap ol[type="a s"] { - list-style-type: lower-alpha; -} - -.mdViewerWrap ol[type="A s"] { - list-style-type: upper-alpha; -} - -.mdViewerWrap ol[type="i s"] { - list-style-type: lower-roman; -} - -.mdViewerWrap ol[type="I s"] { - list-style-type: upper-roman; -} - -.mdViewerWrap ol[type="1"] { - list-style-type: decimal; -} - -.mdViewerWrap div > ol:not([type]) { - list-style-type: decimal; -} - -.mdViewerWrap ul ul, -.mdViewerWrap ul ol, -.mdViewerWrap ol ol, -.mdViewerWrap ol ul { - margin-top: 0; - margin-bottom: 0; -} - -.mdViewerWrap li > p { - margin-top: 16px; -} - -.mdViewerWrap li + li { - margin-top: 0.25em; -} - -.mdViewerWrap dl { - padding: 0; -} - -.mdViewerWrap dl dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: 600; -} - -.mdViewerWrap dl dd { - padding: 0 16px; - margin-bottom: 16px; -} - -.mdViewerWrap table th { - font-weight: 600; -} - -.mdViewerWrap table th, -.mdViewerWrap table td { - padding: 6px 13px; - border: 1px solid #d0d7de; -} - -.mdViewerWrap table td > :last-child { - margin-bottom: 0; -} - -.mdViewerWrap table tr { - background-color: #ffffff; - border-top: 1px solid #d0d7deb3; -} - -.mdViewerWrap table tr:nth-child(2n) { - background-color: #f6f8fa; -} - -.mdViewerWrap table img { - background-color: transparent; -} - -.mdViewerWrap img[align="right"] { - padding-left: 20px; -} - -.mdViewerWrap img[align="left"] { - padding-right: 20px; -} - -.mdViewerWrap .emoji { - max-width: none; - vertical-align: text-top; - background-color: transparent; -} - -.mdViewerWrap span.frame { - display: block; - overflow: hidden; -} - -.mdViewerWrap span.frame > span { - display: block; - float: left; - width: auto; - padding: 7px; - margin: 13px 0 0; - overflow: hidden; - border: 1px solid #d0d7de; -} - -.mdViewerWrap span.frame span img { - display: block; - float: left; -} - -.mdViewerWrap span.frame span span { - display: block; - padding: 5px 0 0; - clear: both; - color: #1f2328; -} - -.mdViewerWrap span.align-center { - display: block; - overflow: hidden; - clear: both; -} - -.mdViewerWrap span.align-center > span { - display: block; - margin: 13px auto 0; - overflow: hidden; - text-align: center; -} - -.mdViewerWrap span.align-center span img { - margin: 0 auto; - text-align: center; -} - -.mdViewerWrap span.align-right { - display: block; - overflow: hidden; - clear: both; -} - -.mdViewerWrap span.align-right > span { - display: block; - margin: 13px 0 0; - overflow: hidden; - text-align: right; -} - -.mdViewerWrap span.align-right span img { - margin: 0; - text-align: right; -} - -.mdViewerWrap span.float-left { - display: block; - float: left; - margin-right: 13px; - overflow: hidden; -} - -.mdViewerWrap span.float-left span { - margin: 13px 0 0; -} - -.mdViewerWrap span.float-right { - display: block; - float: right; - margin-left: 13px; - overflow: hidden; -} - -.mdViewerWrap span.float-right > span { - display: block; - margin: 13px auto 0; - overflow: hidden; - text-align: right; -} - -.mdViewerWrap code, -.mdViewerWrap tt { - padding: 0.2em 0.4em; - margin: 0; - font-size: 85%; - white-space: break-spaces; - background-color: #afb8c133; - border-radius: 6px; -} - -.mdViewerWrap code br, -.mdViewerWrap tt br { - display: none; -} - -.mdViewerWrap del code { - text-decoration: inherit; -} - -.mdViewerWrap samp { - font-size: 85%; -} - -.mdViewerWrap pre code { - font-size: 100%; -} - -.mdViewerWrap pre > code { - padding: 0; - margin: 0; - word-break: normal; - white-space: pre; - background: transparent; - border: 0; -} - -.mdViewerWrap .highlight { - margin-bottom: 16px; -} - -.mdViewerWrap .highlight pre { - margin-bottom: 0; - word-break: normal; -} - -.mdViewerWrap .highlight pre, -.mdViewerWrap pre { - padding: 16px; - overflow: auto; - font-size: 85%; - line-height: 1.45; - color: #1f2328; - background-color: #f6f8fa; - border-radius: 6px; -} - -.mdViewerWrap pre code, -.mdViewerWrap pre tt { - display: inline; - max-width: auto; - padding: 0; - margin: 0; - overflow: visible; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0; -} - -.mdViewerWrap .csv-data td, -.mdViewerWrap .csv-data th { - padding: 5px; - overflow: hidden; - font-size: 12px; - line-height: 1; - text-align: left; - white-space: nowrap; -} - -.mdViewerWrap .csv-data .blob-num { - padding: 10px 8px 9px; - text-align: right; - background: #ffffff; - border: 0; -} - -.mdViewerWrap .csv-data tr { - border-top: 0; -} - -.mdViewerWrap .csv-data th { - font-weight: 600; - background: #f6f8fa; - border-top: 0; -} - -.mdViewerWrap [data-footnote-ref]::before { - content: "["; -} - -.mdViewerWrap [data-footnote-ref]::after { - content: "]"; -} - -.mdViewerWrap .footnotes { - font-size: 12px; - color: #636c76; - border-top: 1px solid #d0d7de; -} - -.mdViewerWrap .footnotes ol { - padding-left: 16px; -} - -.mdViewerWrap .footnotes ol ul { - display: inline-block; - padding-left: 16px; - margin-top: 16px; -} - -.mdViewerWrap .footnotes li { - position: relative; -} - -.mdViewerWrap .footnotes li:target::before { - position: absolute; - top: -8px; - right: -8px; - bottom: -8px; - left: -24px; - pointer-events: none; - content: ""; - border: 2px solid #0969da; - border-radius: 6px; -} - -.mdViewerWrap .footnotes li:target { - color: #1f2328; -} - -.mdViewerWrap .footnotes .data-footnote-backref g-emoji { - font-family: monospace; -} - -.mdViewerWrap .pl-c { - color: #57606a; -} - -.mdViewerWrap .pl-c1, -.mdViewerWrap .pl-s .pl-v { - color: #0550ae; -} - -.mdViewerWrap .pl-e, -.mdViewerWrap .pl-en { - color: #6639ba; -} - -.mdViewerWrap .pl-smi, -.mdViewerWrap .pl-s .pl-s1 { - color: #24292f; -} - -.mdViewerWrap .pl-ent { - color: #0550ae; -} - -.mdViewerWrap .pl-k { - color: #cf222e; -} - -.mdViewerWrap .pl-s, -.mdViewerWrap .pl-pds, -.mdViewerWrap .pl-s .pl-pse .pl-s1, -.mdViewerWrap .pl-sr, -.mdViewerWrap .pl-sr .pl-cce, -.mdViewerWrap .pl-sr .pl-sre, -.mdViewerWrap .pl-sr .pl-sra { - color: #0a3069; -} - -.mdViewerWrap .pl-v, -.mdViewerWrap .pl-smw { - color: #953800; -} - -.mdViewerWrap .pl-bu { - color: #82071e; -} - -.mdViewerWrap .pl-ii { - color: #f6f8fa; - background-color: #82071e; -} - -.mdViewerWrap .pl-c2 { - color: #f6f8fa; - background-color: #cf222e; -} - -.mdViewerWrap .pl-sr .pl-cce { - font-weight: bold; - color: #116329; -} - -.mdViewerWrap .pl-ml { - color: #3b2300; -} - -.mdViewerWrap .pl-mh, -.mdViewerWrap .pl-mh .pl-en, -.mdViewerWrap .pl-ms { - font-weight: bold; - color: #0550ae; -} - -.mdViewerWrap .pl-mi { - font-style: italic; - color: #24292f; -} - -.mdViewerWrap .pl-mb { - font-weight: bold; - color: #24292f; -} - -.mdViewerWrap .pl-md { - color: #82071e; - background-color: #ffebe9; -} - -.mdViewerWrap .pl-mi1 { - color: #116329; - background-color: #dafbe1; -} - -.mdViewerWrap .pl-mc { - color: #953800; - background-color: #ffd8b5; -} - -.mdViewerWrap .pl-mi2 { - color: #eaeef2; - background-color: #0550ae; -} - -.mdViewerWrap .pl-mdr { - font-weight: bold; - color: #8250df; -} - -.mdViewerWrap .pl-ba { - color: #57606a; -} - -.mdViewerWrap .pl-sg { - color: #8c959f; -} - -.mdViewerWrap .pl-corl { - text-decoration: underline; - color: #0a3069; -} - -.mdViewerWrap [role="button"]:focus:not(:focus-visible), -.mdViewerWrap [role="tabpanel"][tabindex="0"]:focus:not(:focus-visible), -.mdViewerWrap button:focus:not(:focus-visible), -.mdViewerWrap summary:focus:not(:focus-visible), -.mdViewerWrap a:focus:not(:focus-visible) { - outline: none; - box-shadow: none; -} - -.mdViewerWrap [tabindex="0"]:focus:not(:focus-visible), -.mdViewerWrap details-dialog:focus:not(:focus-visible) { - outline: none; -} - -.mdViewerWrap g-emoji { - display: inline-block; - min-width: 1ch; - font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-size: 1em; - font-style: normal !important; - font-weight: 400; - line-height: 1; - vertical-align: -0.075em; -} - -.mdViewerWrap g-emoji img { - width: 1em; - height: 1em; -} - -.mdViewerWrap .task-list-item { - list-style-type: none; -} - -.mdViewerWrap .task-list-item label { - font-weight: 400; -} - -.mdViewerWrap .task-list-item.enabled label { - cursor: pointer; -} - -.mdViewerWrap .task-list-item + .task-list-item { - margin-top: 0.25rem; -} - -.mdViewerWrap .task-list-item .handle { - display: none; -} - -.mdViewerWrap .task-list-item-checkbox { - margin: 0 0.2em 0.25em -1.4em; - vertical-align: middle; -} - -.mdViewerWrap .contains-task-list:dir(rtl) .task-list-item-checkbox { - margin: 0 -1.6em 0.25em 0.2em; -} - -.mdViewerWrap .contains-task-list { - position: relative; -} - -.mdViewerWrap .contains-task-list:hover .task-list-item-convert-container, -.mdViewerWrap - .contains-task-list:focus-within - .task-list-item-convert-container { - display: block; - width: auto; - height: 24px; - overflow: visible; - clip: auto; -} - -.mdViewerWrap ::-webkit-calendar-picker-indicator { - filter: invert(50%); -} - -.mdViewerWrap .markdown-alert { - padding: 0.5rem 1rem; - margin-bottom: 1rem; - color: inherit; - border-left: 0.25em solid #d0d7de; -} - -.mdViewerWrap .markdown-alert > :first-child { - margin-top: 0; -} - -.mdViewerWrap .markdown-alert > :last-child { - margin-bottom: 0; -} - -.mdViewerWrap .markdown-alert .markdown-alert-title { - display: flex; - font-weight: 500; - align-items: center; - line-height: 1; -} - -.mdViewerWrap .markdown-alert.markdown-alert-note { - border-left-color: #0969da; -} - -.mdViewerWrap .markdown-alert.markdown-alert-note .markdown-alert-title { - color: #0969da; -} - -.mdViewerWrap .markdown-alert.markdown-alert-important { - border-left-color: #8250df; -} - -.mdViewerWrap .markdown-alert.markdown-alert-important .markdown-alert-title { - color: #8250df; -} - -.mdViewerWrap .markdown-alert.markdown-alert-warning { - border-left-color: #bf8700; -} - -.mdViewerWrap .markdown-alert.markdown-alert-warning .markdown-alert-title { - color: #9a6700; -} - -.mdViewerWrap .markdown-alert.markdown-alert-tip { - border-left-color: #1a7f37; -} - -.mdViewerWrap .markdown-alert.markdown-alert-tip .markdown-alert-title { - color: #1a7f37; -} - -.mdViewerWrap .markdown-alert.markdown-alert-caution { - border-left-color: #cf222e; -} - -.mdViewerWrap .markdown-alert.markdown-alert-caution .markdown-alert-title { - color: #d1242f; -} - -.mdViewerWrap > *:first-child > .heading-element:first-child { - margin-top: 0 !important; -} diff --git a/projects/web/src/pages/extract/components/md-viewer/index.tsx b/projects/web/src/pages/extract/components/md-viewer/index.tsx deleted file mode 100644 index 5c708b5ae18bb0d90467f5757dcd7c493b33cfd6..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/md-viewer/index.tsx +++ /dev/null @@ -1,278 +0,0 @@ -import { useEffect, useRef, useState } from "react"; -import { Tooltip } from "antd"; - -import cls from "classnames"; -import styles from "./index.module.scss"; -import { useDeepCompareEffect, useHover } from "ahooks"; -import IconFont from "@/components/icon-font"; -import { downloadFileUseAScript } from "@/utils/download"; -import { MD_DRIVE_PDF } from "@/constant/event"; -import { useIntl } from "react-intl"; -import LazyUrlMarkdown from "../url-markdown"; -import exitFullScreenSvg from "@/assets/pdf/exitFullScreen.svg"; -import fullScreenSvg from "@/assets/pdf/fullScreen.svg"; -import { MD_PREVIEW_TYPE } from "@/types/extract-task-type"; -import _ from "lodash"; -import { TaskIdResItem } from "@/api/extract"; -import useMdStore from "@/store/mdStore"; -import CodeMirror from "@/components/code-mirror"; -import { useParams } from "react-router-dom"; -import SaveStatus, { SaveStatusRef } from "@/components/SaveStatus"; - -interface IMdViewerProps { - md?: string; - className?: string; - filename?: string; - url?: string; - taskInfo: TaskIdResItem; - curPage: number; - fullScreen?: boolean; - setFullScreen?: (value?: boolean) => void; -} - -const MdViewer: React.FC = ({ - fullScreen, - setFullScreen, - taskInfo, - className = "", - curPage, -}) => { - const mdViewerPef = useRef(null); - const url = taskInfo?.fullMdLink || ""; - const containerRef = useRef(null); - const isHovering = useHover(containerRef); - const { formatMessage } = useIntl(); - const [displayType, setDisplayType] = useState(MD_PREVIEW_TYPE.preview); - const params = useParams(); - const { - setAllMdContentWithAnchor, - allMdContentWithAnchor, - setMdUrlArr, - mdContents, - updateMdContent, - } = useMdStore(); - const [lineWrap, setLineWrap] = useState(false); - - const threshold = 562 - 427; - const statusRef = useRef(null); - - const menuList = [ - { - name: formatMessage({ id: "extractor.markdown.preview" }), - code: MD_PREVIEW_TYPE.preview, - }, - { - name: formatMessage({ id: "extractor.markdown.code" }), - code: MD_PREVIEW_TYPE.code, - }, - ]; - - const getVisibleFromType = (str: string, type: string) => { - return str === type - ? "relative w-full h-full" - : "w-0 h-0 overflow-hidden hidden"; - }; - - const pushMdViewerScroll = (scrollType?: "instant" | "smooth") => { - const container = document.getElementById(`md-container`); - // md渲染的时候用一个元素包括anchor - const element = - displayType === MD_PREVIEW_TYPE.preview - ? document.getElementById(`md-anchor-${curPage - 1}`)?.parentElement - : document.getElementById(`code-${curPage - 1}`); - if (element && container) { - container.scrollTo({ - top: element.offsetTop - 124, - behavior: scrollType || "smooth", - }); - } - }; - - useEffect(() => { - if (isHovering) return; - pushMdViewerScroll(); - }, [curPage, isHovering]); - - useEffect(() => { - pushMdViewerScroll("instant"); - }, [displayType]); - - useEffect(() => { - if (!isHovering) return; - const handleScroll = () => { - if (!containerRef.current) return; - - taskInfo?.markdownUrl?.forEach((page, index) => { - const element = - displayType === MD_PREVIEW_TYPE.preview - ? document.getElementById(`md-anchor-${index}`)?.parentElement - : document.getElementById(`code-${index}`); - - if (element) { - const rect = element.getBoundingClientRect(); - - if (rect.top <= threshold) { - document.dispatchEvent( - new CustomEvent(MD_DRIVE_PDF, { - detail: index, - }) - ); - } - } - }); - }; - - const container = containerRef.current; - if (container) { - container.addEventListener("scroll", handleScroll); - } - - return () => { - if (container) { - container?.removeEventListener("scroll", handleScroll); - } - }; - }, [taskInfo, isHovering, displayType]); - - useDeepCompareEffect(() => { - if (taskInfo?.markdownUrl) { - setMdUrlArr(taskInfo?.markdownUrl); - } - statusRef?.current?.reset(); - }, [taskInfo?.markdownUrl, params?.jobID]); - - const handleContentChange = (val: string, index: number) => { - setAllMdContentWithAnchor(val); - statusRef?.current?.triggerSave(); - if (taskInfo?.file_key) { - updateMdContent(taskInfo.file_key!, index, val); - } - }; - - return ( -
    -
    -
      - {menuList.map((item) => ( -
    • setDisplayType(item.code)} - > - {item.name} -
    • - ))} -
    - - - {displayType === "code" && ( - <> - - setLineWrap?.(!lineWrap)} - /> - - - - )} - - setFullScreen?.(!fullScreen)} - > - {!fullScreen ? ( - - ) : ( - - )} - - - - - - downloadFileUseAScript( - url, - `${_(taskInfo?.fileName).split(".").slice(0, -1).join(".")}.md` - ) - } - /> - -
    -
    -
    - -
    -
    - {taskInfo?.markdownUrl?.map((url: string, index: number) => { - const md = mdContents[url]?.content || ""; - if (!md) return null; - return ( -
    - handleContentChange(val, index)} - editable - className="w-full h-full" - /> -
    - ); - })} -
    -
    -
    - ); -}; -export default MdViewer; diff --git a/projects/web/src/pages/extract/components/md-viewer/test.md b/projects/web/src/pages/extract/components/md-viewer/test.md deleted file mode 100644 index aa6093aa787b2829b88b1abed721927baa5ba185..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/md-viewer/test.md +++ /dev/null @@ -1,85 +0,0 @@ -# 欢迎来到我的博客 - -这是我的个人博客,我会在这里分享我的想法、经验和学习笔记。 - -## 关于我 - -我是一名热爱技术的程序员,专注于 Web 开发领域。我喜欢探索新的技术和框架,并不断学习和提升自己的技能。 - -在这个博客中,你可以找到以下内容: - -- 技术文章和教程 -- 个人项目分享 -- 学习笔记和总结 -- 生活点滴和随笔 - -如果你对我的文章感兴趣,欢迎留言交流和讨论。 - -## 最新文章 - -### 1. 如何使用 React Hooks 优化组件性能 - -在这篇文章中,我将介绍 React Hooks 的基本概念,并通过示例说明如何使用 Hooks 来优化组件的性能。我们会讨论以下内容: - -- useState 和 useEffect 的使用 -- useCallback 和 useMemo 的性能优化技巧 -- 自定义 Hooks 的创建和使用 - -通过学习和应用这些技巧,你可以编写出更加高效和可维护的 React 组件。 - -### 2. 探索 Node.js 的异步编程 - -Node.js 以其非阻塞的异步编程模型而闻名。在这篇文章中,我们将深入探讨 Node.js 中的异步编程概念和技巧。主要内容包括: - -- 回调函数的使用 -- Promise 的链式调用和错误处理 -- async/await 的使用和优势 -- 事件循环和异步 I/O - -通过掌握这些异步编程技巧,你可以更好地利用 Node.js 的优势,编写出高性能和可扩展的应用程序。 - -## 联系我 - -如果你想与我联系,可以通过以下方式找到我: - -- 邮件: example@example.com -- GitHub: [https://github.com/username](https://github.com/username) -- Twitter: [@username](https://twitter.com/username) - -欢迎与我交流和分享你的想法! - ---- - -# 第二页 - -## 我的项目 - -在这个部分,我将介绍一些我最近参与的个人项目。 - -### 1. ToDo 应用 - -这是一个简单的 ToDo 应用,使用 React 和 Firebase 实现。主要功能包括: - -- 添加和删除任务 -- 标记任务为已完成 -- 实时同步和数据持久化 - -通过这个项目,我学习了 React 组件的基本开发和 Firebase 的实时数据库的使用。你可以在这个仓库中找到完整的源代码: [https://github.com/username/todo-app](https://github.com/username/todo-app) - -### 2. 天气预报应用 - -这是一个基于 Node.js 和 Express 的天气预报应用。它使用第三方 API 获取天气数据,并以 Web 页面的形式展示给用户。主要功能包括: - -- 根据用户输入的城市名获取天气信息 -- 显示当前天气状况和未来几天的天气预报 -- 支持多个城市的天气查询 - -通过这个项目,我学习了如何使用 Node.js 和 Express 构建 Web 应用,以及如何与外部 API 进行交互。你可以在这个仓库中找到完整的源代码: [https://github.com/username/weather-app](https://github.com/username/weather-app) - -## 总结 - -这就是我的博客的前两页内容。我会不定期更新文章和分享我的项目。如果你对我的文章或项目感兴趣,欢迎留言交流。 - -如果你有任何建议或意见,也欢迎随时联系我。希望我的博客能给你带来一些有价值的信息和启发。 - -谢谢阅读! diff --git a/projects/web/src/pages/extract/components/pdf-extraction/index.tsx b/projects/web/src/pages/extract/components/pdf-extraction/index.tsx deleted file mode 100644 index 8f907e14d192ce9e52c1b9d4a229e50174babc59..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/pdf-extraction/index.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import cls from "classnames"; -import { - ExtractorUploadButton, - LinearButton, -} from "../pdf-upload-button/index"; -import { useState } from "react"; -import MdViewer from "../md-viewer"; -import PDFViewerMemo from "../pdf-viewer"; - -import LoadingIcon from "../../components/loading-icon"; -import emptySvg from "@/assets/svg/empty.svg"; - -import { useIntl, FormattedMessage } from "react-intl"; - -import { useJobExtraction } from "@/store/jobProgress"; -import { postReUploadExtractTask } from "@/api/extract"; -import { useParams } from "react-router-dom"; - -interface IPdfExtractionProps { - className?: string; -} - -const PdfExtraction = ({ className = "" }: IPdfExtractionProps) => { - const { - refreshQueue, - taskInfo, - isLoading: queueLoading, - isError: compileError, - } = useJobExtraction(); - - const [pdfState, setPdfState] = useState({ - page: 1, - }); - const curPage = pdfState.page; - - const { jobID } = useParams(); - - const { formatMessage } = useIntl(); - - const [fullScreen, setFullScreen] = useState(false); - - const afterUploadSuccess = () => { - refreshQueue(); - }; - - const isQueueAndExtract = queueLoading; - const hiddenQueuePage = !isQueueAndExtract - ? "!w-0 !h-0 overflow-hidden " - : ""; - const hiddenResultPage = isQueueAndExtract ? "!w-0 !h-0 overflow-hidden" : ""; - - const getLayoutClassName = (_fullScreen?: boolean) => { - return { - left: _fullScreen ? "!w-0 !h-0 overflow-hidden hidden" : "min-w-[50%]", - right: _fullScreen ? "w-full " : "min-w-[50%]", - }; - }; - - const afterAsyncCheck = async () => { - return Promise.resolve(true); - }; - - const getExtractionStatusText = (rank: number) => { - switch (true) { - case rank > 1: - return ( - - ); - case rank === 1: - return formatMessage({ id: "extractor.common.extracting" }); - - default: - return ""; - } - }; - - return ( - <> -
    - - -
    - {getExtractionStatusText(taskInfo?.rank)} -
    -
    - -
    - {!compileError ? ( -
    -
    - setPdfState(p)} - /> -
    -
    - setFullScreen(!!bool)} - /> -
    -
    - ) : ( -
    - emptySvg - - {formatMessage({ - id: "extractor.failed", - })} - - { - await postReUploadExtractTask(String(jobID)); - refreshQueue(); - }} - className="mt-4" - text={formatMessage({ - id: "common.retry", - })} - /> -
    - )} -
    - - ); -}; - -export default PdfExtraction; diff --git a/projects/web/src/pages/extract/components/pdf-upload-button/index.module.scss b/projects/web/src/pages/extract/components/pdf-upload-button/index.module.scss deleted file mode 100644 index 5499a5140ac9ed7e8002a049e86f953955e15c92..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/pdf-upload-button/index.module.scss +++ /dev/null @@ -1,53 +0,0 @@ -.gradientBtn { - width: 188px; - height: 37px; - border-radius: 8px; - font-size: 14px; - color: rgba(255, 255, 255, 0.95); - background: linear-gradient(110deg, #38A0FF -33.56%, #0D53DE 32.84%, #5246FF 102.05%); - // background: #3477EB; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - &:hover { - background: #3477EB; - } - :global { - .ant-upload-list-item-container { - // display: none !important; - } - .ant-upload { - display: flex; - align-items: center; - justify-content: center; - width: 100% !important; - height: 100% !important; - line-height: 100% !important; - } - .ant-upload-drag { - border: none !important; - } - } -} - -.linearBtn { - width: 188px; - height: 37px; - border-radius: 8px; - font-size: 14px; - color: rgba(255, 255, 255, 0.95); - background: linear-gradient(110deg, #38A0FF -33.56%, #0D53DE 32.84%, #5246FF 102.05%); - // background: #3477EB; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - &:hover { - color: rgba(255, 255, 255, 0.95) !important; - background: linear-gradient(110deg, #38A0FF -33.56%, #38A0FF 32.84%, #38A0FF 102.05%) !important; - } - &:active { - - } -} diff --git a/projects/web/src/pages/extract/components/pdf-upload-button/index.tsx b/projects/web/src/pages/extract/components/pdf-upload-button/index.tsx deleted file mode 100644 index 0e5566789a6a52a4f815f2eb98a550fb885f3b68..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/pdf-upload-button/index.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { Button } from "antd"; -import cls from "classnames"; -import UploadingOutlined from "@/assets/imgs/online.experience/UploadingOutlined.svg"; -import styles from "./index.module.scss"; -import Upload from "@/components/upload"; -import { ReactNode } from "react"; -import { - postExtractTask, - postReUploadExtractTask, - SubmitRes, -} from "@/api/extract"; - -import { useParams } from "react-router-dom"; -import { ExtractTaskType } from "@/types/extract-task-type"; - -interface IPdfUploadButtonProps { - afterUploadSuccess?: (submitTask: SubmitRes) => void; - afterAsyncCheck?: () => Promise; - text?: string | ReactNode; - className?: string; - showIcon?: boolean; - beforeUpload?: () => void; - onUploadError?: () => void; - accept: string; - extractType: ExtractTaskType; - taskType?: string; - submitType?: "submit" | "reUpload"; - isOcr?: boolean; -} - -interface ILinearButtonProps { - className?: string; - text?: string | ReactNode; - onClick?: () => void; -} - -export const LinearButton = ({ - className = "", - onClick, - text, -}: ILinearButtonProps) => { - return ( - - ); -}; - -export const ExtractorUploadButton = ({ - text = "上传PDF", - className = "", - afterAsyncCheck, - afterUploadSuccess, - beforeUpload: beforeLocalUpload, - onUploadError, - showIcon = true, - accept, - extractType, - taskType, - submitType, - isOcr, -}: IPdfUploadButtonProps) => { - const urlParams = useParams(); - const beforeUpload = async () => { - beforeLocalUpload?.(); - const isCheck = await afterAsyncCheck?.(); - return isCheck; - }; - const onChange = async (pdfFile: any) => { - if (pdfFile?.file?.status === "done") { - const res = - submitType === "reUpload" - ? await postReUploadExtractTask(String(urlParams?.jobID)) - : await postExtractTask({ - fileKey: pdfFile?.file?.response?.data?.data?.file_key, - fileName: pdfFile?.file?.name, - taskType: extractType, - isOcr, - }); - - if (res) { - if (!("error" in res)) { - afterUploadSuccess?.({ - ...(res || {}), - type: extractType, - } as any); - } else { - onUploadError?.(); - } - } else { - onUploadError?.(); - } - } - }; - - return ( - <> - -
    - {showIcon && } - {text} -
    -
    - - ); -}; diff --git a/projects/web/src/pages/extract/components/pdf-upload/index.module.scss b/projects/web/src/pages/extract/components/pdf-upload/index.module.scss deleted file mode 100644 index 45534aa2b13071062a232448d360a6dd15a7010e..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/pdf-upload/index.module.scss +++ /dev/null @@ -1,115 +0,0 @@ -.textBtn { - background-image: none !important; - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background: linear-gradient(111deg, #0D53DE -21.44%, #5246FF 102%) !important; - background-clip: text !important; - -webkit-background-clip: text !important; - -webkit-text-fill-color: transparent !important; - height: 1.5rem !important; - font-weight: 600; - height: 280px !important; - width: 600px !important; - overflow: hidden; -} - -.uploadText { - font-feature-settings: 'liga' off, 'clig' off; - font-family: "PingFang SC"; - font-size: 18px; - font-style: normal; - font-weight: 600; - line-height: 24px; /* 133.333% */ - background: linear-gradient(107deg, #38A0FF -24.14%, #0D53DE 30.09%, #5246FF 86.61%); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; -} - -.uploadDescText { - font-size: 13px; - line-height: 20px; - font-weight: 400; - background: linear-gradient(107deg, rgba(18,19,22,0.6) -24.14%, rgba(18,19,22,0.6) 100.09% ); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - margin-bottom: 1rem; - margin-top: 0.5rem; -} - -.linearText { - font-size: 13px; - line-height: 20px; - font-weight: 400; - background: linear-gradient(107deg, rgba(18,19,22,0.6) -24.14%, rgba(18,19,22,0.6) 100.09% ); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - - - &-item { - font-weight: 400; - font-size: 13px; - line-height: 20px; - margin-right: 1rem; - background: linear-gradient(107deg, #38A0FF -24.14%, #0D53DE 30.09%, #5246FF 86.61%); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - &:hover { - background: #3477EB; - background: linear-gradient(107deg, #3477EB -24.14%, #3477EB 100.09% ); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - } - } -} - -.uploadSection { - border-radius: 12px; - border: 1px dashed var(---Brand1-6, #0D53DE); - background: linear-gradient(180deg, rgba(92, 147, 255, 0.10) -130.23%, rgba(255, 255, 255, 1) 83.57%); - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - filter: blur(0px); - height: 280px !important; - width: 600px !important; - - &:hover { - background: linear-gradient(180deg, rgb(245, 248, 255) -130.23%, rgb(245, 248, 255) 83.57%); - } - - -} - -.item { - border-radius: 12px; - border: 1px solid rgba(198, 217, 255, 0.20); - background: linear-gradient(155deg, rgba(92, 147, 255, 0.10) -13.23%, rgba(255, 255, 255, 0.00) 83.57%); - filter: blur(0px); - padding: 42px 20px; -} - -.customPopover { - :global { - - .ant-popover-content, .ant-popover-inner { - border-radius: 12px !important; - overflow: hidden; - box-shadow: 0px 8px 26px 0px rgba(0, 0, 0, 0.12); - } - - .ant-popover-inner-content { - padding: 12px !important; - } - - .ant-popover-arrow { - display: none !important; - } - } -} diff --git a/projects/web/src/pages/extract/components/pdf-upload/index.tsx b/projects/web/src/pages/extract/components/pdf-upload/index.tsx deleted file mode 100644 index 2721d85e7152652c5108685c6f34a0dd782b29c3..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/pdf-upload/index.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import UploadBg from "@/assets/imgs/online.experience/file-upload-bg.svg"; -import style from "./index.module.scss"; -import { ExtractorUploadButton } from "../pdf-upload-button"; -import { useNavigate } from "react-router-dom"; -import cls from "classnames"; - -import { SubmitRes } from "@/api/extract"; -import { Checkbox, Popover } from "antd"; - -import { useIntl } from "react-intl"; -import IconFont from "@/components/icon-font"; - -import { ADD_TASK_LIST } from "@/constant/event"; -import { useState } from "react"; - -const PdfUpload = () => { - const navigate = useNavigate(); - - const { formatMessage } = useIntl(); - - const [checked, setChecked] = useState(false); - - const afterUploadSuccess = (data: SubmitRes) => { - navigate(`/OpenSourceTools/Extractor/PDF/${data?.id}`); - setTimeout(() => { - document.dispatchEvent( - new CustomEvent(ADD_TASK_LIST, { - detail: data, - }) - ); - }, 10); - }; - - const afterAsyncCheck = async () => { - return Promise.resolve(true); - }; - - return ( -
    -
    -
    - {formatMessage({ id: "extractor.pdf.title" })} -
    -
    - {formatMessage({ id: "extractor.pdf.subTitle" })} -
    - - - - - {formatMessage({ id: "extractor.common.upload" })} - - { - e.preventDefault(); - e.stopPropagation(); - }} - > - setChecked(!checked)} - /> - {formatMessage({ id: "extractor.pdf.ocr" })} - - {formatMessage({ - id: "extractor.pdf.ocr.popover", - })} -
    - } - placement="right" - showArrow={false} - overlayClassName={style.customPopover} - > - - - - {/* - {formatMessage({ id: "extractor.common.pdf.upload.tip" })} - */} -
    - } - className={style.textBtn} - showIcon={false} - /> - -
    - {formatMessage({ - id: "extractor.law", - })} -
    - - ); -}; -export default PdfUpload; diff --git a/projects/web/src/pages/extract/components/pdf-viewer/index.tsx b/projects/web/src/pages/extract/components/pdf-viewer/index.tsx deleted file mode 100644 index 9be6d30b0ca528384a41bbd982a5af41b1fd509f..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/pdf-viewer/index.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import { MD_DRIVE_PDF } from "@/constant/event"; -import { message } from "antd"; -import { TaskIdProgress, TaskIdResItem } from "@/api/extract"; -import React, { useEffect, useRef } from "react"; -import { useLatest } from "ahooks"; -import { - DEFAULT_COLOR_SECTION, - PDF_COLOR_PICKER, -} from "@/constant/pdf-color-picker"; - -interface PDFViewerState { - page: number; -} - -interface Bbox { - type: "title" | "text" | "discarded" | "image"; - bbox: [number, number, number, number]; - color: any; -} - -interface ExtractLayerItem { - preproc_blocks: Bbox[]; - page_idx: number; - page_size: [number, number]; - discarded_blocks: Bbox[]; -} - -// func -const formatJson = (layerList: ExtractLayerItem[]) => { - return layerList?.map((i) => { - let bboxes = [] as { type: string; bbox: number[]; color: any }[]; - - i?.preproc_blocks?.forEach((item) => { - bboxes.push({ - type: item.type, - bbox: item.bbox, - color: PDF_COLOR_PICKER?.[item.type] || DEFAULT_COLOR_SECTION, - }); - }); - - i?.discarded_blocks?.forEach((item) => { - bboxes.push({ - type: item.type, - bbox: item.bbox, - color: PDF_COLOR_PICKER?.[item.type] || DEFAULT_COLOR_SECTION, - }); - }); - - return { - ...i, - bboxes, - }; - }); -}; - -const PDFViewer = ({ - taskInfo, - onChange, -}: { - taskInfo: TaskIdProgress & TaskIdResItem; - onChange: (state: PDFViewerState) => void; -}) => { - const iframeRef = useRef(null); - const _layerData = useLatest(taskInfo?.content); - - const pdfUrl = taskInfo?.url; - - const sendMessageToIframe = (type: string, message: any) => { - if (iframeRef.current) { - iframeRef.current.contentWindow?.postMessage( - { - type, - data: message, - }, - import.meta.env.BASE_URL || "*" - ); - } - }; - - useEffect(() => { - const handleMessage = (event: MessageEvent) => { - if (event?.data?.pageNum) { - const num = event?.data?.pageNum || 1; - sendMessageToIframe("pageChange", num); - } - - if (event?.data?.pageNumDetail) { - const pageNumDetail = event?.data?.pageNumDetail || 1; - onChange?.({ - page: pageNumDetail, - }); - sendMessageToIframe("pageNumDetail", pageNumDetail); - } - - if (event?.data?.status) { - const status = event?.data?.status; - if (status === "loaded") { - sendMessageToIframe( - "initExtractLayerData", - formatJson(_layerData?.current as any) - ); - sendMessageToIframe("title", ""); - } - } - - if (event?.data?.error) { - message?.error(event?.data?.error); - } - }; - - window.addEventListener("message", handleMessage); - - return () => { - window.removeEventListener("message", handleMessage); - }; - }, []); - - useEffect(() => { - const handlePageChange = ({ detail }: CustomEvent) => { - sendMessageToIframe("setPage", detail + 1); - }; - document.addEventListener(MD_DRIVE_PDF, handlePageChange as EventListener); - return () => { - document.removeEventListener( - MD_DRIVE_PDF, - handlePageChange as EventListener - ); - }; - }, []); - - return ( - <> - {pdfUrl ? ( - - ) : null} - - ); -}; - -export default PDFViewer; diff --git a/projects/web/src/pages/extract/components/url-markdown/index.module.scss b/projects/web/src/pages/extract/components/url-markdown/index.module.scss deleted file mode 100644 index 6a1f2f0fcb33ecc64e898b484fe03094f3382819..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/url-markdown/index.module.scss +++ /dev/null @@ -1,1142 +0,0 @@ -/*light*/ - -// 自定义滚动跳 -.scrollBar { - // 火狐 - scrollbar-color: #EBECF0 transparent; - scrollbar-width: thin; - - // 定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸 - &::-webkit-scrollbar { - width: 4px; - height: 6px; - background-color: transparent; - } - - // 定义滚动条轨道 内阴影+圆角 - &::-webkit-scrollbar-track { - background-color: #fff; - border-radius: 10px; - box-shadow: transparent; - } - - // 定义滑块 内阴影+圆角 - &::-webkit-scrollbar-thumb { - background: #EBECF0; - border-radius: 10px; - box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.6); - } - } - - .mdViewerWrap { - font-size: 10px; - } - - .mdViewerWrap { - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; - margin: 0; - color: #1f2328; - background-color: #ffffff; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", - Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; - font-size: 16px; - line-height: 1.5; - word-wrap: break-word; - scroll-behavior: auto; - } - - .mdViewerWrap .octicon { - display: inline-block; - fill: currentColor; - vertical-align: text-bottom; - } - - .mdViewerWrap h1:hover .anchor .octicon-link:before, - .mdViewerWrap h2:hover .anchor .octicon-link:before, - .mdViewerWrap h3:hover .anchor .octicon-link:before, - .mdViewerWrap h4:hover .anchor .octicon-link:before, - .mdViewerWrap h5:hover .anchor .octicon-link:before, - .mdViewerWrap h6:hover .anchor .octicon-link:before { - width: 16px; - height: 16px; - content: " "; - display: inline-block; - background-color: currentColor; - -webkit-mask-image: url("data:image/svg+xml,"); - mask-image: url("data:image/svg+xml,"); - } - - .mdViewerWrap details, - .mdViewerWrap figcaption, - .mdViewerWrap figure { - display: block; - } - - .mdViewerWrap summary { - display: list-item; - } - - .mdViewerWrap [hidden] { - display: none !important; - } - - .mdViewerWrap a { - background-color: transparent; - color: #0969da; - text-decoration: none; - } - - .mdViewerWrap abbr[title] { - border-bottom: none; - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; - } - - .mdViewerWrap b, - .mdViewerWrap strong { - font-weight: 600; - } - - .mdViewerWrap dfn { - font-style: italic; - } - - .mdViewerWrap h1 { - margin: 0.67em 0; - font-weight: 600; - padding-bottom: 0.3em; - font-size: 2em; - border-bottom: 1px solid #d0d7deb3; - } - - .mdViewerWrap mark { - background-color: #fff8c5; - color: #1f2328; - } - - .mdViewerWrap small { - font-size: 90%; - } - - .mdViewerWrap sub, - .mdViewerWrap sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; - } - - .mdViewerWrap sub { - bottom: -0.25em; - } - - .mdViewerWrap sup { - top: -0.5em; - } - - .mdViewerWrap img { - border-style: none; - max-width: 100%; - box-sizing: content-box; - background-color: #ffffff; - } - - .mdViewerWrap code, - .mdViewerWrap kbd, - .mdViewerWrap pre, - .mdViewerWrap samp { - font-family: monospace; - font-size: 1em; - } - - .mdViewerWrap figure { - margin: 1em 40px; - } - - .mdViewerWrap hr { - box-sizing: content-box; - overflow: hidden; - background: transparent; - border-bottom: 1px solid #d0d7deb3; - height: 0.25em; - padding: 0; - margin: 24px 0; - background-color: #d0d7de; - border: 0; - } - - .mdViewerWrap input { - font: inherit; - margin: 0; - overflow: visible; - font-family: inherit; - font-size: inherit; - line-height: inherit; - } - - .mdViewerWrap [type="button"], - .mdViewerWrap [type="reset"], - .mdViewerWrap [type="submit"] { - -webkit-appearance: button; - appearance: button; - } - - .mdViewerWrap [type="checkbox"], - .mdViewerWrap [type="radio"] { - box-sizing: border-box; - padding: 0; - } - - .mdViewerWrap [type="number"]::-webkit-inner-spin-button, - .mdViewerWrap [type="number"]::-webkit-outer-spin-button { - height: auto; - } - - .mdViewerWrap [type="search"]::-webkit-search-cancel-button, - .mdViewerWrap [type="search"]::-webkit-search-decoration { - -webkit-appearance: none; - appearance: none; - } - - .mdViewerWrap ::-webkit-input-placeholder { - color: inherit; - opacity: 0.54; - } - - .mdViewerWrap ::-webkit-file-upload-button { - -webkit-appearance: button; - appearance: button; - font: inherit; - } - - .mdViewerWrap a:hover { - text-decoration: underline; - } - - .mdViewerWrap ::placeholder { - color: #636c76; - opacity: 1; - } - - .mdViewerWrap hr::before { - display: table; - content: ""; - } - - .mdViewerWrap hr::after { - display: table; - clear: both; - content: ""; - } - - .mdViewerWrap table { - border-spacing: 0; - border-collapse: collapse; - display: block; - width: max-content; - max-width: 100%; - overflow: auto; - } - - .mdViewerWrap td, - .mdViewerWrap th { - padding: 0; - } - - .mdViewerWrap details summary { - cursor: pointer; - } - - .mdViewerWrap details:not([open]) > *:not(summary) { - display: none; - } - - .mdViewerWrap a:focus, - .mdViewerWrap [role="button"]:focus, - .mdViewerWrap input[type="radio"]:focus, - .mdViewerWrap input[type="checkbox"]:focus { - outline: 2px solid #0969da; - outline-offset: -2px; - box-shadow: none; - } - - .mdViewerWrap a:focus:not(:focus-visible), - .mdViewerWrap [role="button"]:focus:not(:focus-visible), - .mdViewerWrap input[type="radio"]:focus:not(:focus-visible), - .mdViewerWrap input[type="checkbox"]:focus:not(:focus-visible) { - outline: solid 1px transparent; - } - - .mdViewerWrap a:focus-visible, - .mdViewerWrap [role="button"]:focus-visible, - .mdViewerWrap input[type="radio"]:focus-visible, - .mdViewerWrap input[type="checkbox"]:focus-visible { - outline: 2px solid #0969da; - outline-offset: -2px; - box-shadow: none; - } - - .mdViewerWrap a:not([class]):focus, - .mdViewerWrap a:not([class]):focus-visible, - .mdViewerWrap input[type="radio"]:focus, - .mdViewerWrap input[type="radio"]:focus-visible, - .mdViewerWrap input[type="checkbox"]:focus, - .mdViewerWrap input[type="checkbox"]:focus-visible { - outline-offset: 0; - } - - .mdViewerWrap kbd { - display: inline-block; - padding: 3px 5px; - font: 11px ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, - Liberation Mono, monospace; - line-height: 10px; - color: #1f2328; - vertical-align: middle; - background-color: #f6f8fa; - border: solid 1px #afb8c133; - border-bottom-color: #afb8c133; - border-radius: 6px; - box-shadow: inset 0 -1px 0 #afb8c133; - } - - .mdViewerWrap h1, - .mdViewerWrap h2, - .mdViewerWrap h3, - .mdViewerWrap h4, - .mdViewerWrap h5, - .mdViewerWrap h6 { - margin-top: 24px; - margin-bottom: 16px; - font-weight: 600; - line-height: 1.25; - } - - .mdViewerWrap h2 { - font-weight: 600; - padding-bottom: 0.3em; - font-size: 1.5em; - border-bottom: 1px solid #d0d7deb3; - } - - .mdViewerWrap h3 { - font-weight: 600; - font-size: 1.25em; - } - - .mdViewerWrap h4 { - font-weight: 600; - font-size: 1em; - } - - .mdViewerWrap h5 { - font-weight: 600; - font-size: 0.875em; - } - - .mdViewerWrap h6 { - font-weight: 600; - font-size: 0.85em; - color: #636c76; - } - - .mdViewerWrap p { - margin-top: 0; - margin-bottom: 10px; - font-size: 1.25em; - } - - .mdViewerWrap blockquote { - margin: 0; - padding: 0 1em; - color: #636c76; - border-left: 0.25em solid #d0d7de; - } - - .mdViewerWrap ul, - .mdViewerWrap ol { - margin-top: 0; - margin-bottom: 0; - padding-left: 2em; - } - - .mdViewerWrap ol ol, - .mdViewerWrap ul ol { - list-style-type: lower-roman; - } - - .mdViewerWrap ul ul ol, - .mdViewerWrap ul ol ol, - .mdViewerWrap ol ul ol, - .mdViewerWrap ol ol ol { - list-style-type: lower-alpha; - } - - .mdViewerWrap dd { - margin-left: 0; - } - - .mdViewerWrap tt, - .mdViewerWrap code, - .mdViewerWrap samp { - font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, - Liberation Mono, monospace; - font-size: 12px; - } - - .mdViewerWrap pre { - margin-top: 0; - margin-bottom: 0; - font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, - Liberation Mono, monospace; - font-size: 12px; - word-wrap: normal; - } - - .mdViewerWrap .octicon { - display: inline-block; - overflow: visible !important; - vertical-align: text-bottom; - fill: currentColor; - } - - .mdViewerWrap input::-webkit-outer-spin-button, - .mdViewerWrap input::-webkit-inner-spin-button { - margin: 0; - -webkit-appearance: none; - appearance: none; - } - - .mdViewerWrap .mr-2 { - margin-right: 0.5rem !important; - } - - .mdViewerWrap::before { - display: table; - content: ""; - } - - .mdViewerWrap::after { - display: table; - clear: both; - content: ""; - } - - .mdViewerWrap > *:first-child { - margin-top: 0 !important; - } - - .mdViewerWrap > *:last-child { - margin-bottom: 0 !important; - } - - .mdViewerWrap a:not([href]) { - color: inherit; - text-decoration: none; - } - - .mdViewerWrap .absent { - color: #d1242f; - } - - .mdViewerWrap .anchor { - float: left; - padding-right: 4px; - margin-left: -20px; - line-height: 1; - } - - .mdViewerWrap .anchor:focus { - outline: none; - } - - .mdViewerWrap p, - .mdViewerWrap blockquote, - .mdViewerWrap ul, - .mdViewerWrap ol, - .mdViewerWrap dl, - .mdViewerWrap table, - .mdViewerWrap pre, - .mdViewerWrap details { - margin-top: 0; - margin-bottom: 16px; - } - - .mdViewerWrap blockquote > :first-child { - margin-top: 0; - } - - .mdViewerWrap blockquote > :last-child { - margin-bottom: 0; - } - - .mdViewerWrap h1 .octicon-link, - .mdViewerWrap h2 .octicon-link, - .mdViewerWrap h3 .octicon-link, - .mdViewerWrap h4 .octicon-link, - .mdViewerWrap h5 .octicon-link, - .mdViewerWrap h6 .octicon-link { - color: #1f2328; - vertical-align: middle; - visibility: hidden; - } - - .mdViewerWrap h1:hover .anchor, - .mdViewerWrap h2:hover .anchor, - .mdViewerWrap h3:hover .anchor, - .mdViewerWrap h4:hover .anchor, - .mdViewerWrap h5:hover .anchor, - .mdViewerWrap h6:hover .anchor { - text-decoration: none; - } - - .mdViewerWrap h1:hover .anchor .octicon-link, - .mdViewerWrap h2:hover .anchor .octicon-link, - .mdViewerWrap h3:hover .anchor .octicon-link, - .mdViewerWrap h4:hover .anchor .octicon-link, - .mdViewerWrap h5:hover .anchor .octicon-link, - .mdViewerWrap h6:hover .anchor .octicon-link { - visibility: visible; - } - - .mdViewerWrap h1 tt, - .mdViewerWrap h1 code, - .mdViewerWrap h2 tt, - .mdViewerWrap h2 code, - .mdViewerWrap h3 tt, - .mdViewerWrap h3 code, - .mdViewerWrap h4 tt, - .mdViewerWrap h4 code, - .mdViewerWrap h5 tt, - .mdViewerWrap h5 code, - .mdViewerWrap h6 tt, - .mdViewerWrap h6 code { - padding: 0 0.2em; - font-size: inherit; - } - - .mdViewerWrap summary h1, - .mdViewerWrap summary h2, - .mdViewerWrap summary h3, - .mdViewerWrap summary h4, - .mdViewerWrap summary h5, - .mdViewerWrap summary h6 { - display: inline-block; - } - - .mdViewerWrap summary h1 .anchor, - .mdViewerWrap summary h2 .anchor, - .mdViewerWrap summary h3 .anchor, - .mdViewerWrap summary h4 .anchor, - .mdViewerWrap summary h5 .anchor, - .mdViewerWrap summary h6 .anchor { - margin-left: -40px; - } - - .mdViewerWrap summary h1, - .mdViewerWrap summary h2 { - padding-bottom: 0; - border-bottom: 0; - } - - .mdViewerWrap ul.no-list, - .mdViewerWrap ol.no-list { - padding: 0; - list-style-type: none; - } - - .mdViewerWrap ol[type="a s"] { - list-style-type: lower-alpha; - } - - .mdViewerWrap ol[type="A s"] { - list-style-type: upper-alpha; - } - - .mdViewerWrap ol[type="i s"] { - list-style-type: lower-roman; - } - - .mdViewerWrap ol[type="I s"] { - list-style-type: upper-roman; - } - - .mdViewerWrap ol[type="1"] { - list-style-type: decimal; - } - - .mdViewerWrap div > ol:not([type]) { - list-style-type: decimal; - } - - .mdViewerWrap ul ul, - .mdViewerWrap ul ol, - .mdViewerWrap ol ol, - .mdViewerWrap ol ul { - margin-top: 0; - margin-bottom: 0; - } - - .mdViewerWrap li > p { - margin-top: 16px; - } - - .mdViewerWrap li + li { - margin-top: 0.25em; - } - - .mdViewerWrap dl { - padding: 0; - } - - .mdViewerWrap dl dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: 600; - } - - .mdViewerWrap dl dd { - padding: 0 16px; - margin-bottom: 16px; - } - - .mdViewerWrap table th { - font-weight: 600; - } - - .mdViewerWrap table th, - .mdViewerWrap table td { - padding: 6px 13px; - border: 1px solid #d0d7de; - } - - .mdViewerWrap table td > :last-child { - margin-bottom: 0; - } - - .mdViewerWrap table tr { - background-color: #ffffff; - border-top: 1px solid #d0d7deb3; - } - - .mdViewerWrap table tr:nth-child(2n) { - background-color: #f6f8fa; - } - - .mdViewerWrap table img { - background-color: transparent; - } - - .mdViewerWrap img[align="right"] { - padding-left: 20px; - } - - .mdViewerWrap img[align="left"] { - padding-right: 20px; - } - - .mdViewerWrap .emoji { - max-width: none; - vertical-align: text-top; - background-color: transparent; - } - - .mdViewerWrap span.frame { - display: block; - overflow: hidden; - } - - .mdViewerWrap span.frame > span { - display: block; - float: left; - width: auto; - padding: 7px; - margin: 13px 0 0; - overflow: hidden; - border: 1px solid #d0d7de; - } - - .mdViewerWrap span.frame span img { - display: block; - float: left; - } - - .mdViewerWrap span.frame span span { - display: block; - padding: 5px 0 0; - clear: both; - color: #1f2328; - } - - .mdViewerWrap span.align-center { - display: block; - overflow: hidden; - clear: both; - } - - .mdViewerWrap span.align-center > span { - display: block; - margin: 13px auto 0; - overflow: hidden; - text-align: center; - } - - .mdViewerWrap span.align-center span img { - margin: 0 auto; - text-align: center; - } - - .mdViewerWrap span.align-right { - display: block; - overflow: hidden; - clear: both; - } - - .mdViewerWrap span.align-right > span { - display: block; - margin: 13px 0 0; - overflow: hidden; - text-align: right; - } - - .mdViewerWrap span.align-right span img { - margin: 0; - text-align: right; - } - - .mdViewerWrap span.float-left { - display: block; - float: left; - margin-right: 13px; - overflow: hidden; - } - - .mdViewerWrap span.float-left span { - margin: 13px 0 0; - } - - .mdViewerWrap span.float-right { - display: block; - float: right; - margin-left: 13px; - overflow: hidden; - } - - .mdViewerWrap span.float-right > span { - display: block; - margin: 13px auto 0; - overflow: hidden; - text-align: right; - } - - .mdViewerWrap code, - .mdViewerWrap tt { - padding: 0.2em 0.4em; - margin: 0; - font-size: 85%; - white-space: break-spaces; - background-color: #afb8c133; - border-radius: 6px; - } - - .mdViewerWrap code br, - .mdViewerWrap tt br { - display: none; - } - - .mdViewerWrap del code { - text-decoration: inherit; - } - - .mdViewerWrap samp { - font-size: 85%; - } - - .mdViewerWrap pre code { - font-size: 100%; - } - - .mdViewerWrap pre > code { - padding: 0; - margin: 0; - word-break: normal; - white-space: pre; - background: transparent; - border: 0; - } - - .mdViewerWrap .highlight { - margin-bottom: 16px; - } - - .mdViewerWrap .highlight pre { - margin-bottom: 0; - word-break: normal; - } - - .mdViewerWrap .highlight pre, - .mdViewerWrap pre { - padding: 16px; - overflow: auto; - font-size: 85%; - line-height: 1.45; - color: #1f2328; - background-color: #f6f8fa; - border-radius: 6px; - } - - .mdViewerWrap pre code, - .mdViewerWrap pre tt { - display: inline; - max-width: auto; - padding: 0; - margin: 0; - overflow: visible; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0; - } - - .mdViewerWrap .csv-data td, - .mdViewerWrap .csv-data th { - padding: 5px; - overflow: hidden; - font-size: 12px; - line-height: 1; - text-align: left; - white-space: nowrap; - } - - .mdViewerWrap .csv-data .blob-num { - padding: 10px 8px 9px; - text-align: right; - background: #ffffff; - border: 0; - } - - .mdViewerWrap .csv-data tr { - border-top: 0; - } - - .mdViewerWrap .csv-data th { - font-weight: 600; - background: #f6f8fa; - border-top: 0; - } - - .mdViewerWrap [data-footnote-ref]::before { - content: "["; - } - - .mdViewerWrap [data-footnote-ref]::after { - content: "]"; - } - - .mdViewerWrap .footnotes { - font-size: 12px; - color: #636c76; - border-top: 1px solid #d0d7de; - } - - .mdViewerWrap .footnotes ol { - padding-left: 16px; - } - - .mdViewerWrap .footnotes ol ul { - display: inline-block; - padding-left: 16px; - margin-top: 16px; - } - - .mdViewerWrap .footnotes li { - position: relative; - } - - .mdViewerWrap .footnotes li:target::before { - position: absolute; - top: -8px; - right: -8px; - bottom: -8px; - left: -24px; - pointer-events: none; - content: ""; - border: 2px solid #0969da; - border-radius: 6px; - } - - .mdViewerWrap .footnotes li:target { - color: #1f2328; - } - - .mdViewerWrap .footnotes .data-footnote-backref g-emoji { - font-family: monospace; - } - - .mdViewerWrap .pl-c { - color: #57606a; - } - - .mdViewerWrap .pl-c1, - .mdViewerWrap .pl-s .pl-v { - color: #0550ae; - } - - .mdViewerWrap .pl-e, - .mdViewerWrap .pl-en { - color: #6639ba; - } - - .mdViewerWrap .pl-smi, - .mdViewerWrap .pl-s .pl-s1 { - color: #24292f; - } - - .mdViewerWrap .pl-ent { - color: #0550ae; - } - - .mdViewerWrap .pl-k { - color: #cf222e; - } - - .mdViewerWrap .pl-s, - .mdViewerWrap .pl-pds, - .mdViewerWrap .pl-s .pl-pse .pl-s1, - .mdViewerWrap .pl-sr, - .mdViewerWrap .pl-sr .pl-cce, - .mdViewerWrap .pl-sr .pl-sre, - .mdViewerWrap .pl-sr .pl-sra { - color: #0a3069; - } - - .mdViewerWrap .pl-v, - .mdViewerWrap .pl-smw { - color: #953800; - } - - .mdViewerWrap .pl-bu { - color: #82071e; - } - - .mdViewerWrap .pl-ii { - color: #f6f8fa; - background-color: #82071e; - } - - .mdViewerWrap .pl-c2 { - color: #f6f8fa; - background-color: #cf222e; - } - - .mdViewerWrap .pl-sr .pl-cce { - font-weight: bold; - color: #116329; - } - - .mdViewerWrap .pl-ml { - color: #3b2300; - } - - .mdViewerWrap .pl-mh, - .mdViewerWrap .pl-mh .pl-en, - .mdViewerWrap .pl-ms { - font-weight: bold; - color: #0550ae; - } - - .mdViewerWrap .pl-mi { - font-style: italic; - color: #24292f; - } - - .mdViewerWrap .pl-mb { - font-weight: bold; - color: #24292f; - } - - .mdViewerWrap .pl-md { - color: #82071e; - background-color: #ffebe9; - } - - .mdViewerWrap .pl-mi1 { - color: #116329; - background-color: #dafbe1; - } - - .mdViewerWrap .pl-mc { - color: #953800; - background-color: #ffd8b5; - } - - .mdViewerWrap .pl-mi2 { - color: #eaeef2; - background-color: #0550ae; - } - - .mdViewerWrap .pl-mdr { - font-weight: bold; - color: #8250df; - } - - .mdViewerWrap .pl-ba { - color: #57606a; - } - - .mdViewerWrap .pl-sg { - color: #8c959f; - } - - .mdViewerWrap .pl-corl { - text-decoration: underline; - color: #0a3069; - } - - .mdViewerWrap [role="button"]:focus:not(:focus-visible), - .mdViewerWrap [role="tabpanel"][tabindex="0"]:focus:not(:focus-visible), - .mdViewerWrap button:focus:not(:focus-visible), - .mdViewerWrap summary:focus:not(:focus-visible), - .mdViewerWrap a:focus:not(:focus-visible) { - outline: none; - box-shadow: none; - } - - .mdViewerWrap [tabindex="0"]:focus:not(:focus-visible), - .mdViewerWrap details-dialog:focus:not(:focus-visible) { - outline: none; - } - - .mdViewerWrap g-emoji { - display: inline-block; - min-width: 1ch; - font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-size: 1em; - font-style: normal !important; - font-weight: 400; - line-height: 1; - vertical-align: -0.075em; - } - - .mdViewerWrap g-emoji img { - width: 1em; - height: 1em; - } - - .mdViewerWrap .task-list-item { - list-style-type: none; - } - - .mdViewerWrap .task-list-item label { - font-weight: 400; - } - - .mdViewerWrap .task-list-item.enabled label { - cursor: pointer; - } - - .mdViewerWrap .task-list-item + .task-list-item { - margin-top: 0.25rem; - } - - .mdViewerWrap .task-list-item .handle { - display: none; - } - - .mdViewerWrap .task-list-item-checkbox { - margin: 0 0.2em 0.25em -1.4em; - vertical-align: middle; - } - - .mdViewerWrap .contains-task-list:dir(rtl) .task-list-item-checkbox { - margin: 0 -1.6em 0.25em 0.2em; - } - - .mdViewerWrap .contains-task-list { - position: relative; - } - - .mdViewerWrap .contains-task-list:hover .task-list-item-convert-container, - .mdViewerWrap - .contains-task-list:focus-within - .task-list-item-convert-container { - display: block; - width: auto; - height: 24px; - overflow: visible; - clip: auto; - } - - .mdViewerWrap ::-webkit-calendar-picker-indicator { - filter: invert(50%); - } - - .mdViewerWrap .markdown-alert { - padding: 0.5rem 1rem; - margin-bottom: 1rem; - color: inherit; - border-left: 0.25em solid #d0d7de; - } - - .mdViewerWrap .markdown-alert > :first-child { - margin-top: 0; - } - - .mdViewerWrap .markdown-alert > :last-child { - margin-bottom: 0; - } - - .mdViewerWrap .markdown-alert .markdown-alert-title { - display: flex; - font-weight: 500; - align-items: center; - line-height: 1; - } - - .mdViewerWrap .markdown-alert.markdown-alert-note { - border-left-color: #0969da; - } - - .mdViewerWrap .markdown-alert.markdown-alert-note .markdown-alert-title { - color: #0969da; - } - - .mdViewerWrap .markdown-alert.markdown-alert-important { - border-left-color: #8250df; - } - - .mdViewerWrap .markdown-alert.markdown-alert-important .markdown-alert-title { - color: #8250df; - } - - .mdViewerWrap .markdown-alert.markdown-alert-warning { - border-left-color: #bf8700; - } - - .mdViewerWrap .markdown-alert.markdown-alert-warning .markdown-alert-title { - color: #9a6700; - } - - .mdViewerWrap .markdown-alert.markdown-alert-tip { - border-left-color: #1a7f37; - } - - .mdViewerWrap .markdown-alert.markdown-alert-tip .markdown-alert-title { - color: #1a7f37; - } - - .mdViewerWrap .markdown-alert.markdown-alert-caution { - border-left-color: #cf222e; - } - - .mdViewerWrap .markdown-alert.markdown-alert-caution .markdown-alert-title { - color: #d1242f; - } - - .mdViewerWrap > *:first-child > .heading-element:first-child { - margin-top: 0 !important; - } - \ No newline at end of file diff --git a/projects/web/src/pages/extract/components/url-markdown/index.tsx b/projects/web/src/pages/extract/components/url-markdown/index.tsx deleted file mode 100644 index 1865f44c76927146c424ad76cd35ba0cdfd94de3..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/components/url-markdown/index.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import ReactMarkdown from "react-markdown"; -import remarkMath from "remark-math"; -import rehypeKatex from "rehype-katex"; -import rehypeRaw from "rehype-raw"; -import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; -import remarkGfm from "remark-gfm"; -import styles from "./index.module.scss"; -import { useRef } from "react"; -import cls from "classnames"; - -interface IMarkdownProps { - content?: string; - markdownClass?: string; - markdownId?: string; -} - -const LazyUrlMarkdown: React.FC = ({ - content, - markdownClass = "", -}) => { - const ref = useRef(null); - - return ( -
    -
    - - ) : ( - - {children} - - ); - }, - }} - > - {content} - -
    -
    - ); -}; - -export default LazyUrlMarkdown; diff --git a/projects/web/src/pages/extract/extractor-home/index.module.scss b/projects/web/src/pages/extract/extractor-home/index.module.scss deleted file mode 100644 index e305b83304565f7e5c318fa9fe8a23dcf036324f..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/extractor-home/index.module.scss +++ /dev/null @@ -1,84 +0,0 @@ -.item { - border-radius: 12px; - border: 1px solid rgba(198, 217, 255, 0.20); - background: linear-gradient(155deg, rgba(92, 147, 255, 0.10) -130.23%, rgba(255, 255, 255, 0.00) 83.57%); - filter: blur(0px); - padding: 42px 20px; - cursor: pointer; - position: relative; - - &:hover { - border-radius: 12px; - border: 1px solid rgba(198, 217, 255, 0.20); - background: linear-gradient(155deg, rgba(92, 147, 255, 0.20) -83.23%, rgba(255, 255, 255, 0.00) 83.57%); - box-shadow: 0px 8px 26px 0px rgba(0, 0, 0, 0.12); - } -} - -.itemComingSoon_zh-CN { - &:hover { - - backdrop-filter: blur(-100px); - & > .itemContent { - opacity: 0; - z-index: 0; - } - &::before { - display: inline-block; - content: '敬请期待'; - width: 100%; - height: 100%; - line-height: 184px; - position: absolute; - background-image: url('@/assets/pdf/comingSoonLayer.svg'); - background-color: rgba(255, 255, 255, 0.8); - background-size: contain; - top: 0; - left: 0; - border-radius: 12px; - // background:white; - -webkit-backdrop-filter: blur(2030px) brightness(110%); - backdrop-filter: blur(2030px) brightness(110%); - - color: var(--60-text-3, rgba(18, 19, 22, 0.60)); - text-align: center; - font-feature-settings: 'liga' off, 'clig' off; - z-index: 1; - } - - } -} - -.itemComingSoon_en-US { - &:hover { - - backdrop-filter: blur(-100px); - & > .itemContent { - opacity: 0; - z-index: 0; - } - &::before { - display: inline-block; - content: 'Stay Tuned'; - width: 100%; - height: 100%; - line-height: 224px; - position: absolute; - background-image: url('@/assets/pdf/comingSoonLayer.svg'); - background-color: rgba(255, 255, 255, 0.8); - background-size: contain; - top: 0; - left: 0; - border-radius: 12px; - // background:white; - -webkit-backdrop-filter: blur(2030px) brightness(110%); - backdrop-filter: blur(2030px) brightness(110%); - - color: var(--60-text-3, rgba(18, 19, 22, 0.60)); - text-align: center; - font-feature-settings: 'liga' off, 'clig' off; - z-index: 1; - } - - } -} diff --git a/projects/web/src/pages/extract/extractor-home/index.tsx b/projects/web/src/pages/extract/extractor-home/index.tsx deleted file mode 100644 index c0d488b85bd72c705b0ff8f86450b7784ec68220..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/extractor-home/index.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import extractorPdfIcon from "@/assets/pdf/extractor-pdf.svg"; -import extractorTableIcon from "@/assets/pdf/extractor-table.svg"; -import extractorFormulaIcon from "@/assets/pdf/extractor-formula.svg"; -import style from "./index.module.scss"; -import cls from "classnames"; -import { EXTRACTOR_TYPE_LIST } from "@/types/extract-task-type"; -import { useNavigate } from "react-router-dom"; -import { useIntl } from "react-intl"; - -const ITEM_LIST = [ - { - id: 1, - icon: extractorPdfIcon, - [`zh-CN-title`]: "PDF文档提取", - [`en-US-title`]: "PDF Document Extraction", - type: EXTRACTOR_TYPE_LIST.pdf, - [`zh-CN-desc`]: - "支持文本/扫描型 pdf 解析,识别各类版面元素并转换为多模态 Markdown 格式", - [`en-US-desc`]: - "Supports text/scanned PDF parsing, identifies various layout elements and converts them into multimodal Markdown format", - }, - { - id: 2, - icon: extractorFormulaIcon, - [`zh-CN-title`]: "公式检测与识别", - [`en-US-title`]: "Formula Detection and Recognition", - type: EXTRACTOR_TYPE_LIST.formula, - [`zh-CN-desc`]: - "对行内、行间公式进行检测,对数学公式进行识别并转换为 Latex 格式", - [`en-US-desc`]: - "Detect formulas within and between lines, identify mathematical formulas and convert them into Latex format", - }, - { - id: 3, - icon: extractorTableIcon, - [`zh-CN-title`]: "表格识别", - [`en-US-title`]: "Table recognition", - type: EXTRACTOR_TYPE_LIST.table, - [`zh-CN-desc`]: "对表格进行检测并转换为 Markdown 格式", - [`en-US-desc`]: "Detect and convert tables to Markdown format", - comingSoon: true, - }, -] as Record; - -const ExtractorHome = () => { - const navigate = useNavigate(); - const { formatMessage, locale } = useIntl(); - const defaultLocale = "zh-CN"; - - return ( -
    -
    - {formatMessage({ id: "extractor.home.title" })} -
    -
    - {formatMessage({ id: "extractor.home.subTitle" })} -
    - -
    - {ITEM_LIST?.map((i: Record) => { - return ( -
    { - if (i?.comingSoon) return; - navigate(`/OpenSourceTools/Extractor/${i?.type}`); - }} - > -
    -
    - {""} - - {i?.[`${locale}-title`]} - -
    -
    - {i?.[`${locale}-desc`]} -
    -
    -
    - ); - })} -
    -
    - {formatMessage({ - id: "extractor.law", - })} -
    -
    - ); -}; -export default ExtractorHome; diff --git a/projects/web/src/pages/extract/formula/formula-detail-left/index.tsx b/projects/web/src/pages/extract/formula/formula-detail-left/index.tsx deleted file mode 100644 index 7105e0648984ea00d716c8923b0d954855467408..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/formula/formula-detail-left/index.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import showLayerIcon from "@/assets/pdf/extractor-show-layer.svg"; -import hiddenLayerIcon from "@/assets/pdf/extractor-hidden-layer.svg"; - -import { useRef, useState } from "react"; -import IconFont from "@/components/icon-font"; -import ImageLayerViewer, { - ImageLayerViewerRef, -} from "../../components/image-layer-viwer"; - -import { useUpdate } from "ahooks"; -import { TaskIdProgress, TaskIdResItem } from "@/api/extract"; -import { Tooltip } from "antd"; -import { useIntl } from "react-intl"; - -interface IFormulaDetailLeftProps { - taskInfo: TaskIdProgress & TaskIdResItem; -} - -const FormulaDetailLeft = ({ taskInfo }: IFormulaDetailLeftProps) => { - const imageRef = useRef(null); - const { formatMessage } = useIntl(); - const [layerVisible, setLayerVisible] = useState(true); - const update = useUpdate(); - - if (!taskInfo?.fileInfo?.height || !taskInfo?.fileInfo?.width) { - console.info( - "formula extractor interface error: the picture size is invalid" - ); - } - return ( -
    -
    - - {layerVisible - ? formatMessage({ - id: "extractor.button.hiddenLayer", - }) - : formatMessage({ - id: "extractor.button.showLayer", - })} - - } - > - setLayerVisible(!layerVisible)} - > - {taskInfo?.type === "formula-detect" ? null : layerVisible ? ( - Hide Layer - ) : ( - Show Layer - )} - - - {taskInfo?.type === "formula-detect" ? null : ( - - )} -
    - { - imageRef?.current?.zoomOut(); - }} - /> - - {((imageRef?.current?.scale || 0) * 100 || 1).toFixed(0)}% - - { - imageRef?.current?.zoomIn(); - }} - /> -
    -
    - { - // imageRef?.current?.scale为了这个更新 - update(); - }} - className={"!h-[calc(100%-48px)]"} - layerVisible={ - taskInfo?.type === "formula-detect" ? false : layerVisible - } - imageUrl={taskInfo?.url} - /> -
    - ); -}; - -export default FormulaDetailLeft; diff --git a/projects/web/src/pages/extract/formula/formula-detail-right/index.tsx b/projects/web/src/pages/extract/formula/formula-detail-right/index.tsx deleted file mode 100644 index b9ef731385a7041d14abb8bcdcaac547dd368ec0..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/formula/formula-detail-right/index.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import ImageLayerViewer from "../../components/image-layer-viwer"; -import exitFullScreenSvg from "@/assets/pdf/exitFullScreen.svg"; -import fullScreenSvg from "@/assets/pdf/fullScreen.svg"; -import { Tooltip } from "antd"; -import { useIntl } from "react-intl"; -import { TaskIdProgress, TaskIdResItem } from "@/api/extract"; -import IconFont from "@/components/icon-font"; -import { CopyToClipboard } from "react-copy-to-clipboard"; -import { useEffect, useMemo, useRef, useState } from "react"; -import { message } from "antd"; -import { MD_PREVIEW_TYPE } from "@/types/extract-task-type"; -import CodeMirror from "@/components/code-mirror"; -import LatexRenderer from "../../components/latex-renderer"; -import { useParams } from "react-router-dom"; -interface IImageOriginViewerProps { - fullScreen?: boolean; - setFullScreen?: (val: boolean) => void; - taskInfo: TaskIdProgress & TaskIdResItem; -} - -const FormulaDetailRight = ({ - fullScreen, - setFullScreen, - taskInfo, -}: IImageOriginViewerProps) => { - const CONTROL_BAR_HEIGHT = 48; - const { formatMessage } = useIntl(); - const [displayType, setDisplayType] = useState(MD_PREVIEW_TYPE.preview); - const imageViewerRef = useRef(); - const formulaType = taskInfo?.type; - const params = useParams(); - const jobID = params?.jobID; - const formulaLateX = useMemo(() => { - return taskInfo?.content?.map((i: any) => i?.latex + "\\\\\n").join(""); - }, [taskInfo?.content]); - - const handleCopy = () => {}; - - const menuList = [ - { - name: formatMessage({ id: "extractor.markdown.preview" }), - code: MD_PREVIEW_TYPE.preview, - }, - { - name: formatMessage({ id: "extractor.markdown.code" }), - code: MD_PREVIEW_TYPE.code, - }, - ]; - - useEffect(() => { - imageViewerRef?.current?.updateScaleAndPosition(); - }, [fullScreen]); - - useEffect(() => { - setDisplayType(MD_PREVIEW_TYPE.preview); - }, [jobID]); - - return ( -
    -
    - {formulaType === "formula-extract" && ( -
      - {menuList.map((item) => ( -
    • setDisplayType(item.code)} - > - {item.name} -
    • - ))} -
    - )} - - - setFullScreen?.(!fullScreen)} - > - {!fullScreen ? ( - - ) : ( - - )} - - - {formulaType === "formula-extract" && ( -
    - - - { - message.success(formatMessage({ id: "common.copySuccess" })); - }} - > - - handleCopy()} - /> - - - -
    - )} -
    - {displayType === MD_PREVIEW_TYPE.preview ? ( - formulaType === "formula-extract" ? ( -
    - -
    - ) : ( - - ) - ) : ( -
    - -
    - )} -
    - ); -}; - -export default FormulaDetailRight; diff --git a/projects/web/src/pages/extract/formula/formula-detail/index.tsx b/projects/web/src/pages/extract/formula/formula-detail/index.tsx deleted file mode 100644 index 4e07141e6185805252981dcd7ef02816f36e481d..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/formula/formula-detail/index.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import cls from "classnames"; - -import { useEffect, useState } from "react"; - -import LoadingIcon from "../../components/loading-icon"; - -import { SubmitRes } from "@/api/extract"; -import emptySvg from "@/assets/svg/empty.svg"; - -import { FormattedMessage } from "react-intl"; - -import FormulaDetailLeft from "../formula-detail-left"; -import FormulaDetailRight from "../formula-detail-right"; - -import { useIntl } from "react-intl"; -import { ExtractorUploadButton } from "../../components/pdf-upload-button"; -import useExtractorJobProgress from "@/store/jobProgress"; -interface IPdfExtractionProps { - setUploadShow: (bool: boolean) => void; - className?: string; -} - -const FormulaDetail = ({ className = "" }: IPdfExtractionProps) => { - const { - taskInfo, - queueLoading, - interfaceError: compileError, - refreshQueue, - jobID, - } = useExtractorJobProgress(); - - const [fullScreen, setFullScreen] = useState(false); - const { formatMessage } = useIntl(); - - const isQueueAndExtract = queueLoading; - const hiddenQueuePage = !isQueueAndExtract ? "opacity-0 " : ""; - const hiddenResultPage = isQueueAndExtract ? "z-[-1] opacity-0" : ""; - - const getLayoutClassName = (_fullScreen?: boolean) => { - return { - left: _fullScreen ? "w-0 overflow-hidden" : "w-[50%] max-w-[50%]", - right: _fullScreen ? "w-full " : "w-[50%] max-w-[50%]", - }; - }; - - const afterUploadSuccess = (data: SubmitRes) => { - refreshQueue(); - }; - const afterAsyncCheck = () => { - return Promise.resolve(true); - }; - - useEffect(() => { - setFullScreen(false); - }, [jobID]); - - return ( - <> -
    - - -
    - {taskInfo?.rank > 1 ? ( - - ) : taskInfo.state === "done" || taskInfo?.state === "unknown" ? ( - formatMessage({ - id: "extractor.common.loading", - }) - ) : ( - formatMessage({ - id: "extractor.common.extracting", - }) - )} -
    -
    - -
    - {!compileError ? ( -
    -
    - -
    -
    - -
    -
    - ) : ( -
    - emptySvg - - {formatMessage({ - id: "extractor.failed", - })} - - - {formatMessage({ - id: "extractor.button.reUpload", - })} - - } - /> -
    - )} -
    - - ); -}; - -export default FormulaDetail; diff --git a/projects/web/src/pages/extract/formula/formula-popover/index.module.scss b/projects/web/src/pages/extract/formula/formula-popover/index.module.scss deleted file mode 100644 index 38229f8ee306ef143dcc751a33dfa3b44236e04e..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/formula/formula-popover/index.module.scss +++ /dev/null @@ -1,18 +0,0 @@ -.formulaPopover { - :global { - - .ant-popover-content, .ant-popover-inner { - border-radius: 12px !important; - overflow: hidden; - box-shadow: 0px 8px 26px 0px rgba(0, 0, 0, 0.12); - } - - .ant-popover-inner-content { - padding: 24px !important; - } - - .ant-popover-arrow { - display: none !important; - } - } -} diff --git a/projects/web/src/pages/extract/formula/formula-popover/index.tsx b/projects/web/src/pages/extract/formula/formula-popover/index.tsx deleted file mode 100644 index ac8e2b638475e1bd72751b3aa2e41e97f7f739a0..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/formula/formula-popover/index.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { ReactNode } from "react"; -import { Popover } from "antd"; -import IconFont from "@/components/icon-font"; -import { useIntl } from "react-intl"; -import style from "./index.module.scss"; - -interface IFormulaPopoverProps { - type: string; - text?: string | ReactNode; -} - -const FormulaPopover = ({ type, text }: IFormulaPopoverProps) => { - const { formatMessage } = useIntl(); - const content = ( -
    - {/* 顺序反了 */} - {formatMessage({ - id: - type === "detect" - ? "extractor.formula.popover.extract" - : "extractor.formula.popover.detect", - })} - formula-popover -
    - ); - return ( - - - - {text} - - - - - ); -}; - -export default FormulaPopover; diff --git a/projects/web/src/pages/extract/formula/formula-upload/index.module.scss b/projects/web/src/pages/extract/formula/formula-upload/index.module.scss deleted file mode 100644 index bb63f363bbef96a299354b7cb3496e45e6612022..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/formula/formula-upload/index.module.scss +++ /dev/null @@ -1,87 +0,0 @@ - - -.uploadText { - font-feature-settings: 'liga' off, 'clig' off; - font-family: "PingFang SC"; - font-size: 18px; - font-style: normal; - font-weight: 600; - line-height: 24px; /* 133.333% */ - background: linear-gradient(107deg, #38A0FF -24.14%, #0D53DE 30.09%, #5246FF 86.61%); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; -} - -.uploadDescText { - font-size: 13px; - line-height: 20px; - font-weight: 400; - background: linear-gradient(107deg, rgba(18,19,22,0.6) -24.14%, rgba(18,19,22,0.6) 100.09% ); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - margin-bottom: 1rem; - margin-top: 0.5rem; -} - -.linearText { - font-size: 13px; - line-height: 20px; - font-weight: 400; - background: linear-gradient(107deg, rgba(18,19,22,0.6) -24.14%, rgba(18,19,22,0.6) 100.09% ); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - - &-item { - font-weight: 400; - font-size: 13px; - line-height: 20px; - margin-right: 1rem; - background: linear-gradient(107deg, #38A0FF -24.14%, #0D53DE 30.09%, #5246FF 86.61%); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - &:hover { - background: #3477EB; - background: linear-gradient(107deg, #3477EB -24.14%, #3477EB 100.09% ); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - } - } -} - -.uploadSection { - border-radius: 12px; - border: 1px dashed var(---Brand1-6, #0D53DE); - background: linear-gradient(180deg, rgba(92, 147, 255, 0.10) -130.23%, rgba(255, 255, 255, 1) 83.57%); - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - filter: blur(0px); - height: 280px !important; - width: 600px !important; - - &:hover { - background: linear-gradient(180deg, rgb(245, 248, 255) -130.23%, rgb(245, 248, 255) 83.57%); - } -} - -.textBtn { - background-image: none !important; - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background: linear-gradient(111deg, #0D53DE -21.44%, #5246FF 102%) !important; - background-clip: text !important; - -webkit-background-clip: text !important; - -webkit-text-fill-color: transparent !important; - height: 1.5rem !important; - font-weight: 600; - height: 280px !important; - width: 600px !important; - overflow: hidden; -} diff --git a/projects/web/src/pages/extract/formula/formula-upload/index.tsx b/projects/web/src/pages/extract/formula/formula-upload/index.tsx deleted file mode 100644 index bbf98c2e63d4ec91347ec736357b5bbe48172be1..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/formula/formula-upload/index.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import { useIntl } from "react-intl"; -import IconFont from "@/components/icon-font"; -import { useState } from "react"; -import cls from "classnames"; -import { ExtractorUploadButton } from "../../components/pdf-upload-button"; -import UploadBg from "@/assets/imgs/online.experience/file-upload-bg.svg"; -import style from "./index.module.scss"; -import { SubmitRes } from "@/api/extract"; -import { ADD_TASK_LIST } from "@/constant/event"; -import { FORMULA_TYPE } from "@/types/extract-task-type"; -import { useNavigate } from "react-router-dom"; - -const FORMULA_ITEM_LIST = [ - { - type: FORMULA_TYPE.detect, - [`zh-CN-name`]: "公式检测", - [`en-US-name`]: "Formula Detection", - }, - { - type: FORMULA_TYPE.extract, - [`zh-CN-name`]: "公式识别", - [`en-US-name`]: "Formula Recognition", - }, -]; - -const FormulaUpload = () => { - const navigate = useNavigate(); - const { formatMessage, locale } = useIntl(); - const [formulaType, setFormulaType] = useState(FORMULA_TYPE.detect); - - const afterUploadSuccess = (data: SubmitRes) => { - navigate(`/OpenSourceTools/Extractor/formula/${data?.id}`); - setTimeout(() => { - document.dispatchEvent( - new CustomEvent(ADD_TASK_LIST, { - detail: data, - }) - ); - }, 10); - }; - const afterAsyncCheck = () => { - return Promise.resolve(true); - }; - - return ( -
    -
    navigate("/OpenSourceTools/Extractor")} - > - - {formatMessage({ id: "extractor.home" })} -
    -
    -
    - {FORMULA_ITEM_LIST.map((i) => { - return ( - setFormulaType(i?.type)} - className={cls( - "relative text-[1.5rem] text-[#121316] cursor-pointer mx-[1.5rem]", - formulaType === i?.type && "!text-[#0D53DE] font-semibold" - )} - > - {i?.[`${locale || "zh-CN"}-name` as "en-US-name"]} - {formulaType === i?.type && ( - - )} - - ); - })} -
    - -
    - {formatMessage({ - id: - formulaType === "extract" - ? "extractor.formula.title2" - : "extractor.formula.title", - })} -
    - - - - - {formatMessage({ id: "extractor.formula.upload.text" })} - - - {formatMessage({ id: "extractor.formula.upload.accept" })} - -
    - - {formatMessage({ - id: "extractor.formula.upload.try", - })} - -
    -
    - } - > -
    -
    - {formatMessage({ - id: "extractor.law", - })} -
    - - ); -}; - -export default FormulaUpload; diff --git a/projects/web/src/pages/extract/formula/index.module.scss b/projects/web/src/pages/extract/formula/index.module.scss deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/projects/web/src/pages/extract/formula/index.tsx b/projects/web/src/pages/extract/formula/index.tsx deleted file mode 100644 index 8f4e0e3c38e84de90cd223d9b0530b01fc30fc99..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/formula/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Outlet } from "react-router-dom"; - -const Formula = () => { - return ( -
    - -
    - ); -}; - -export default Formula; diff --git a/projects/web/src/pages/extract/index.module.scss b/projects/web/src/pages/extract/index.module.scss deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/projects/web/src/pages/extract/index.tsx b/projects/web/src/pages/extract/index.tsx deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/projects/web/src/pages/extract/table/index.tsx b/projects/web/src/pages/extract/table/index.tsx deleted file mode 100644 index b16962f17d8cfd761ab08d7940abbcdbbd51d466..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/table/index.tsx +++ /dev/null @@ -1,5 +0,0 @@ -const ExtractorTable = () => { - return <>ExtractorTable; -}; - -export default ExtractorTable; diff --git a/projects/web/src/pages/extract/table/table-detail/index.tsx b/projects/web/src/pages/extract/table/table-detail/index.tsx deleted file mode 100644 index db192bc26e1167e5a2146fa1393685293ac723d5..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/extract/table/table-detail/index.tsx +++ /dev/null @@ -1,5 +0,0 @@ -const TableDetail = () => { - return <>TableDetail; -}; - -export default TableDetail; diff --git a/projects/web/src/pages/home.module.scss b/projects/web/src/pages/home.module.scss deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/projects/web/src/pages/home.tsx b/projects/web/src/pages/home.tsx deleted file mode 100644 index fa0309a9c22eb5c5979447dd1493b648f4670a4b..0000000000000000000000000000000000000000 --- a/projects/web/src/pages/home.tsx +++ /dev/null @@ -1,75 +0,0 @@ -"use client"; - -import ErrorBoundary from "@/components/error-boundary"; -import styles from "./home.module.scss"; -import { SlotID, Path } from "@/constant/route"; -import { - BrowserRouter, - Routes, - Route, - Outlet, - Navigate, - useLocation, - HashRouter, -} from "react-router-dom"; -import { ExtractorSide } from "./extract-side"; -import { LanguageProvider } from "@/context/language-provider"; -import PDFUpload from "@/pages/extract/components/pdf-upload"; -import PDFExtractionJob from "@/pages/extract/components/pdf-extraction"; - -export function WindowContent() { - const location = useLocation(); - const isHome = location.pathname === Path.Home; - - return ( - <> - -
    - -
    - - ); -} - -function Screen() { - const renderContent = () => { - return ( -
    - - }> - } - /> - } - /> - } - /> - } - /> - - -
    - ); - }; - - return <>{renderContent()}; -} - -export function Home() { - return ( - - - - - - - - ); -} diff --git a/projects/web/src/routes/index.tsx b/projects/web/src/routes/index.tsx deleted file mode 100644 index 6bdb0b06391483fca2ecfe3ef87080a946e0ba1c..0000000000000000000000000000000000000000 --- a/projects/web/src/routes/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Routes, Route } from "react-router-dom"; -import PDFUpload from "@/pages/extract/components/pdf-upload"; -import PDFExtractionJob from "@/pages/extract/components/pdf-extraction"; - -function AppRoutes() { - return ( - <> - } /> - } - /> - - ); -} - -export default AppRoutes; diff --git a/projects/web/src/store/jobProgress.ts b/projects/web/src/store/jobProgress.ts deleted file mode 100644 index bb08d694753f7ecf9ca1b7560eb390afdd207c93..0000000000000000000000000000000000000000 --- a/projects/web/src/store/jobProgress.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { - getExtractTaskIdProgress, - getPdfExtractQueue, - TaskIdResItem, -} from "@/api/extract"; -import { create } from "zustand"; -import { useCallback, useEffect, useRef, useState } from "react"; -import { useParams } from "react-router-dom"; -import { UPDATE_TASK_LIST } from "@/constant/event"; -import { useQuery } from "@tanstack/react-query"; - -interface ExtractorState { - taskInfo: TaskIdResItem; - queueLoading: boolean | null; - interfaceError: boolean; - setTaskInfo: (taskInfo: TaskIdResItem) => void; - setQueueLoading: (loading: boolean | null) => void; - setInterfaceError: (error: boolean) => void; -} - -const defaultTaskInfo: TaskIdResItem = { - id: 0, - rank: 0, - state: "pending", - url: "", - type: "unknown", - queues: -1, -}; - -const useExtractorStore = create((set) => ({ - taskInfo: defaultTaskInfo, - queueLoading: null, - interfaceError: false, - setTaskInfo: (taskInfo: any) => set({ taskInfo }), - setQueueLoading: (loading) => set({ queueLoading: loading }), - setInterfaceError: (error) => set({ interfaceError: error }), -})); - -export const useJobExtraction = () => { - const { jobID } = useParams<{ jobID: string }>(); - const { - setTaskInfo, - setQueueLoading, - queueLoading, - taskInfo, - interfaceError, - setInterfaceError, - } = useExtractorStore(); - - const timeoutRef = useRef(null); - const [isPolling, setIsPolling] = useState(true); - - const stopTaskLoading = () => { - setQueueLoading(false); - }; - - // Query for task progress - const taskProgressQuery = useQuery({ - queryKey: ["taskProgress", jobID], - queryFn: () => { - setQueueLoading(true); - setIsPolling(true); - return getExtractTaskIdProgress(jobID!) - .then((res) => { - if (res?.state === "done" || res?.state === "failed") { - stopTaskLoading(); - - document.dispatchEvent( - new CustomEvent("UPDATE_TASK_LIST", { - detail: { state: res.state, id: jobID }, - }) - ); - } - if (res) { - setTaskInfo(res); - } - - return res; - }) - .catch(() => { - stopTaskLoading(); - setTaskInfo({ state: "failed" }); - }); - }, - enabled: false, - }); - - // Query for queue status - const queueStatusQuery = useQuery({ - queryKey: ["queueStatus", jobID], - queryFn: async () => { - setQueueLoading(true); - const response = await getPdfExtractQueue(jobID).then((res) => { - // setTaskInfo({ rand: "failed" }); - - if (res) { - const targetPendingRunningJob = res?.filter( - (i) => String(i.id) === jobID - )?.[0]; - - if (targetPendingRunningJob) { - setTaskInfo(targetPendingRunningJob); - } else { - setIsPolling(false); - setQueueLoading(false); - getExtractTaskIdProgress(jobID!).then((res) => { - setTaskInfo(res as any); - }); - } - } - - return res; - }); - return response; - }, - - enabled: - isPolling && - (taskProgressQuery?.data?.state === "running" || - taskProgressQuery?.data?.state === "pending"), - refetchInterval: 2000, // Poll every 2 seconds - }); - - useEffect(() => { - if (taskProgressQuery.data?.state === "done") { - stopTaskLoading(); - setInterfaceError(false); - setIsPolling(false); - if (timeoutRef.current) { - clearTimeout(timeoutRef.current); - } else { - timeoutRef.current = setTimeout(() => { - document.dispatchEvent( - new CustomEvent(UPDATE_TASK_LIST, { - detail: { state: "done", jobID }, - }) - ); - }, 10); - } - } else if (taskProgressQuery.data?.state === "failed") { - stopTaskLoading(); - setInterfaceError(true); - - setIsPolling(false); - - if (timeoutRef.current) { - clearTimeout(timeoutRef.current); - } else { - timeoutRef.current = setTimeout(() => { - document.dispatchEvent( - new CustomEvent(UPDATE_TASK_LIST, { - detail: { state: "failed", jobID }, - }) - ); - }, 10); - } - } - // TIP这里得用taskInfo - }, [taskProgressQuery.data]); - - const refreshQueue = () => { - // stop last ID polling - setIsPolling(false); - setTaskInfo(defaultTaskInfo); - taskProgressQuery.refetch(); - }; - - useEffect(() => { - if (jobID) { - // stop last ID polling d - setTaskInfo(defaultTaskInfo); - taskProgressQuery.refetch(); - } - }, [jobID]); - - return { - taskInfo: taskInfo, - isLoading: queueLoading, - isError: - interfaceError || taskProgressQuery.isError || queueStatusQuery.isError, - refreshQueue, - }; -}; diff --git a/projects/web/src/store/languageStore.ts b/projects/web/src/store/languageStore.ts deleted file mode 100644 index 42f20dcb07918b76399059b80daca08babd7f74d..0000000000000000000000000000000000000000 --- a/projects/web/src/store/languageStore.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { create } from "zustand"; -import { Language } from "@/constant"; -import { LOCALE_STORAGE_KEY } from "@/constant/storage"; - -type LanguageType = (typeof Language)[keyof typeof Language]; - -type LanguageStore = { - language: LanguageType; - setLanguage: (language: LanguageType) => void; - toggleLanguage: () => void; -}; - -const getInitialLanguage = (): LanguageType => { - // Try to get language setting from localStorage - const savedLanguage = localStorage.getItem( - LOCALE_STORAGE_KEY - ) as LanguageType; - if (savedLanguage && Object.values(Language).includes(savedLanguage)) { - return savedLanguage; - } - - // If no valid language setting in localStorage, try to get browser language - const browserLanguage = navigator.language.toLowerCase(); - if (browserLanguage.startsWith("zh")) { - return Language.ZH_CN; - } else if (browserLanguage.startsWith("en")) { - return Language.EN_US; - } - - // Default to Chinese - return Language.ZH_CN; -}; - -export const useLanguageStore = create((set) => ({ - language: getInitialLanguage(), - setLanguage: (language) => { - localStorage.setItem(LOCALE_STORAGE_KEY, language); - set({ language }); - }, - toggleLanguage: () => - set((state) => { - const newLanguage = - state.language === Language.ZH_CN ? Language.EN_US : Language.ZH_CN; - localStorage.setItem(LOCALE_STORAGE_KEY, newLanguage); - return { language: newLanguage }; - }), -})); diff --git a/projects/web/src/store/mdStore.ts b/projects/web/src/store/mdStore.ts deleted file mode 100644 index 2368b27491a114eb65a79d2371dd4997a83edba8..0000000000000000000000000000000000000000 --- a/projects/web/src/store/mdStore.ts +++ /dev/null @@ -1,250 +0,0 @@ -// mdStore.ts -import { create } from "zustand"; -import axios from "axios"; -import { updateMarkdownContent, UpdateMarkdownRequest } from "@/api/extract"; // 确保路径正确 - -interface MdContent { - content: string; - isLoading: boolean; -} - -type AnchorType = - | "span" - | "div" - | "comment" - | "data-attribute" - | "hr" - | "mark" - | "p"; - -interface AnchorOptions { - type: AnchorType; - prefix?: string; - style?: string; - className?: string; - customAttributes?: Record; -} - -const defaultAnchorOptions: AnchorOptions = { - type: "span", - prefix: "md-anchor-", - style: "display:none;", - className: "", - customAttributes: {}, -}; - -interface MdState { - mdContents: Record; - allMdContent: string; - allMdContentWithAnchor: string; - error: Error | null; - currentRequestId: number; - setMdUrlArr: (urls: string[]) => Promise; - getAllMdContent: (data: string[]) => string; - setAllMdContent: (val?: string) => void; - setAllMdContentWithAnchor: (val?: string) => void; - getContentWithAnchors: ( - data: string[], - options?: Partial - ) => string; - jumpToAnchor: (anchorId: string) => number; - reset: () => void; - updateMdContent: ( - fileKey: string, - pageNumber: string | number, - newContent: string - ) => Promise; -} - -const MAX_CONCURRENT_REQUESTS = 2; - -const initialState = { - mdContents: {}, - allMdContent: "", - allMdContentWithAnchor: "", - error: null, - currentRequestId: 0, -}; - -const useMdStore = create((set, get) => ({ - ...initialState, - - reset: () => { - set(initialState); - }, - - setAllMdContent: (value?: string) => { - set(() => ({ - allMdContent: value, - })); - }, - - setAllMdContentWithAnchor: (value?: string) => { - set(() => ({ - allMdContentWithAnchor: value, - })); - }, - - setMdUrlArr: async (urls: string[]) => { - const requestId = get().currentRequestId + 1; - set((state) => ({ currentRequestId: requestId, error: null })); - - const fetchContent = async (url: string): Promise<[string, string]> => { - try { - const response = await axios.get(url); - return [url, response.data]; - } catch (error) { - if (get().currentRequestId === requestId) { - set((state) => ({ error: error as Error })); - } - return [url, ""]; - } - }; - - const fetchWithConcurrency = async ( - urls: string[] - ): Promise<[string, string][]> => { - const queue = [...urls]; - const results: [string, string][] = []; - const inProgress = new Set>(); - - while (queue.length > 0 || inProgress.size > 0) { - while (inProgress.size < MAX_CONCURRENT_REQUESTS && queue.length > 0) { - const url = queue.shift()!; - const promise = fetchContent(url); - inProgress.add(promise); - promise.then((result) => { - results.push(result); - inProgress.delete(promise); - }); - } - if (inProgress.size > 0) { - await Promise.race(inProgress); - } - } - - return results; - }; - - const results = await fetchWithConcurrency(urls); - - if (get().currentRequestId === requestId) { - const newMdContents: Record = {}; - results.forEach(([url, content]) => { - newMdContents[url] = { content, isLoading: false }; - }); - - set((state) => ({ - mdContents: newMdContents, - allMdContent: state.getAllMdContent(results.map((i) => i[1])), - allMdContentWithAnchor: state.getContentWithAnchors( - results.map((i) => i[1]) - ), - })); - } - }, - - getAllMdContent: (data) => { - return data?.join("\n\n"); - }, - - getContentWithAnchors: (data: string[], options?: Partial) => { - const opts = { ...defaultAnchorOptions, ...options }; - - const generateAnchorTag = (index: number) => { - const id = `${opts.prefix}${index}`; - const attributes = Object.entries(opts.customAttributes || {}) - .map(([key, value]) => `${key}="${value}"`) - .join(" "); - - switch (opts.type) { - case "span": - case "div": - case "mark": - case "p": - return `<${opts.type} id="${id}" style="${opts.style}" class="${opts.className}" ${attributes}>`; - case "comment": - return ``; - case "data-attribute": - return ``; - case "hr": - return `
    `; - default: - return ``; - } - }; - - return data - ?.map((content, index) => { - const anchorTag = generateAnchorTag(index); - return `${anchorTag}\n\n${content}`; - }) - .join("\n\n"); - }, - - jumpToAnchor: (anchorId: string) => { - const { mdContents } = get(); - const contentArray = Object.values(mdContents).map( - (content) => content.content - ); - let totalLength = 0; - for (let i = 0; i < contentArray.length; i++) { - if (anchorId === `md-anchor-${i}`) { - return totalLength; - } - totalLength += contentArray[i].length + 2; // +2 for "\n\n" - } - return -1; // Anchor not found - }, - - updateMdContent: async ( - fileKey: string, - pageNumber: string, - newContent: string - ) => { - try { - const params: UpdateMarkdownRequest = { - file_key: fileKey, - data: { - [pageNumber]: newContent, - }, - }; - - const result = await updateMarkdownContent(params); - - if (result && result.success) { - // 更新本地状态 - set((state) => { - const updatedMdContents = { ...state.mdContents }; - if (updatedMdContents[fileKey]) { - updatedMdContents[fileKey] = { - ...updatedMdContents[fileKey], - content: newContent, - }; - } - - // 重新计算 allMdContent 和 allMdContentWithAnchor - const contentArray = Object.values(updatedMdContents).map( - (content) => content.content - ); - const newAllMdContent = state.getAllMdContent(contentArray); - const newAllMdContentWithAnchor = - state.getContentWithAnchors(contentArray); - - return { - mdContents: updatedMdContents, - allMdContent: newAllMdContent, - allMdContentWithAnchor: newAllMdContentWithAnchor, - }; - }); - } else { - throw new Error("Failed to update Markdown content"); - } - } catch (error) { - set({ error: error as Error }); - throw error; - } - }, -})); - -export default useMdStore; diff --git a/projects/web/src/styles/variable.scss b/projects/web/src/styles/variable.scss deleted file mode 100644 index cfda77a1b03a6e2172355f87019b02d59c35b07f..0000000000000000000000000000000000000000 --- a/projects/web/src/styles/variable.scss +++ /dev/null @@ -1 +0,0 @@ -$page-min-witch: 1260px; \ No newline at end of file diff --git a/projects/web/src/types/extract-task-type.ts b/projects/web/src/types/extract-task-type.ts deleted file mode 100644 index 7a60eead0acad69ebe2fd163e0de75dfea15f907..0000000000000000000000000000000000000000 --- a/projects/web/src/types/extract-task-type.ts +++ /dev/null @@ -1,21 +0,0 @@ -export type ExtractTaskType = - | "pdf" - | "formula-detect" - | "formula-extract" - | "table-recogn"; - -export const EXTRACTOR_TYPE_LIST = { - table: "table", - formula: "formula", - pdf: "PDF", -}; - -export enum FORMULA_TYPE { - extract = "extract", - detect = "detect", -} - -export enum MD_PREVIEW_TYPE { - preview = "preview", - code = "code", -} diff --git a/projects/web/src/utils/download.ts b/projects/web/src/utils/download.ts deleted file mode 100644 index da00239165ced2892fe78dbc3fbffd88f4346fb0..0000000000000000000000000000000000000000 --- a/projects/web/src/utils/download.ts +++ /dev/null @@ -1,44 +0,0 @@ -export async function downloadFileUseAScript( - url: string, - filename?: string -): Promise { - try { - // 发起请求获取文件 - const response = await fetch(url); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - // 获取文件内容的 Blob - const blob = await response.blob(); - - // 创建一个 Blob URL - const blobUrl = window.URL.createObjectURL(blob); - - // 创建一个隐藏的元素 - const link = document.createElement("a"); - link.style.display = "none"; - link.href = blobUrl; - - // 设置下载的文件名 - const contentDisposition = response.headers.get("Content-Disposition"); - const fileName = - filename || - (contentDisposition - ? contentDisposition.split("filename=")[1].replace(/['"]/g, "") - : url.split("/").pop() || "download"); - - link.download = fileName; - - // 将链接添加到文档中并触发点击 - document.body.appendChild(link); - link.click(); - - // 清理 - document.body.removeChild(link); - window.URL.revokeObjectURL(blobUrl); - } catch (error) { - console.error("Download failed:", error); - } -} diff --git a/projects/web/src/utils/locale.ts b/projects/web/src/utils/locale.ts deleted file mode 100644 index 0f96be9f936898e36064a77e66b031eebaaa7ff5..0000000000000000000000000000000000000000 --- a/projects/web/src/utils/locale.ts +++ /dev/null @@ -1,16 +0,0 @@ -export enum ELocal { - "zh-CN" = "zh-CN", - "en-US" = "en-US", -} -export const locale: { [key: string]: string } = { - [ELocal["zh-CN"]]: "中文", - [ELocal["en-US"]]: "En", -}; -export const localeName: { [key: string]: string } = { - [ELocal["zh-CN"]]: "nameZh", - [ELocal["en-US"]]: "name", -}; - -export const getLocale = () => { - return localStorage.getItem("umi_locale") || ELocal["zh-CN"]; -}; diff --git a/projects/web/src/utils/windowOpen.ts b/projects/web/src/utils/windowOpen.ts deleted file mode 100644 index 805881d34f63b27f80c2d07f75f93ee44a5c5825..0000000000000000000000000000000000000000 --- a/projects/web/src/utils/windowOpen.ts +++ /dev/null @@ -1,24 +0,0 @@ -export const windowOpen = ( - url: string, - type?: "_blank" | "_parent" | "_self" | "_top" -) => { - const a = document.createElement("a"); - a.setAttribute("href", url); - a.setAttribute("target", type || "_blank"); - a.rel = "noreferrer"; - document.body.appendChild(a); - if (a.click) { - a?.click(); - } else { - try { - let evt = new Event("click", { - bubbles: false, - cancelable: true, - }); - a.dispatchEvent(evt); - } catch (error) { - window.open(url, type || "_blank"); - } - } - document.body.removeChild(a); -}; diff --git a/projects/web/src/vite-env.d.ts b/projects/web/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a0061d6e6e1f271b21da95423b448b32..0000000000000000000000000000000000000000 --- a/projects/web/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/projects/web/tailwind.config.js b/projects/web/tailwind.config.js deleted file mode 100644 index 930f83d968b259dfa8cad3ef8235168a70956198..0000000000000000000000000000000000000000 --- a/projects/web/tailwind.config.js +++ /dev/null @@ -1,35 +0,0 @@ -module.exports = { - content: [ - "./src/**/*.{js,jsx,ts,tsx}", - ], - plugins: [ - function ({ addUtilities }) { - const newUtilities = { - '.scrollbar-thin': { - scrollbarWidth: '2px', - // scrollbarColor: 'rgba(13, 83, 222, 1)', - '&::-webkit-scrollbar': { - width: '6px', - height: '6px' - }, - '&::-webkit-scrollbar-track': { - backgroundColor: 'transparent' - }, - '&::-webkit-scrollbar-thumb': { - // backgroundColor: 'rgba(13, 83, 222, 0.01)', - borderRadius: '20px', - border: '3px solid transparent' - }, - '&:hover::-webkit-scrollbar-thumb': { - width: '6px', - border: '3px solid rgb(229 231 235)', - backgroundColor: 'rgb(229 231 235)' - } - } - // 你可以添加更多自定义的滚动条样式 - }; - addUtilities(newUtilities, ['responsive', 'hover']); - }, - ], - // ...other configurations -} \ No newline at end of file diff --git a/projects/web/tsconfig.app.json b/projects/web/tsconfig.app.json deleted file mode 100644 index 22aefb247f4d3a606a05a0e4b4c6fe0b4e61139a..0000000000000000000000000000000000000000 --- a/projects/web/tsconfig.app.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["src"] -} diff --git a/projects/web/tsconfig.json b/projects/web/tsconfig.json deleted file mode 100644 index 44faff780518f3eaae6623d051df2c2b62c3857b..0000000000000000000000000000000000000000 --- a/projects/web/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "files": [], - "compilerOptions": { - // ... other options ... - "types": ["node"] - }, - "references": [ - { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" } - ] -} diff --git a/projects/web/tsconfig.node.json b/projects/web/tsconfig.node.json deleted file mode 100644 index 0d3d71446a455c5f997e3cffb25099dab0f74a9b..0000000000000000000000000000000000000000 --- a/projects/web/tsconfig.node.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2023"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["vite.config.ts"] -} diff --git a/projects/web/vite.config.ts b/projects/web/vite.config.ts deleted file mode 100644 index 263d7adbf0cb819090ca01c04d00062ce10e837b..0000000000000000000000000000000000000000 --- a/projects/web/vite.config.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; -import path from "path"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react()], - server: { - proxy: { - "/api": { - target: "http://localhost:5559", - changeOrigin: true, - }, - }, - }, - css: { - modules: { - localsConvention: "camelCaseOnly", // transfer kebab-case to camelCase - scopeBehaviour: "local", - generateScopedName: "[name]__[local]___[hash:base64:5]", - }, - }, - publicDir: "public", - resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, - }, -}); diff --git a/projects/web_demo/README.md b/projects/web_demo/README.md deleted file mode 100644 index cd4b11de204bee1e440ac9e1946f929c6ab673f6..0000000000000000000000000000000000000000 --- a/projects/web_demo/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# MinerU Local web_demo -## Feature Overview -

    - -

    - -- Supports uploading PDFs and calling MinerU for processing - -- Supports online editing of the Markdown results parsed by MinerU - -- Supports viewing of historical tasks - -## Installation and Deployment - -0. MinerU Installation and Deployment - - -``` -# The service depends on mineru, please ensure mineru is installed first -``` - -1. Package the front-end interface - -```bash -# First, navigate to the front-end directory -cd projects/web - -# Modify the configuration -# Change the IP in the target field of the file vite.config.ts to your own computer's IP - -# Build the front-end project -npm install -g yarn -yarn install -yarn build -``` - -2. Install service dependencies - -```bash -# First, navigate to the back-end directory -cd projects/web_demo -# Install dependencies -pip3 install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple -``` - -3. Start the service - -```bash -# Navigate to the program directory -cd projects/web_demo/web_demo -# Start the service -python3 app.py or python app.py -# Access the interface by visiting the started address in the browser -``` - -ps:API documentation - -``` -https://apifox.com/apidoc/shared-b8eda098-ab9c-4cb3-9432-62be9be9c6f7 -``` diff --git a/projects/web_demo/README_zh-CN.md b/projects/web_demo/README_zh-CN.md deleted file mode 100644 index d9ee597b9665c9b8fb6f589358db61afb34ba58c..0000000000000000000000000000000000000000 --- a/projects/web_demo/README_zh-CN.md +++ /dev/null @@ -1,59 +0,0 @@ -# MinerU本地web_demo -## 功能简介 -

    - -

    - -- 支持上传pdf,并调用MinerU进行处理 - -- 支持对MinerU解析的Markdown结果进行在线修改 - -- 支持查看历史任务 - -## 安装部署 - -0. MinerU安装部署 - -``` -# 服务依赖MinerU,请先确保MinerU已安装 -``` - -1. 打包前端界面 - -```bash -# 先进入前端目录 -cd projects/web - -# 修改配置 -# 将文件vite.config.ts中的target中的IP更改为自己电脑IP - -# 打包前端项目 -npm install -g yarn -yarn install -yarn build -``` - -2. 安装服务依赖 - -```bash -# 先进入后端目录 -cd projects/web_demo -# 安装依赖 -pip3 install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple -``` - -3. 启动服务 - -```bash -# 进入程序目录 -cd projects/web_demo/web_demo -# 启动服务 -python3 app.py 或者 python app.py -# 在浏览器访问启动的地址即可访问界面 -``` - -ps:接口文档 - -``` -https://apifox.com/apidoc/shared-b8eda098-ab9c-4cb3-9432-62be9be9c6f7 -``` diff --git a/projects/web_demo/images/web_demo_1.png b/projects/web_demo/images/web_demo_1.png deleted file mode 100644 index 2d903adec1f6fb9e3c1e39a8b620653faa5ac6b6..0000000000000000000000000000000000000000 Binary files a/projects/web_demo/images/web_demo_1.png and /dev/null differ diff --git a/projects/web_demo/poetry.lock b/projects/web_demo/poetry.lock deleted file mode 100644 index b9706f230f443b5c30f410964a037c3fed405a6c..0000000000000000000000000000000000000000 --- a/projects/web_demo/poetry.lock +++ /dev/null @@ -1,687 +0,0 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. - -[[package]] -name = "alembic" -version = "1.13.2" -description = "A database migration tool for SQLAlchemy." -optional = false -python-versions = ">=3.8" -files = [ - {file = "alembic-1.13.2-py3-none-any.whl", hash = "sha256:6b8733129a6224a9a711e17c99b08462dbf7cc9670ba8f2e2ae9af860ceb1953"}, - {file = "alembic-1.13.2.tar.gz", hash = "sha256:1ff0ae32975f4fd96028c39ed9bb3c867fe3af956bd7bb37343b54c9fe7445ef"}, -] - -[package.dependencies] -Mako = "*" -SQLAlchemy = ">=1.3.0" -typing-extensions = ">=4" - -[package.extras] -tz = ["backports.zoneinfo"] - -[[package]] -name = "aniso8601" -version = "9.0.1" -description = "A library for parsing ISO 8601 strings." -optional = false -python-versions = "*" -files = [ - {file = "aniso8601-9.0.1-py2.py3-none-any.whl", hash = "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f"}, - {file = "aniso8601-9.0.1.tar.gz", hash = "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"}, -] - -[package.extras] -dev = ["black", "coverage", "isort", "pre-commit", "pyenchant", "pylint"] - -[[package]] -name = "blinker" -version = "1.8.2" -description = "Fast, simple object-to-object and broadcast signaling" -optional = false -python-versions = ">=3.8" -files = [ - {file = "blinker-1.8.2-py3-none-any.whl", hash = "sha256:1779309f71bf239144b9399d06ae925637cf6634cf6bd131104184531bf67c01"}, - {file = "blinker-1.8.2.tar.gz", hash = "sha256:8f77b09d3bf7c795e969e9486f39c2c5e9c39d4ee07424be2bc594ece9642d83"}, -] - -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "flask" -version = "3.0.3" -description = "A simple framework for building complex web applications." -optional = false -python-versions = ">=3.8" -files = [ - {file = "flask-3.0.3-py3-none-any.whl", hash = "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3"}, - {file = "flask-3.0.3.tar.gz", hash = "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842"}, -] - -[package.dependencies] -blinker = ">=1.6.2" -click = ">=8.1.3" -itsdangerous = ">=2.1.2" -Jinja2 = ">=3.1.2" -Werkzeug = ">=3.0.0" - -[package.extras] -async = ["asgiref (>=3.2)"] -dotenv = ["python-dotenv"] - -[[package]] -name = "flask-cors" -version = "5.0.0" -description = "A Flask extension adding a decorator for CORS support" -optional = false -python-versions = "*" -files = [ - {file = "Flask_Cors-5.0.0-py2.py3-none-any.whl", hash = "sha256:b9e307d082a9261c100d8fb0ba909eec6a228ed1b60a8315fd85f783d61910bc"}, - {file = "flask_cors-5.0.0.tar.gz", hash = "sha256:5aadb4b950c4e93745034594d9f3ea6591f734bb3662e16e255ffbf5e89c88ef"}, -] - -[package.dependencies] -Flask = ">=0.9" - -[[package]] -name = "flask-jwt-extended" -version = "4.6.0" -description = "Extended JWT integration with Flask" -optional = false -python-versions = ">=3.7,<4" -files = [ - {file = "Flask-JWT-Extended-4.6.0.tar.gz", hash = "sha256:9215d05a9413d3855764bcd67035e75819d23af2fafb6b55197eb5a3313fdfb2"}, - {file = "Flask_JWT_Extended-4.6.0-py2.py3-none-any.whl", hash = "sha256:63a28fc9731bcc6c4b8815b6f954b5904caa534fc2ae9b93b1d3ef12930dca95"}, -] - -[package.dependencies] -Flask = ">=2.0,<4.0" -PyJWT = ">=2.0,<3.0" -Werkzeug = ">=0.14" - -[package.extras] -asymmetric-crypto = ["cryptography (>=3.3.1)"] - -[[package]] -name = "flask-marshmallow" -version = "1.2.1" -description = "Flask + marshmallow for beautiful APIs" -optional = false -python-versions = ">=3.8" -files = [ - {file = "flask_marshmallow-1.2.1-py3-none-any.whl", hash = "sha256:10b5048ecfaa26f7c8d0aed7d81083164450e6be8e81c04b3d4a586b3f7b6678"}, - {file = "flask_marshmallow-1.2.1.tar.gz", hash = "sha256:00ee96399ed664963afff3b5d6ee518640b0f91dbc2aace2b5abcf32f40ef23a"}, -] - -[package.dependencies] -Flask = ">=2.2" -marshmallow = ">=3.0.0" - -[package.extras] -dev = ["flask-marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"] -docs = ["Sphinx (==7.2.6)", "marshmallow-sqlalchemy (>=0.19.0)", "sphinx-issues (==4.0.0)"] -sqlalchemy = ["flask-sqlalchemy (>=3.0.0)", "marshmallow-sqlalchemy (>=0.29.0)"] -tests = ["flask-marshmallow[sqlalchemy]", "pytest"] - -[[package]] -name = "flask-migrate" -version = "4.0.7" -description = "SQLAlchemy database migrations for Flask applications using Alembic." -optional = false -python-versions = ">=3.6" -files = [ - {file = "Flask-Migrate-4.0.7.tar.gz", hash = "sha256:dff7dd25113c210b069af280ea713b883f3840c1e3455274745d7355778c8622"}, - {file = "Flask_Migrate-4.0.7-py3-none-any.whl", hash = "sha256:5c532be17e7b43a223b7500d620edae33795df27c75811ddf32560f7d48ec617"}, -] - -[package.dependencies] -alembic = ">=1.9.0" -Flask = ">=0.9" -Flask-SQLAlchemy = ">=1.0" - -[[package]] -name = "flask-restful" -version = "0.3.10" -description = "Simple framework for creating REST APIs" -optional = false -python-versions = "*" -files = [ - {file = "Flask-RESTful-0.3.10.tar.gz", hash = "sha256:fe4af2ef0027df8f9b4f797aba20c5566801b6ade995ac63b588abf1a59cec37"}, - {file = "Flask_RESTful-0.3.10-py2.py3-none-any.whl", hash = "sha256:1cf93c535172f112e080b0d4503a8d15f93a48c88bdd36dd87269bdaf405051b"}, -] - -[package.dependencies] -aniso8601 = ">=0.82" -Flask = ">=0.8" -pytz = "*" -six = ">=1.3.0" - -[package.extras] -docs = ["sphinx"] - -[[package]] -name = "flask-sqlalchemy" -version = "3.1.1" -description = "Add SQLAlchemy support to your Flask application." -optional = false -python-versions = ">=3.8" -files = [ - {file = "flask_sqlalchemy-3.1.1-py3-none-any.whl", hash = "sha256:4ba4be7f419dc72f4efd8802d69974803c37259dd42f3913b0dcf75c9447e0a0"}, - {file = "flask_sqlalchemy-3.1.1.tar.gz", hash = "sha256:e4b68bb881802dda1a7d878b2fc84c06d1ee57fb40b874d3dc97dabfa36b8312"}, -] - -[package.dependencies] -flask = ">=2.2.5" -sqlalchemy = ">=2.0.16" - -[[package]] -name = "greenlet" -version = "3.0.3" -description = "Lightweight in-process concurrent programming" -optional = false -python-versions = ">=3.7" -files = [ - {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"}, - {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"}, - {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"}, - {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"}, - {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"}, - {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"}, - {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"}, - {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"}, - {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"}, - {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"}, - {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"}, - {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"}, - {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"}, - {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"}, - {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"}, - {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"}, - {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"}, - {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"}, - {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"}, - {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"}, - {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"}, - {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"}, - {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"}, - {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"}, - {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"}, - {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"}, - {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"}, - {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"}, -] - -[package.extras] -docs = ["Sphinx", "furo"] -test = ["objgraph", "psutil"] - -[[package]] -name = "itsdangerous" -version = "2.2.0" -description = "Safely pass data to untrusted environments and back." -optional = false -python-versions = ">=3.8" -files = [ - {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, - {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, -] - -[[package]] -name = "jinja2" -version = "3.1.4" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -files = [ - {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, - {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "loguru" -version = "0.7.2" -description = "Python logging made (stupidly) simple" -optional = false -python-versions = ">=3.5" -files = [ - {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"}, - {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"] - -[[package]] -name = "mako" -version = "1.3.5" -description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -optional = false -python-versions = ">=3.8" -files = [ - {file = "Mako-1.3.5-py3-none-any.whl", hash = "sha256:260f1dbc3a519453a9c856dedfe4beb4e50bd5a26d96386cb6c80856556bb91a"}, - {file = "Mako-1.3.5.tar.gz", hash = "sha256:48dbc20568c1d276a2698b36d968fa76161bf127194907ea6fc594fa81f943bc"}, -] - -[package.dependencies] -MarkupSafe = ">=0.9.2" - -[package.extras] -babel = ["Babel"] -lingua = ["lingua"] -testing = ["pytest"] - -[[package]] -name = "markupsafe" -version = "2.1.5" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.7" -files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, -] - -[[package]] -name = "marshmallow" -version = "3.22.0" -description = "A lightweight library for converting complex datatypes to and from native Python datatypes." -optional = false -python-versions = ">=3.8" -files = [ - {file = "marshmallow-3.22.0-py3-none-any.whl", hash = "sha256:71a2dce49ef901c3f97ed296ae5051135fd3febd2bf43afe0ae9a82143a494d9"}, - {file = "marshmallow-3.22.0.tar.gz", hash = "sha256:4972f529104a220bb8637d595aa4c9762afbe7f7a77d82dc58c1615d70c5823e"}, -] - -[package.dependencies] -packaging = ">=17.0" - -[package.extras] -dev = ["marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"] -docs = ["alabaster (==1.0.0)", "autodocsumm (==0.2.13)", "sphinx (==8.0.2)", "sphinx-issues (==4.1.0)", "sphinx-version-warning (==1.1.2)"] -tests = ["pytest", "pytz", "simplejson"] - -[[package]] -name = "marshmallow-sqlalchemy" -version = "1.1.0" -description = "SQLAlchemy integration with the marshmallow (de)serialization library" -optional = false -python-versions = ">=3.8" -files = [ - {file = "marshmallow_sqlalchemy-1.1.0-py3-none-any.whl", hash = "sha256:cce261148e4c6ec4ee275f3d29352933380a1afa2fd3933f5e9ecd02fdc16ade"}, - {file = "marshmallow_sqlalchemy-1.1.0.tar.gz", hash = "sha256:2ab092da269dafa8a05d51a58409af71a8d2183958ba47143127dd239e0359d8"}, -] - -[package.dependencies] -marshmallow = ">=3.18.0" -SQLAlchemy = ">=1.4.40,<3.0" - -[package.extras] -dev = ["marshmallow-sqlalchemy[tests]", "pre-commit (>=3.5,<4.0)", "tox"] -docs = ["alabaster (==1.0.0)", "sphinx (==8.0.2)", "sphinx-issues (==4.1.0)"] -tests = ["pytest (<9)", "pytest-lazy-fixtures"] - -[[package]] -name = "packaging" -version = "24.1" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, -] - -[[package]] -name = "pyjwt" -version = "2.9.0" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, - {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, -] - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pytz" -version = "2024.1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -files = [ - {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, - {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "sqlalchemy" -version = "2.0.32" -description = "Database Abstraction Library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "SQLAlchemy-2.0.32-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0c9045ecc2e4db59bfc97b20516dfdf8e41d910ac6fb667ebd3a79ea54084619"}, - {file = "SQLAlchemy-2.0.32-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1467940318e4a860afd546ef61fefb98a14d935cd6817ed07a228c7f7c62f389"}, - {file = "SQLAlchemy-2.0.32-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5954463675cb15db8d4b521f3566a017c8789222b8316b1e6934c811018ee08b"}, - {file = "SQLAlchemy-2.0.32-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:167e7497035c303ae50651b351c28dc22a40bb98fbdb8468cdc971821b1ae533"}, - {file = "SQLAlchemy-2.0.32-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b27dfb676ac02529fb6e343b3a482303f16e6bc3a4d868b73935b8792edb52d0"}, - {file = "SQLAlchemy-2.0.32-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bf2360a5e0f7bd75fa80431bf8ebcfb920c9f885e7956c7efde89031695cafb8"}, - {file = "SQLAlchemy-2.0.32-cp310-cp310-win32.whl", hash = "sha256:306fe44e754a91cd9d600a6b070c1f2fadbb4a1a257b8781ccf33c7067fd3e4d"}, - {file = "SQLAlchemy-2.0.32-cp310-cp310-win_amd64.whl", hash = "sha256:99db65e6f3ab42e06c318f15c98f59a436f1c78179e6a6f40f529c8cc7100b22"}, - {file = "SQLAlchemy-2.0.32-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:21b053be28a8a414f2ddd401f1be8361e41032d2ef5884b2f31d31cb723e559f"}, - {file = "SQLAlchemy-2.0.32-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b178e875a7a25b5938b53b006598ee7645172fccafe1c291a706e93f48499ff5"}, - {file = "SQLAlchemy-2.0.32-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723a40ee2cc7ea653645bd4cf024326dea2076673fc9d3d33f20f6c81db83e1d"}, - {file = "SQLAlchemy-2.0.32-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:295ff8689544f7ee7e819529633d058bd458c1fd7f7e3eebd0f9268ebc56c2a0"}, - {file = "SQLAlchemy-2.0.32-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:49496b68cd190a147118af585173ee624114dfb2e0297558c460ad7495f9dfe2"}, - {file = "SQLAlchemy-2.0.32-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:acd9b73c5c15f0ec5ce18128b1fe9157ddd0044abc373e6ecd5ba376a7e5d961"}, - {file = "SQLAlchemy-2.0.32-cp311-cp311-win32.whl", hash = "sha256:9365a3da32dabd3e69e06b972b1ffb0c89668994c7e8e75ce21d3e5e69ddef28"}, - {file = "SQLAlchemy-2.0.32-cp311-cp311-win_amd64.whl", hash = "sha256:8bd63d051f4f313b102a2af1cbc8b80f061bf78f3d5bd0843ff70b5859e27924"}, - {file = "SQLAlchemy-2.0.32-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6bab3db192a0c35e3c9d1560eb8332463e29e5507dbd822e29a0a3c48c0a8d92"}, - {file = "SQLAlchemy-2.0.32-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:19d98f4f58b13900d8dec4ed09dd09ef292208ee44cc9c2fe01c1f0a2fe440e9"}, - {file = "SQLAlchemy-2.0.32-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd33c61513cb1b7371fd40cf221256456d26a56284e7d19d1f0b9f1eb7dd7e8"}, - {file = "SQLAlchemy-2.0.32-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d6ba0497c1d066dd004e0f02a92426ca2df20fac08728d03f67f6960271feec"}, - {file = "SQLAlchemy-2.0.32-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2b6be53e4fde0065524f1a0a7929b10e9280987b320716c1509478b712a7688c"}, - {file = "SQLAlchemy-2.0.32-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:916a798f62f410c0b80b63683c8061f5ebe237b0f4ad778739304253353bc1cb"}, - {file = "SQLAlchemy-2.0.32-cp312-cp312-win32.whl", hash = "sha256:31983018b74908ebc6c996a16ad3690301a23befb643093fcfe85efd292e384d"}, - {file = "SQLAlchemy-2.0.32-cp312-cp312-win_amd64.whl", hash = "sha256:4363ed245a6231f2e2957cccdda3c776265a75851f4753c60f3004b90e69bfeb"}, - {file = "SQLAlchemy-2.0.32-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b8afd5b26570bf41c35c0121801479958b4446751a3971fb9a480c1afd85558e"}, - {file = "SQLAlchemy-2.0.32-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c750987fc876813f27b60d619b987b057eb4896b81117f73bb8d9918c14f1cad"}, - {file = "SQLAlchemy-2.0.32-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ada0102afff4890f651ed91120c1120065663506b760da4e7823913ebd3258be"}, - {file = "SQLAlchemy-2.0.32-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:78c03d0f8a5ab4f3034c0e8482cfcc415a3ec6193491cfa1c643ed707d476f16"}, - {file = "SQLAlchemy-2.0.32-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:3bd1cae7519283ff525e64645ebd7a3e0283f3c038f461ecc1c7b040a0c932a1"}, - {file = "SQLAlchemy-2.0.32-cp37-cp37m-win32.whl", hash = "sha256:01438ebcdc566d58c93af0171c74ec28efe6a29184b773e378a385e6215389da"}, - {file = "SQLAlchemy-2.0.32-cp37-cp37m-win_amd64.whl", hash = "sha256:4979dc80fbbc9d2ef569e71e0896990bc94df2b9fdbd878290bd129b65ab579c"}, - {file = "SQLAlchemy-2.0.32-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c742be912f57586ac43af38b3848f7688863a403dfb220193a882ea60e1ec3a"}, - {file = "SQLAlchemy-2.0.32-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:62e23d0ac103bcf1c5555b6c88c114089587bc64d048fef5bbdb58dfd26f96da"}, - {file = "SQLAlchemy-2.0.32-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:251f0d1108aab8ea7b9aadbd07fb47fb8e3a5838dde34aa95a3349876b5a1f1d"}, - {file = "SQLAlchemy-2.0.32-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ef18a84e5116340e38eca3e7f9eeaaef62738891422e7c2a0b80feab165905f"}, - {file = "SQLAlchemy-2.0.32-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3eb6a97a1d39976f360b10ff208c73afb6a4de86dd2a6212ddf65c4a6a2347d5"}, - {file = "SQLAlchemy-2.0.32-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0c1c9b673d21477cec17ab10bc4decb1322843ba35b481585facd88203754fc5"}, - {file = "SQLAlchemy-2.0.32-cp38-cp38-win32.whl", hash = "sha256:c41a2b9ca80ee555decc605bd3c4520cc6fef9abde8fd66b1cf65126a6922d65"}, - {file = "SQLAlchemy-2.0.32-cp38-cp38-win_amd64.whl", hash = "sha256:8a37e4d265033c897892279e8adf505c8b6b4075f2b40d77afb31f7185cd6ecd"}, - {file = "SQLAlchemy-2.0.32-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:52fec964fba2ef46476312a03ec8c425956b05c20220a1a03703537824b5e8e1"}, - {file = "SQLAlchemy-2.0.32-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:328429aecaba2aee3d71e11f2477c14eec5990fb6d0e884107935f7fb6001632"}, - {file = "SQLAlchemy-2.0.32-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85a01b5599e790e76ac3fe3aa2f26e1feba56270023d6afd5550ed63c68552b3"}, - {file = "SQLAlchemy-2.0.32-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaf04784797dcdf4c0aa952c8d234fa01974c4729db55c45732520ce12dd95b4"}, - {file = "SQLAlchemy-2.0.32-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4488120becf9b71b3ac718f4138269a6be99a42fe023ec457896ba4f80749525"}, - {file = "SQLAlchemy-2.0.32-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:14e09e083a5796d513918a66f3d6aedbc131e39e80875afe81d98a03312889e6"}, - {file = "SQLAlchemy-2.0.32-cp39-cp39-win32.whl", hash = "sha256:0d322cc9c9b2154ba7e82f7bf25ecc7c36fbe2d82e2933b3642fc095a52cfc78"}, - {file = "SQLAlchemy-2.0.32-cp39-cp39-win_amd64.whl", hash = "sha256:7dd8583df2f98dea28b5cd53a1beac963f4f9d087888d75f22fcc93a07cf8d84"}, - {file = "SQLAlchemy-2.0.32-py3-none-any.whl", hash = "sha256:e567a8793a692451f706b363ccf3c45e056b67d90ead58c3bc9471af5d212202"}, - {file = "SQLAlchemy-2.0.32.tar.gz", hash = "sha256:c1b88cc8b02b6a5f0efb0345a03672d4c897dc7d92585176f88c67346f565ea8"}, -] - -[package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version < \"3.13\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} -typing-extensions = ">=4.6.0" - -[package.extras] -aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] -aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] -aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] -asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] -mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] -mssql = ["pyodbc"] -mssql-pymssql = ["pymssql"] -mssql-pyodbc = ["pyodbc"] -mypy = ["mypy (>=0.910)"] -mysql = ["mysqlclient (>=1.4.0)"] -mysql-connector = ["mysql-connector-python"] -oracle = ["cx_oracle (>=8)"] -oracle-oracledb = ["oracledb (>=1.0.1)"] -postgresql = ["psycopg2 (>=2.7)"] -postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] -postgresql-pg8000 = ["pg8000 (>=1.29.1)"] -postgresql-psycopg = ["psycopg (>=3.0.7)"] -postgresql-psycopg2binary = ["psycopg2-binary"] -postgresql-psycopg2cffi = ["psycopg2cffi"] -postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] -pymysql = ["pymysql"] -sqlcipher = ["sqlcipher3_binary"] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "werkzeug" -version = "3.0.4" -description = "The comprehensive WSGI web application library." -optional = false -python-versions = ">=3.8" -files = [ - {file = "werkzeug-3.0.4-py3-none-any.whl", hash = "sha256:02c9eb92b7d6c06f31a782811505d2157837cea66aaede3e217c7c27c039476c"}, - {file = "werkzeug-3.0.4.tar.gz", hash = "sha256:34f2371506b250df4d4f84bfe7b0921e4762525762bbd936614909fe25cd7306"}, -] - -[package.dependencies] -MarkupSafe = ">=2.1.1" - -[package.extras] -watchdog = ["watchdog (>=2.3)"] - -[[package]] -name = "win32-setctime" -version = "1.1.0" -description = "A small Python utility to set file creation time on Windows" -optional = false -python-versions = ">=3.5" -files = [ - {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, - {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, -] - -[package.extras] -dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] - -[metadata] -lock-version = "2.0" -python-versions = "^3.10" -content-hash = "dda1a445d3e4ac500b0e776fae43a153624d8d62cb91ca0f2584837b622a42a7" diff --git a/projects/web_demo/pyproject.toml b/projects/web_demo/pyproject.toml deleted file mode 100644 index 05164cd51955cfb84d5c81cdfea08e95751914c5..0000000000000000000000000000000000000000 --- a/projects/web_demo/pyproject.toml +++ /dev/null @@ -1,24 +0,0 @@ -[tool.poetry] -name = "web-api" -version = "0.1.0" -description = "" -authors = ["houlinfeng "] -readme = "README.md" - -[tool.poetry.dependencies] -python = "^3.10" -flask = "^3.0.3" -flask-restful = "^0.3.10" -flask-cors = "^5.0.0" -flask-sqlalchemy = "^3.1.1" -flask-migrate = "^4.0.7" -flask-jwt-extended = "^4.6.0" -flask-marshmallow = "^1.2.1" -pyyaml = "^6.0.2" -loguru = "^0.7.2" -marshmallow-sqlalchemy = "^1.1.0" - - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" diff --git a/projects/web_demo/requirements.txt b/projects/web_demo/requirements.txt deleted file mode 100644 index 92242b62bf546a7520804aeb95071c1e3aa4f3c6..0000000000000000000000000000000000000000 --- a/projects/web_demo/requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -flask-cors -flask-jwt-extended -flask-marshmallow -flask-migrate -flask-restful -flask-sqlalchemy -flask -greenlet -loguru -marshmallow-sqlalchemy -marshmallow -pyjwt -pyyaml diff --git a/projects/web_demo/tests/__init__.py b/projects/web_demo/tests/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/projects/web_demo/web_demo/__init__.py b/projects/web_demo/web_demo/__init__.py deleted file mode 100644 index 8c0262efb737bd7e99315feffd981f8069f61a90..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__all__ = ["common", "api"] \ No newline at end of file diff --git a/projects/web_demo/web_demo/api/__init__.py b/projects/web_demo/web_demo/api/__init__.py deleted file mode 100644 index 5efbb90421d700d8f790ad833f9cfb61a6c146f2..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/__init__.py +++ /dev/null @@ -1,38 +0,0 @@ -import os -from .extentions import app, db, migrate, jwt, ma -from common.web_hook import before_request -from common.logger import setup_log - -root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - - -def _register_db(flask_app): - from common import import_models - db.init_app(flask_app) - with app.app_context(): - db.create_all() - - -def create_app(config): - """ - Create and configure an instance of the Flask application - :param config: - :return: - """ - app.static_folder = os.path.join(root_dir, "static") - if config is None: - config = {} - app.config.update(config) - setup_log(config) - _register_db(app) - migrate.init_app(app=app, db=db) - jwt.init_app(app=app) - ma.init_app(app=app) - from .analysis import analysis_blue - app.register_blueprint(analysis_blue) - from .react_app import react_app_blue - app.register_blueprint(react_app_blue) - - app.before_request(before_request) - - return app diff --git a/projects/web_demo/web_demo/api/analysis/__init__.py b/projects/web_demo/web_demo/api/analysis/__init__.py deleted file mode 100644 index 309d8e7abff335bb3aae7bc2b7a25e9744e7efe9..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -from flask import Blueprint -from ..extentions import Api -from .upload_view import UploadPdfView -from .analysis_view import AnalysisTaskView, AnalysisTaskProgressView -from .img_md_view import ImgView, MdView -from .task_view import TaskView, HistoricalTasksView, DeleteTaskView -from .markdown_view import MarkdownView - -analysis_blue = Blueprint('analysis', __name__) - -api_v2 = Api(analysis_blue, prefix='/api/v2') -api_v2.add_resource(UploadPdfView, '/analysis/upload_pdf') -api_v2.add_resource(AnalysisTaskView, '/extract/task/submit') -api_v2.add_resource(AnalysisTaskProgressView, '/extract/task/progress') -api_v2.add_resource(ImgView, '/analysis/pdf_img') -api_v2.add_resource(MdView, '/analysis/pdf_md') -api_v2.add_resource(TaskView, '/extract/taskQueue') -api_v2.add_resource(HistoricalTasksView, '/extract/list') -api_v2.add_resource(DeleteTaskView, '/extract/task/') -api_v2.add_resource(MarkdownView, '/extract/markdown') \ No newline at end of file diff --git a/projects/web_demo/web_demo/api/analysis/analysis_view.py b/projects/web_demo/web_demo/api/analysis/analysis_view.py deleted file mode 100644 index b88a1b48fe8a26cb4c9e52787d457be0ac4fa058..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/analysis_view.py +++ /dev/null @@ -1,242 +0,0 @@ -import json -import threading -from multiprocessing import Process -from pathlib import Path -from flask import request, current_app, url_for -from flask_restful import Resource -from .ext import find_file, task_state_map -# from .formula_ext import formula_detection, formula_recognition -from .serialization import AnalysisViewSchema -from marshmallow import ValidationError -from ..extentions import db -from .models import AnalysisTask, AnalysisPdf -from .pdf_ext import analysis_pdf_task -from common.custom_response import generate_response - - -class AnalysisTaskProgressView(Resource): - - def get(self): - """ - 获取任务进度 - :return: - """ - params = request.args - id = params.get('id') - analysis_task = AnalysisTask.query.filter(AnalysisTask.id == id).first() - if not analysis_task: - return generate_response(code=400, msg="Invalid ID", msgZH="无效id") - match analysis_task.task_type: - case 'pdf': - analysis_pdf = AnalysisPdf.query.filter(AnalysisPdf.id == analysis_task.analysis_pdf_id).first() - file_url = url_for('analysis.uploadpdfview', filename=analysis_task.file_name, as_attachment=False) - file_name_split = analysis_task.file_name.split("_") - file_name = file_name_split[-1] if file_name_split else analysis_task.file_name - if analysis_task.status == 0: - data = { - "state": task_state_map.get(analysis_task.status), - "status": analysis_pdf.status, - "url": file_url, - "fileName": file_name, - "file_key": analysis_task.file_key, - "content": [], - "markdownUrl": [], - "fullMdLink": "", - "type": analysis_task.task_type, - } - return generate_response(data=data) - elif analysis_task.status == 1: - if analysis_pdf.status == 1: # 任务正常完成 - bbox_info = json.loads(analysis_pdf.bbox_info) - md_link_list = json.loads(analysis_pdf.md_link_list) - full_md_link = analysis_pdf.full_md_link - data = { - "state": task_state_map.get(analysis_task.status), - "status": analysis_pdf.status, - "url": file_url, - "fileName": file_name, - "file_key": analysis_task.file_key, - "content": bbox_info, - "markdownUrl": md_link_list, - "fullMdLink": full_md_link, - "type": analysis_task.task_type, - } - return generate_response(data=data) - else: # 任务异常结束 - data = { - "state": "failed", - "status": analysis_pdf.status, - "url": file_url, - "fileName": file_name, - "file_key": analysis_task.file_key, - "content": [], - "markdownUrl": [], - "fullMdLink": "", - "type": analysis_task.task_type, - } - return generate_response(code=-60004, data=data, msg="Failed to retrieve PDF parsing progress", - msgZh="无法获取PDF解析进度") - else: - data = { - "state": task_state_map.get(analysis_task.status), - "status": analysis_pdf.status, - "url": file_url, - "fileName": file_name, - "file_key": analysis_task.file_key, - "content": [], - "markdownUrl": [], - "fullMdLink": "", - "type": analysis_task.task_type, - } - return generate_response(data=data) - case 'formula-detect': - return generate_response(code=400, msg="Not yet supported", msgZH="功能待开发") - case 'formula-extract': - return generate_response(code=400, msg="Not yet supported", msgZH="功能待开发") - case 'table-recogn': - return generate_response(code=400, msg="Not yet supported", msgZH="功能待开发") - case _: - return generate_response(code=400, msg="Not yet supported", msgZH="参数不支持") - - -class AnalysisTaskView(Resource): - - def post(self): - """ - 提交任务 - :return: - """ - analysis_view_schema = AnalysisViewSchema() - try: - params = analysis_view_schema.load(request.get_json()) - except ValidationError as err: - return generate_response(code=400, msg=err.messages) - file_key = params.get("fileKey") - file_name = params.get("fileName") - task_type = params.get("taskType") - is_ocr = params.get("isOcr", False) - - pdf_upload_folder = current_app.config['PDF_UPLOAD_FOLDER'] - upload_dir = f"{current_app.static_folder}/{pdf_upload_folder}" - file_path = find_file(file_key, upload_dir) - match task_type: - case 'pdf': - if not file_path: - return generate_response(code=400, msg="FileKey is invalid, no PDF file found", - msgZH="fileKey无效,未找到pdf文件") - analysis_task = AnalysisTask.query.filter(AnalysisTask.status.in_([0, 2])).first() - file_name = Path(file_path).name - with db.auto_commit(): - analysis_pdf_object = AnalysisPdf( - file_name=file_name, - file_path=file_path, - status=3 if analysis_task else 0, - ) - db.session.add(analysis_pdf_object) - db.session.flush() - analysis_pdf_id = analysis_pdf_object.id - with db.auto_commit(): - analysis_task_object = AnalysisTask( - file_key=file_key, - file_name=file_name, - task_type=task_type, - is_ocr=is_ocr, - status=2 if analysis_task else 0, - analysis_pdf_id=analysis_pdf_id - ) - db.session.add(analysis_task_object) - db.session.flush() - analysis_task_id = analysis_task_object.id - if not analysis_task: # 已有同类型任务在执行,请等待执行完成 - file_stem = Path(file_path).stem - pdf_analysis_folder = current_app.config['PDF_ANALYSIS_FOLDER'] - pdf_dir = f"{current_app.static_folder}/{pdf_analysis_folder}/{file_stem}" - image_dir = f"{pdf_dir}/images" - t = threading.Thread(target=analysis_pdf_task, - args=(pdf_dir, image_dir, file_path, is_ocr, analysis_pdf_id)) - t.start() - # 生成文件的URL路径 - file_url = url_for('analysis.uploadpdfview', filename=file_name, as_attachment=False) - data = { - "url": file_url, - "fileName": file_name, - "id": analysis_task_id - } - return generate_response(data=data) - case 'formula-detect': - # if not file_path: - # return generate_response(code=400, msg="FileKey is invalid, no image file found", - # msgZH="fileKey无效,未找到图片") - # return formula_detection(file_path, upload_dir) - return generate_response(code=400, msg="Not yet supported", msgZH="功能待开发") - case 'formula-extract': - # if not file_path: - # return generate_response(code=400, msg="FileKey is invalid, no image file found", - # msgZH="fileKey无效,未找到图片") - # return formula_recognition(file_path, upload_dir) - return generate_response(code=400, msg="Not yet supported", msgZH="功能待开发") - case 'table-recogn': - return generate_response(code=400, msg="Not yet supported", msgZH="功能待开发") - case _: - return generate_response(code=400, msg="Not yet supported", msgZH="参数不支持") - - def put(self): - """ - 重新发起任务 - :return: - """ - params = json.loads(request.data) - id = params.get('id') - analysis_task = AnalysisTask.query.filter(AnalysisTask.id == id).first() - if not analysis_task: - return generate_response(code=400, msg="Invalid ID", msgZH="无效id") - match analysis_task.task_type: - case 'pdf': - task_r_p = AnalysisTask.query.filter(AnalysisTask.status.in_([0, 2])).first() - if task_r_p: - with db.auto_commit(): - analysis_pdf_object = AnalysisPdf.query.filter_by(id=analysis_task.analysis_pdf_id).first() - analysis_pdf_object.status = 3 - db.session.add(analysis_pdf_object) - with db.auto_commit(): - analysis_task.status = 2 - db.session.add(analysis_task) - else: - with db.auto_commit(): - analysis_pdf_object = AnalysisPdf.query.filter_by(id=analysis_task.analysis_pdf_id).first() - analysis_pdf_object.status = 0 - db.session.add(analysis_pdf_object) - with db.auto_commit(): - analysis_task.status = 0 - db.session.add(analysis_task) - - pdf_upload_folder = current_app.config['PDF_UPLOAD_FOLDER'] - upload_dir = f"{current_app.static_folder}/{pdf_upload_folder}" - file_path = find_file(analysis_task.file_key, upload_dir) - file_stem = Path(file_path).stem - pdf_analysis_folder = current_app.config['PDF_ANALYSIS_FOLDER'] - pdf_dir = f"{current_app.static_folder}/{pdf_analysis_folder}/{file_stem}" - image_dir = f"{pdf_dir}/images" - process = Process(target=analysis_pdf_task, - args=(pdf_dir, image_dir, file_path, analysis_task.is_ocr, - analysis_task.analysis_pdf_id)) - process.start() - - # 生成文件的URL路径 - file_url = url_for('analysis.uploadpdfview', filename=analysis_task.file_name, as_attachment=False) - file_name_split = analysis_task.file_name.split("_") - new_file_name = file_name_split[-1] if file_name_split else analysis_task.file_name - data = { - "url": file_url, - "fileName": new_file_name, - "id": analysis_task.id - } - return generate_response(data=data) - case 'formula-detect': - return generate_response(code=400, msg="Not yet supported", msgZH="功能待开发") - case 'formula-extract': - return generate_response(code=400, msg="Not yet supported", msgZH="功能待开发") - case 'table-recogn': - return generate_response(code=400, msg="Not yet supported", msgZH="功能待开发") - case _: - return generate_response(code=400, msg="Not yet supported", msgZH="参数不支持") diff --git a/projects/web_demo/web_demo/api/analysis/ext.py b/projects/web_demo/web_demo/api/analysis/ext.py deleted file mode 100644 index 6767fd0b6ea40f5cd55b4e4b1644f9236b48571d..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/ext.py +++ /dev/null @@ -1,25 +0,0 @@ -import os - -task_state_map = { - 0: "running", - 1: "done", - 2: "pending" -} - - -def find_file(file_key, file_dir): - """ - 查询文件 - :param file_key: 文件哈希 - :param file_dir: 文件目录 - :return: - """ - pdf_path = "" - for root, subDirs, files in os.walk(file_dir): - for fileName in files: - if fileName.startswith(file_key): - pdf_path = os.path.join(root, fileName) - break - if pdf_path: - break - return pdf_path diff --git a/projects/web_demo/web_demo/api/analysis/formula_ext.py b/projects/web_demo/web_demo/api/analysis/formula_ext.py deleted file mode 100644 index aebcca14a480d603de92e4b8d8b99c3c539f790e..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/formula_ext.py +++ /dev/null @@ -1,280 +0,0 @@ -import os -import pkgutil -import numpy as np -import yaml -import argparse -import cv2 -from pathlib import Path -from ultralytics import YOLO -from unimernet.common.config import Config -import unimernet.tasks as tasks -from unimernet.processors import load_processor -from magic_pdf.libs.config_reader import get_local_models_dir, get_device -from torchvision import transforms -from magic_pdf.pre_proc.ocr_span_list_modify import remove_overlaps_low_confidence_spans, remove_overlaps_min_spans -from PIL import Image -from common.ext import singleton_func -from common.custom_response import generate_response - - -def mfd_model_init(weight): - mfd_model = YOLO(weight) - return mfd_model - - -def mfr_model_init(weight_dir, cfg_path, _device_='cpu'): - args = argparse.Namespace(cfg_path=cfg_path, options=None) - cfg = Config(args) - cfg.config.model.pretrained = os.path.join(weight_dir, "pytorch_model.bin") - cfg.config.model.model_config.model_name = weight_dir - cfg.config.model.tokenizer_config.path = weight_dir - task = tasks.setup_task(cfg) - model = task.build_model(cfg) - model = model.to(_device_) - vis_processor = load_processor('formula_image_eval', cfg.config.datasets.formula_rec_eval.vis_processor.eval) - return model, vis_processor - - -@singleton_func -class CustomPEKModel: - def __init__(self): - # PDF-Extract-Kit/models - models_dir = get_local_models_dir() - self.device = get_device() - loader = pkgutil.get_loader("magic_pdf") - root_dir = Path(loader.path).parent - # model_config目录 - model_config_dir = os.path.join(root_dir, 'resources', 'model_config') - # 构建 model_configs.yaml 文件的完整路径 - config_path = os.path.join(model_config_dir, 'model_configs.yaml') - with open(config_path, "r", encoding='utf-8') as f: - configs = yaml.load(f, Loader=yaml.FullLoader) - - # 初始化公式检测模型 - self.mfd_model = mfd_model_init(str(os.path.join(models_dir, configs["weights"]["mfd"]))) - - # 初始化公式解析模型 - mfr_weight_dir = str(os.path.join(models_dir, configs["weights"]["mfr"])) - mfr_cfg_path = str(os.path.join(model_config_dir, "UniMERNet", "demo.yaml")) - self.mfr_model, mfr_vis_processors = mfr_model_init(mfr_weight_dir, mfr_cfg_path, _device_=self.device) - self.mfr_transform = transforms.Compose([mfr_vis_processors, ]) - - -def get_all_spans(layout_dets) -> list: - def remove_duplicate_spans(spans): - new_spans = [] - for span in spans: - if not any(span == existing_span for existing_span in new_spans): - new_spans.append(span) - return new_spans - - all_spans = [] - # allow_category_id_list = [3, 5, 13, 14, 15] - """当成span拼接的""" - # 3: 'image', # 图片 - # 5: 'table', # 表格 - # 13: 'inline_equation', # 行内公式 - # 14: 'interline_equation', # 行间公式 - # 15: 'text', # ocr识别文本 - for layout_det in layout_dets: - if layout_det.get("bbox") is not None: - # 兼容直接输出bbox的模型数据,如paddle - x0, y0, x1, y1 = layout_det["bbox"] - else: - # 兼容直接输出poly的模型数据,如xxx - x0, y0, _, _, x1, y1, _, _ = layout_det["poly"] - bbox = [x0, y0, x1, y1] - layout_det["bbox"] = bbox - all_spans.append(layout_det) - return remove_duplicate_spans(all_spans) - - -def formula_predict(mfd_model, image): - """ - 公式检测 - :param mfd_model: - :param image: - :return: - """ - latex_filling_list = [] - # 公式检测 - mfd_res = mfd_model.predict(image, imgsz=1888, conf=0.25, iou=0.45, verbose=True)[0] - for xyxy, conf, cla in zip(mfd_res.boxes.xyxy.cpu(), mfd_res.boxes.conf.cpu(), mfd_res.boxes.cls.cpu()): - xmin, ymin, xmax, ymax = [int(p.item()) for p in xyxy] - new_item = { - 'category_id': 13 + int(cla.item()), - 'poly': [xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax], - 'score': round(float(conf.item()), 2), - 'latex': '', - } - latex_filling_list.append(new_item) - return latex_filling_list - - -def formula_detection(file_path, upload_dir): - """ - 公式检测 - :param file_path: 文件路径 - :param upload_dir: 上传文件夹 - :return: - """ - try: - image_open = Image.open(file_path) - except IOError: - return generate_response(code=400, msg="params is not valid", msgZh="参数类型不是图片,无效参数") - - filename = Path(file_path).name - - # 获取图片宽高 - width, height = image_open.size - # 转换为RGB,忽略透明度通道 - rgb_image = image_open.convert('RGB') - # 保存转换后的图片 - rgb_image.save(file_path) - - # 初始化模型 - cpm = CustomPEKModel() - # 初始化公式检测模型 - mfd_model = cpm.mfd_model - - image_conv = Image.open(file_path) - image_array = np.array(image_conv) - pdf_width = 1416 - pdf_height = 1888 - - # 重置图片大小 - scale = min(pdf_width // 2 / width, pdf_height // 2 / height) # 缩放比例 - nw = int(width * scale) - nh = int(height * scale) - image_resize = cv2.resize(image_array, (nw, nh), interpolation=cv2.INTER_LINEAR) - resize_image_path = f"{upload_dir}/resize_{filename}" - cv2.imwrite(resize_image_path, image_resize) - # 将重置的图片贴到pdf白纸中 - x = (pdf_width - nw) // 2 - y = (pdf_height - nh) // 2 - new_img = Image.new('RGB', (pdf_width, pdf_height), 'white') - image_scale = Image.open(resize_image_path) - new_img.paste(image_scale, (x, y)) - - # 公式检测 - latex_filling_list = formula_predict(mfd_model, new_img) - - os.remove(resize_image_path) - - # 将缩放图公式检测的坐标还原为原图公式检测的坐标 - for item in latex_filling_list: - item_poly = item["poly"] - item["poly"] = [ - (item_poly[0] - x) / scale, - (item_poly[1] - y) / scale, - (item_poly[2] - x) / scale, - (item_poly[3] - y) / scale, - (item_poly[4] - x) / scale, - (item_poly[5] - y) / scale, - (item_poly[6] - x) / scale, - (item_poly[7] - y) / scale, - ] - - if not latex_filling_list: - return generate_response(code=1001, msg="detection fail", msgZh="公式检测失败,图片过小,无法检测") - - spans = get_all_spans(latex_filling_list) - '''删除重叠spans中置信度较低的那些''' - spans, dropped_spans_by_confidence = remove_overlaps_low_confidence_spans(spans) - '''删除重叠spans中较小的那些''' - spans, dropped_spans_by_span_overlap = remove_overlaps_min_spans(spans) - - return generate_response(data={ - 'layout': spans, - }) - - -def formula_recognition(file_path, upload_dir): - """ - 公式识别 - :param file_path: 文件路径 - :param upload_dir: 上传文件夹 - :return: - """ - try: - image_open = Image.open(file_path) - except IOError: - return generate_response(code=400, msg="params is not valid", msgZh="参数类型不是图片,无效参数") - - filename = Path(file_path).name - - # 获取图片宽高 - width, height = image_open.size - # 转换为RGB,忽略透明度通道 - rgb_image = image_open.convert('RGB') - # 保存转换后的图片 - rgb_image.save(file_path) - - image_conv = Image.open(file_path) - image_array = np.array(image_conv) - pdf_width = 1416 - pdf_height = 1888 - - # 重置图片大小 - scale = min(pdf_width // 2 / width, pdf_height // 2 / height) # 缩放比例 - nw = int(width * scale) - nh = int(height * scale) - image_resize = cv2.resize(image_array, (nw, nh), interpolation=cv2.INTER_LINEAR) - resize_image_path = f"{upload_dir}/resize_{filename}" - cv2.imwrite(resize_image_path, image_resize) - # 将重置的图片贴到pdf白纸中 - x = (pdf_width - nw) // 2 - y = (pdf_height - nh) // 2 - new_img = Image.new('RGB', (pdf_width, pdf_height), 'white') - image_scale = Image.open(resize_image_path) - new_img.paste(image_scale, (x, y)) - new_img_array = np.array(new_img) - - # 初始化模型 - cpm = CustomPEKModel() - # device - device = cpm.device - # 初始化公式检测模型 - mfd_model = cpm.mfd_model - # 初始化公式解析模型 - mfr_model = cpm.mfr_model - mfr_transform = cpm.mfr_transform - # 公式识别 - latex_filling_list, mfr_res = formula_recognition(mfd_model, new_img_array, mfr_transform, device, mfr_model, - image_open) - - os.remove(resize_image_path) - - # 将缩放图公式检测的坐标还原为原图公式检测的坐标 - for item in latex_filling_list: - item_poly = item["poly"] - item["poly"] = [ - (item_poly[0] - x) / scale, - (item_poly[1] - y) / scale, - (item_poly[2] - x) / scale, - (item_poly[3] - y) / scale, - (item_poly[4] - x) / scale, - (item_poly[5] - y) / scale, - (item_poly[6] - x) / scale, - (item_poly[7] - y) / scale, - ] - - spans = get_all_spans(latex_filling_list) - '''删除重叠spans中置信度较低的那些''' - spans, dropped_spans_by_confidence = remove_overlaps_low_confidence_spans(spans) - '''删除重叠spans中较小的那些''' - spans, dropped_spans_by_span_overlap = remove_overlaps_min_spans(spans) - - if not latex_filling_list: - width, height = image_open.size - latex_filling_list.append({ - 'category_id': 14, - 'poly': [0, 0, width, 0, width, height, 0, height], - 'score': 1, - 'latex': mfr_res[0] if mfr_res else "", - }) - - return generate_response(data={ - 'layout': spans if spans else latex_filling_list, - "mfr_res": mfr_res - }) diff --git a/projects/web_demo/web_demo/api/analysis/img_md_view.py b/projects/web_demo/web_demo/api/analysis/img_md_view.py deleted file mode 100644 index 66df7bc739df404bc6e79763e7cdb16eac91b405..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/img_md_view.py +++ /dev/null @@ -1,46 +0,0 @@ -from pathlib import Path -from flask import request, current_app, send_from_directory -from flask_restful import Resource - - -class ImgView(Resource): - def get(self): - """ - 获取pdf解析的图片 - :return: - """ - params = request.args - pdf = params.get('pdf') - filename = params.get('filename') - as_attachment = params.get('as_attachment') - if str(as_attachment).lower() == "true": - as_attachment = True - else: - as_attachment = False - file_stem = Path(pdf).stem - pdf_analysis_folder = current_app.config['PDF_ANALYSIS_FOLDER'] - pdf_dir = f"{current_app.static_folder}/{pdf_analysis_folder}/{file_stem}" - image_dir = f"{pdf_dir}/images" - response = send_from_directory(image_dir, filename, as_attachment=as_attachment) - return response - - -class MdView(Resource): - def get(self): - """ - 获取pdf解析的markdown - :return: - """ - params = request.args - pdf = params.get('pdf') - filename = params.get('filename') - as_attachment = params.get('as_attachment') - if str(as_attachment).lower() == "true": - as_attachment = True - else: - as_attachment = False - file_stem = Path(pdf).stem - pdf_analysis_folder = current_app.config['PDF_ANALYSIS_FOLDER'] - pdf_dir = f"{current_app.static_folder}/{pdf_analysis_folder}/{file_stem}" - response = send_from_directory(pdf_dir, filename, as_attachment=as_attachment) - return response diff --git a/projects/web_demo/web_demo/api/analysis/markdown_view.py b/projects/web_demo/web_demo/api/analysis/markdown_view.py deleted file mode 100644 index d82d95b2c329b5a6e88829734801d7d9fa5f9326..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/markdown_view.py +++ /dev/null @@ -1,44 +0,0 @@ -import json -from pathlib import Path -from flask import request, current_app -from flask_restful import Resource -from common.custom_response import generate_response - - -class MarkdownView(Resource): - - def put(self): - """ - 编辑markdown - """ - params = json.loads(request.data) - file_key = params.get('file_key') - data = params.get('data', {}) - if not data: - return generate_response(code=400, msg="empty data", msgZH="数据为空,无法更新markdown") - - pdf_analysis_folder = current_app.config['PDF_ANALYSIS_FOLDER'] - pdf_dir = f"{current_app.static_folder}/{pdf_analysis_folder}" - markdown_file_dir = "" - for path_obj in Path(pdf_dir).iterdir(): - if path_obj.name.startswith(file_key): - markdown_file_dir = path_obj - break - - if markdown_file_dir and Path(markdown_file_dir).exists(): - for k, v in data.items(): - md_path = f"{markdown_file_dir}/{k}.md" - if Path(md_path).exists(): - with open(md_path, 'w', encoding="utf-8") as f: - f.write(v) - - full_content = "" - for path_obj in Path(markdown_file_dir).iterdir(): - if path_obj.is_file() and path_obj.suffix == ".md" and path_obj.stem != "full": - with open(path_obj, 'r', encoding="utf-8") as f: - full_content += f.read() + "\n" - with open(f"{markdown_file_dir}/full.md", 'w', encoding="utf-8") as f: - f.write(full_content) - else: - return generate_response(code=400, msg="Invalid file_key", msgZH="文件哈希错误") - return generate_response() diff --git a/projects/web_demo/web_demo/api/analysis/models.py b/projects/web_demo/web_demo/api/analysis/models.py deleted file mode 100644 index 8221f54a933fdf21195e2e6889ae693d73ff8a07..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/models.py +++ /dev/null @@ -1,29 +0,0 @@ -from datetime import datetime -from ..extentions import db - - -class AnalysisTask(db.Model): - __tablename__ = 'analysis_task' - id = db.Column(db.Integer, primary_key=True, autoincrement=True) - file_key = db.Column(db.Text, comment="文件唯一哈希") - file_name = db.Column(db.Text, comment="文件名称") - task_type = db.Column(db.String(128), comment="任务类型") - is_ocr = db.Column(db.Boolean, default=False, comment="是否ocr") - status = db.Column(db.Integer, default=0, comment="状态") # 0 running 1 done 2 pending - analysis_pdf_id = db.Column(db.Integer, comment="analysis_pdf的id") - create_date = db.Column(db.DateTime(), nullable=False, default=datetime.now) - update_date = db.Column(db.DateTime(), nullable=False, default=datetime.now, onupdate=datetime.now) - - -class AnalysisPdf(db.Model): - __tablename__ = 'analysis_pdf' - id = db.Column(db.Integer, primary_key=True, autoincrement=True) - file_name = db.Column(db.Text, comment="文件名称") - file_url = db.Column(db.Text, comment="文件原路径") - file_path = db.Column(db.Text, comment="文件路径") - status = db.Column(db.Integer, default=3, comment="状态") # 0 转换中 1 已完成 2 转换失败 3 init - bbox_info = db.Column(db.Text, comment="坐标数据") - md_link_list = db.Column(db.Text, comment="markdown分页链接") - full_md_link = db.Column(db.Text, comment="markdown全文链接") - create_date = db.Column(db.DateTime(), nullable=False, default=datetime.now) - update_date = db.Column(db.DateTime(), nullable=False, default=datetime.now, onupdate=datetime.now) \ No newline at end of file diff --git a/projects/web_demo/web_demo/api/analysis/pdf_ext.py b/projects/web_demo/web_demo/api/analysis/pdf_ext.py deleted file mode 100644 index 4d14b53f85174a2673c0aae6b6410e7a4cccae9f..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/pdf_ext.py +++ /dev/null @@ -1,175 +0,0 @@ -import json -import os -import shutil -import traceback -from pathlib import Path - -from common.error_types import ApiException -from common.mk_markdown.mk_markdown import \ - ocr_mk_mm_markdown_with_para_and_pagination -from flask import current_app, url_for -from loguru import logger - -import magic_pdf.model as model_config -from magic_pdf.config.enums import SupportedPdfParseMethod -from magic_pdf.data.data_reader_writer import FileBasedDataWriter -from magic_pdf.data.dataset import PymuDocDataset -from magic_pdf.libs.json_compressor import JsonCompressor -from magic_pdf.model.doc_analyze_by_custom_model import doc_analyze -from magic_pdf.operators.models import InferenceResult - -from ..extentions import app, db -from .ext import find_file -from .models import AnalysisPdf, AnalysisTask - -model_config.__use_inside_model__ = True - - -def analysis_pdf(image_url_prefix, image_dir, pdf_bytes, is_ocr=False): - try: - model_json = [] # model_json传空list使用内置模型解析 - image_writer = FileBasedDataWriter(image_dir) - logger.info(f'is_ocr: {is_ocr}') - parse_method = 'ocr' - ds = PymuDocDataset(pdf_bytes) - # Choose parsing method - if not is_ocr: - if ds.classify() == SupportedPdfParseMethod.OCR: - parse_method = 'ocr' - else: - parse_method = 'txt' - - if parse_method == 'ocr': - infer_result = ds.apply(doc_analyze, ocr=True) - else: - infer_result = ds.apply(doc_analyze, ocr=False) - - if parse_method == 'ocr': - pipe_res = infer_result.pipe_ocr_mode(image_writer) - else: - pipe_res = infer_result.pipe_txt_mode(image_writer) - - pdf_mid_data = pipe_res._pipe_res - pdf_info_list = pdf_mid_data['pdf_info'] - md_content = json.dumps(ocr_mk_mm_markdown_with_para_and_pagination(pdf_info_list, image_url_prefix), - ensure_ascii=False) - bbox_info = get_bbox_info(pdf_info_list) - return md_content, bbox_info - except Exception as e: # noqa: F841 - logger.error(traceback.format_exc()) - -def get_bbox_info(data): - bbox_info = [] - for page in data: - preproc_blocks = page.get('preproc_blocks', []) - discarded_blocks = page.get('discarded_blocks', []) - bbox_info.append({ - 'preproc_blocks': preproc_blocks, - 'page_idx': page.get('page_idx'), - 'page_size': page.get('page_size'), - 'discarded_blocks': discarded_blocks, - }) - return bbox_info - - -def analysis_pdf_task(pdf_dir, image_dir, pdf_path, is_ocr, analysis_pdf_id): - """解析pdf. - - :param pdf_dir: pdf解析目录 - :param image_dir: 图片目录 - :param pdf_path: pdf路径 - :param is_ocr: 是否启用ocr - :param analysis_pdf_id: pdf解析表id - :return: - """ - try: - logger.info(f'start task: {pdf_path}') - logger.info(f'image_dir: {image_dir}') - if not Path(image_dir).exists(): - Path(image_dir).mkdir(parents=True, exist_ok=True) - else: - # 清空image_dir,避免同文件多次解析图片积累 - shutil.rmtree(image_dir, ignore_errors=True) - os.makedirs(image_dir, exist_ok=True) - - # 获取文件内容 - with open(pdf_path, 'rb') as file: - pdf_bytes = file.read() - # 生成图片链接 - with app.app_context(): - image_url_prefix = f"http://{current_app.config['SERVER_NAME']}{current_app.config['FILE_API']}&pdf={Path(pdf_path).name}&filename=" - # 解析文件 - md_content, bbox_info = analysis_pdf(image_url_prefix, image_dir, pdf_bytes, is_ocr) - - # ############ markdown ############# - pdf_name = Path(pdf_path).name - - full_md_content = '' - for item in json.loads(md_content): - full_md_content += item['md_content'] + '\n' - - full_md_name = 'full.md' - with open(f'{pdf_dir}/{full_md_name}', 'w', encoding='utf-8') as file: - file.write(full_md_content) - with app.app_context(): - full_md_link = url_for('analysis.mdview', filename=full_md_name, as_attachment=False) - full_md_link = f'{full_md_link}&pdf={pdf_name}' - - md_link_list = [] - with app.app_context(): - for n, md in enumerate(json.loads(md_content)): - md_content = md['md_content'] - md_name = f"{md.get('page_no', n)}.md" - with open(f'{pdf_dir}/{md_name}', 'w', encoding='utf-8') as file: - file.write(md_content) - md_url = url_for('analysis.mdview', filename=md_name, as_attachment=False) - md_link_list.append(f'{md_url}&pdf={pdf_name}') - - with app.app_context(): - with db.auto_commit(): - analysis_pdf_object = AnalysisPdf.query.filter_by(id=analysis_pdf_id).first() - analysis_pdf_object.status = 1 - analysis_pdf_object.bbox_info = json.dumps(bbox_info, ensure_ascii=False) - analysis_pdf_object.md_link_list = json.dumps(md_link_list, ensure_ascii=False) - analysis_pdf_object.full_md_link = full_md_link - db.session.add(analysis_pdf_object) - with db.auto_commit(): - analysis_task_object = AnalysisTask.query.filter_by(analysis_pdf_id=analysis_pdf_id).first() - analysis_task_object.status = 1 - db.session.add(analysis_task_object) - logger.info('finished!') - except Exception as e: # noqa: F841 - logger.error(traceback.format_exc()) - with app.app_context(): - with db.auto_commit(): - analysis_pdf_object = AnalysisPdf.query.filter_by(id=analysis_pdf_id).first() - analysis_pdf_object.status = 2 - db.session.add(analysis_pdf_object) - with db.auto_commit(): - analysis_task_object = AnalysisTask.query.filter_by(analysis_pdf_id=analysis_pdf_id).first() - analysis_task_object.status = 1 - db.session.add(analysis_task_object) - raise ApiException(code=500, msg='PDF parsing failed', msgZH='pdf解析失败') - finally: - # 执行pending - with app.app_context(): - analysis_task_object = AnalysisTask.query.filter_by(status=2).order_by( - AnalysisTask.update_date.asc()).first() - if analysis_task_object: - pdf_upload_folder = current_app.config['PDF_UPLOAD_FOLDER'] - upload_dir = f'{current_app.static_folder}/{pdf_upload_folder}' - file_path = find_file(analysis_task_object.file_key, upload_dir) - file_stem = Path(file_path).stem - pdf_analysis_folder = current_app.config['PDF_ANALYSIS_FOLDER'] - pdf_dir = f'{current_app.static_folder}/{pdf_analysis_folder}/{file_stem}' - image_dir = f'{pdf_dir}/images' - with db.auto_commit(): - analysis_pdf_object = AnalysisPdf.query.filter_by(id=analysis_task_object.analysis_pdf_id).first() - analysis_pdf_object.status = 0 - db.session.add(analysis_pdf_object) - with db.auto_commit(): - analysis_task_object.status = 0 - db.session.add(analysis_task_object) - analysis_pdf_task(pdf_dir, image_dir, file_path, analysis_task_object.is_ocr, analysis_task_object.analysis_pdf_id) - else: - logger.info('all task finished!') diff --git a/projects/web_demo/web_demo/api/analysis/serialization.py b/projects/web_demo/web_demo/api/analysis/serialization.py deleted file mode 100644 index 727c6aedad2b766bfe0c8f74637d4ee050563c87..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/serialization.py +++ /dev/null @@ -1,28 +0,0 @@ -from marshmallow import Schema, fields, validates_schema, validates -from common.error_types import ApiException -from .models import AnalysisTask - - -class BooleanField(fields.Boolean): - def _deserialize(self, value, attr, data, **kwargs): - # 进行自定义验证 - if not isinstance(value, bool): - raise ApiException(code=400, msg="isOcr not a valid boolean", msgZH="isOcr不是有效的布尔值") - - return value - - -class AnalysisViewSchema(Schema): - fileKey = fields.Str(required=True) - fileName = fields.Str() - taskType = fields.Str(required=True) - isOcr = BooleanField() - - @validates_schema(pass_many=True) - def validate_passwords(self, data, **kwargs): - task_type = data['taskType'] - file_key = data['fileKey'] - if not file_key: - raise ApiException(code=400, msg="fileKey cannot be empty", msgZH="fileKey不能为空") - if not task_type: - raise ApiException(code=400, msg="taskType cannot be empty", msgZH="taskType不能为空") diff --git a/projects/web_demo/web_demo/api/analysis/task_view.py b/projects/web_demo/web_demo/api/analysis/task_view.py deleted file mode 100644 index ea09f07bd556b54dd29d4ea81611faa190efd289..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/task_view.py +++ /dev/null @@ -1,102 +0,0 @@ -import json -from flask import url_for, request -from flask_restful import Resource -from sqlalchemy import func -from ..extentions import db -from .models import AnalysisTask, AnalysisPdf -from .ext import task_state_map -from common.custom_response import generate_response - - -class TaskView(Resource): - def get(self): - """ - 查询正在进行的任务 - :return: - """ - analysis_task_running = AnalysisTask.query.filter(AnalysisTask.status == 0).first() - analysis_task_pending = AnalysisTask.query.filter(AnalysisTask.status == 2).order_by( - AnalysisTask.create_date.asc()).all() - pending_total = db.session.query(func.count(AnalysisTask.id)).filter(AnalysisTask.status == 2).scalar() - if analysis_task_running: - task_nums = pending_total + 1 - file_name_split = analysis_task_running.file_name.split("_") - new_file_name = file_name_split[-1] if file_name_split else analysis_task_running.file_name - data = [ - { - "queues": task_nums, # 正在排队的任务总数 - "rank": 1, - "id": analysis_task_running.id, - "url": url_for('analysis.uploadpdfview', filename=analysis_task_running.file_name, as_attachment=False), - "fileName": new_file_name, - "type": analysis_task_running.task_type, - "state": task_state_map.get(analysis_task_running.status), - } - ] - else: - task_nums = pending_total - data = [] - for n, task in enumerate(analysis_task_pending): - file_name_split = task.file_name.split("_") - new_file_name = file_name_split[-1] if file_name_split else task.file_name - data.append({ - "queues": task_nums, # 正在排队的任务总数 - "rank": n + 2, - "id": task.id, - "url": url_for('analysis.uploadpdfview', filename=task.file_name, as_attachment=False), - "fileName": new_file_name, - "type": task.task_type, - "state": task_state_map.get(task.status), - }) - data.reverse() - return generate_response(data=data, total=task_nums) - - -class HistoricalTasksView(Resource): - def get(self): - """ - 获取任务历史记录 - :return: - """ - params = request.args - page_no = params.get('pageNo', 1) - page_size = params.get('pageSize', 10) - total = db.session.query(func.count(AnalysisTask.id)).scalar() - analysis_task = AnalysisTask.query.order_by(AnalysisTask.create_date.desc()).paginate(page=int(page_no), - per_page=int(page_size), - error_out=False) - data = [] - for n, task in enumerate(analysis_task): - file_name_split = task.file_name.split("_") - new_file_name = file_name_split[-1] if file_name_split else task.file_name - data.append({ - "fileName": new_file_name, - "id": task.id, - "type": task.task_type, - "state": task_state_map.get(task.status), - }) - data = { - "list": data, - "total": total, - "pageNo": page_no, - "pageSize": page_size, - } - return generate_response(data=data) - - -class DeleteTaskView(Resource): - def delete(self, id): - """ - 删除任务历史记录 - :return: - """ - analysis_task = AnalysisTask.query.filter(AnalysisTask.id == id, AnalysisTask.status != 0).first() - if analysis_task: - analysis_pdf = AnalysisPdf.query.filter(AnalysisPdf.id == AnalysisTask.analysis_pdf_id).first() - with db.auto_commit(): - db.session.delete(analysis_pdf) - db.session.delete(analysis_task) - else: - return generate_response(code=400, msg="The ID is incorrect", msgZH="id不正确") - - return generate_response(data={"id": id}) diff --git a/projects/web_demo/web_demo/api/analysis/upload_view.py b/projects/web_demo/web_demo/api/analysis/upload_view.py deleted file mode 100644 index b8a4767b00adb9196152c9442b912bed16bca449..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/analysis/upload_view.py +++ /dev/null @@ -1,89 +0,0 @@ -import json -import time -import traceback -import requests -from flask import request, current_app, url_for, send_from_directory -from flask_restful import Resource -from werkzeug.utils import secure_filename -from pathlib import Path -from common.ext import is_pdf, calculate_file_hash, url_is_pdf -from io import BytesIO -from werkzeug.datastructures import FileStorage -from common.custom_response import generate_response -from loguru import logger - - -class UploadPdfView(Resource): - - def get(self): - """ - 获取pdf - :return: - """ - params = request.args - filename = params.get('filename') - as_attachment = params.get('as_attachment') - if str(as_attachment).lower() == "true": - as_attachment = True - else: - as_attachment = False - pdf_upload_folder = current_app.config['PDF_UPLOAD_FOLDER'] - response = send_from_directory(f"{current_app.static_folder}/{pdf_upload_folder}", filename, - as_attachment=as_attachment) - return response - - def post(self): - """ - 上传pdf - :return: - """ - file_list = request.files.getlist("file") - if file_list: - file = file_list[0] - filename = secure_filename(file.filename) - if not file or file and not is_pdf(filename, file): - return generate_response(code=400, msg="Invalid PDF file", msgZH="PDF文件参数无效") - else: - params = json.loads(request.data) - pdf_url = params.get('pdfUrl') - try: - response = requests.get(pdf_url, stream=True) - except ConnectionError as e: - logger.error(traceback.format_exc()) - return generate_response(code=400, msg="params is not valid", msgZh="参数错误,pdf链接无法访问") - if response.status_code != 200: - return generate_response(code=400, msg="params is not valid", msgZh="参数错误,pdf链接响应状态异常") - # 创建一个模拟的 FileStorage 对象 - file_content = BytesIO(response.content) - filename = Path(pdf_url).name if ".pdf" in pdf_url else f"{Path(pdf_url).name}.pdf" - file = FileStorage( - stream=file_content, - filename=filename, - content_type=response.headers.get('Content-Type', 'application/octet-stream') - ) - if not file or file and not url_is_pdf(file): - return generate_response(code=400, msg="Invalid PDF file", msgZH="PDF文件参数无效") - - pdf_upload_folder = current_app.config['PDF_UPLOAD_FOLDER'] - upload_dir = f"{current_app.static_folder}/{pdf_upload_folder}" - if not Path(upload_dir).exists(): - Path(upload_dir).mkdir(parents=True, exist_ok=True) - file_key = f"{calculate_file_hash(file)}{int(time.time())}" - new_filename = f"{file_key}_{filename}" - file_path = f"{upload_dir}/{new_filename}" - # file.save(file_path) - chunk_size = 8192 - with open(file_path, 'wb') as f: - while True: - chunk = file.stream.read(chunk_size) - if not chunk: - break - f.write(chunk) - - # 生成文件的URL路径 - file_url = url_for('analysis.uploadpdfview', filename=new_filename, as_attachment=False) - data = { - "url": file_url, - "file_key": file_key - } - return generate_response(data=data) diff --git a/projects/web_demo/web_demo/api/extentions.py b/projects/web_demo/web_demo/api/extentions.py deleted file mode 100644 index 2d1c35c43f2c7e641229cb18fd0149a48481f1a4..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/extentions.py +++ /dev/null @@ -1,63 +0,0 @@ -from contextlib import contextmanager - -from common.error_types import ApiException -from flask import Flask, jsonify -from flask_cors import CORS -from flask_jwt_extended import JWTManager -from flask_marshmallow import Marshmallow -from flask_migrate import Migrate -from flask_restful import Api as _Api -from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy -from loguru import logger -from werkzeug.exceptions import HTTPException - - -class Api(_Api): - def handle_error(self, e): - if isinstance(e, ApiException): - code = e.code - msg = e.msg - msgZH = e.msgZH - error_code = e.error_code - elif isinstance(e, HTTPException): - code = e.code - msg = e.description - msgZH = '服务异常,详细信息请查看日志' - error_code = e.code - else: - code = 500 - msg = str(e) - error_code = 500 - msgZH = '服务异常,详细信息请查看日志' - - # 使用 loguru 记录异常信息 - logger.opt(exception=e).error(f'An error occurred: {msg}') - - return jsonify({ - 'error': 'Internal Server Error' if code == 500 else e.name, - 'msg': msg, - 'msgZH': msgZH, - 'code': code, - 'error_code': error_code - }), code - - -class SQLAlchemy(_SQLAlchemy): - @contextmanager - def auto_commit(self): - try: - yield - db.session.commit() - db.session.flush() - except Exception as e: - db.session.rollback() - raise e - - -app = Flask(__name__) -CORS(app, supports_credentials=True) -db = SQLAlchemy() -migrate = Migrate() -jwt = JWTManager() -ma = Marshmallow() -folder = app.config.get('REACT_APP_DIST') diff --git a/projects/web_demo/web_demo/api/react_app/__init__.py b/projects/web_demo/web_demo/api/react_app/__init__.py deleted file mode 100644 index b93589a026e66a366eddc7257cf61393cb448789..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/react_app/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -from pathlib import Path -from flask import Blueprint -from ..extentions import app, Api -from .react_app_view import ReactAppView -from loguru import logger - -folder = Path(app.config.get("REACT_APP_DIST", "../../web/dist/")).resolve() -logger.info(f"react_app folder: {folder}") -react_app_blue = Blueprint('react_app', __name__, static_folder=folder, static_url_path='', template_folder=folder) -react_app_api = Api(react_app_blue, prefix='') -react_app_api.add_resource(ReactAppView, '/') \ No newline at end of file diff --git a/projects/web_demo/web_demo/api/react_app/react_app_view.py b/projects/web_demo/web_demo/api/react_app/react_app_view.py deleted file mode 100644 index 7c2ff82a54483acb77c30475c29b968fec3610e1..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/api/react_app/react_app_view.py +++ /dev/null @@ -1,11 +0,0 @@ -from flask import render_template, Response -from flask_restful import Resource - - -class ReactAppView(Resource): - def get(self): - # 创建自定义的响应对象 - rendered_template = render_template('index.html') - response = Response(rendered_template, mimetype='text/html') - - return response diff --git a/projects/web_demo/web_demo/app.py b/projects/web_demo/web_demo/app.py deleted file mode 100644 index 61a01559793965bdfef393b0638b190d450fe013..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/app.py +++ /dev/null @@ -1,54 +0,0 @@ -import socket -from api import create_app -from pathlib import Path -import yaml - - -def get_local_ip(): - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.connect(('8.8.8.8', 80)) # Google DNS 服务器 - ip_address = sock.getsockname()[0] - sock.close() - return ip_address - - -current_file_path = Path(__file__).resolve() -base_dir = current_file_path.parent -config_path = base_dir / "config/config.yaml" - - -class ConfigMap(dict): - __setattr__ = dict.__setitem__ - __getattr__ = dict.__getitem__ - - -with open(str(config_path), mode='r', encoding='utf-8') as fd: - data = yaml.load(fd, Loader=yaml.FullLoader) - _config = data.get(data.get("CurrentConfig", "DevelopmentConfig")) -config = ConfigMap() -for k, v in _config.items(): - config[k] = v -config['base_dir'] = base_dir -database = _config.get("database") -if database: - if database.get("type") == "sqlite": - database_uri = f'sqlite:///{base_dir}/{database.get("path")}' - elif database.get("type") == "mysql": - database_uri = f'mysql+pymysql://{database.get("user")}:{database.get("password")}@{database.get("host")}:{database.get("port")}/{database.get("database")}?' - else: - database_uri = '' - config['SQLALCHEMY_DATABASE_URI'] = database_uri - -ip_address = get_local_ip() -port = config.get("PORT", 5559) -# 配置 SERVER_NAME -config['SERVER_NAME'] = f'{ip_address}:{port}' -# 配置 APPLICATION_ROOT -config['APPLICATION_ROOT'] = '/' -# 配置 PREFERRED_URL_SCHEME -config['PREFERRED_URL_SCHEME'] = 'http' - -app = create_app(config) - -if __name__ == '__main__': - app.run(host="0.0.0.0", port=port, debug=config.get("DEBUG", False)) diff --git a/projects/web_demo/web_demo/common/__init__.py b/projects/web_demo/web_demo/common/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/projects/web_demo/web_demo/common/custom_response.py b/projects/web_demo/web_demo/common/custom_response.py deleted file mode 100644 index 7d244c1a1c95e27a64a2abaddb51ca580554fa79..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/common/custom_response.py +++ /dev/null @@ -1,23 +0,0 @@ -from flask import jsonify - - -class ResponseCode: - SUCCESS = 200 - PARAM_WARING = 400 - MESSAGE = "success" - - -def generate_response(data=None, code=ResponseCode.SUCCESS, msg=ResponseCode.MESSAGE, **kwargs): - """ - 自定义响应 - :param code:状态码 - :param data:返回数据 - :param msg:返回消息 - :param kwargs: - :return: - """ - msg = msg or 'success' if code == 200 else msg or 'fail' - success = True if code == 200 else False - res = jsonify(dict(code=code, success=success, data=data, msg=msg, **kwargs)) - res.status_code = 200 - return res diff --git a/projects/web_demo/web_demo/common/error_types.py b/projects/web_demo/web_demo/common/error_types.py deleted file mode 100644 index 8624437d69b3180ce72a7e0a800555b6a961e01a..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/common/error_types.py +++ /dev/null @@ -1,45 +0,0 @@ -import json -from flask import request -from werkzeug.exceptions import HTTPException - - -class ApiException(HTTPException): - """API错误基类""" - code = 500 - msg = 'Sorry, we made a mistake Σ(っ °Д °;)っ' - msgZH = "" - error_code = 999 - - def __init__(self, msg=None, msgZH=None, code=None, error_code=None, headers=None): - if code: - self.code = code - if msg: - self.msg = msg - if msgZH: - self.msgZH = msgZH - if error_code: - self.error_code = error_code - super(ApiException, self).__init__(msg, None) - - @staticmethod - def get_error_url(): - """获取出错路由和请求方式""" - method = request.method - full_path = str(request.full_path) - main_path = full_path.split('?')[0] - res = method + ' ' + main_path - return res - - def get_body(self, environ=None, scope=None): - """异常返回信息""" - body = dict( - msg=self.msg, - error_code=self.error_code, - request=self.get_error_url() - ) - text = json.dumps(body) - return text - - def get_headers(self, environ=None, scope=None): - """异常返回格式""" - return [("Content-Type", "application/json")] \ No newline at end of file diff --git a/projects/web_demo/web_demo/common/ext.py b/projects/web_demo/web_demo/common/ext.py deleted file mode 100644 index ef91a5323ede7cc87322c4482bc1db773db1ca89..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/common/ext.py +++ /dev/null @@ -1,94 +0,0 @@ -import hashlib -import mimetypes -import urllib.parse - - -def is_pdf(filename, file): - """ - 判断文件是否为PDF格式,支持中文名和特殊字符。 - - :param filename: 文件名 - :param file: 文件对象 - :return: 如果文件是PDF格式,则返回True,否则返回False - """ - try: - # 对文件名进行URL解码,处理特殊字符 - decoded_filename = urllib.parse.unquote(filename) - - # 检查MIME类型 - mime_type, _ = mimetypes.guess_type(decoded_filename) - print(f"Detected MIME type: {mime_type}") - - # 某些情况下mime_type可能为None,需要特殊处理 - if mime_type is None: - # 只检查文件内容的PDF标识 - file_start = file.read(5) - file.seek(0) # 重置文件指针 - return file_start.startswith(b'%PDF-') - - if mime_type != 'application/pdf': - return False - - # 检查文件内容的PDF标识 - file_start = file.read(5) - file.seek(0) # 重置文件指针 - if not file_start.startswith(b'%PDF-'): - return False - - return True - - except Exception as e: - print(f"Error checking PDF format: {str(e)}") - # 发生错误时,仍然尝试通过文件头判断 - try: - file_start = file.read(5) - file.seek(0) - return file_start.startswith(b'%PDF-') - except: - return False - - -def url_is_pdf(file): - """ - 判断文件是否为PDF格式。 - - :param file: 文件对象 - :return: 如果文件是PDF格式,则返回True,否则返回False - """ - # 检查文件内容 - file_start = file.read(5) - file.seek(0) - if not file_start.startswith(b'%PDF-'): - return False - - return True - - -def calculate_file_hash(file, algorithm='sha256'): - """ - 计算给定文件的哈希值。 - - :param file: 文件对象 - :param algorithm: 哈希算法的名字,如:'sha256', 'md5', 'sha1'等 - :return: 文件的哈希值 - """ - hash_func = getattr(hashlib, algorithm)() - block_size = 65536 # 64KB chunks - # with open(file_path, 'rb') as file: - buffer = file.read(block_size) - while len(buffer) > 0: - hash_func.update(buffer) - buffer = file.read(block_size) - file.seek(0) - return hash_func.hexdigest() - - -def singleton_func(cls): - instance = {} - - def _singleton(*args, **kwargs): - if cls not in instance: - instance[cls] = cls(*args, **kwargs) - return instance[cls] - - return _singleton diff --git a/projects/web_demo/web_demo/common/import_models.py b/projects/web_demo/web_demo/common/import_models.py deleted file mode 100644 index 06af38e31ac922c8c37dba3b717492ad871885a8..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/common/import_models.py +++ /dev/null @@ -1 +0,0 @@ -from api.analysis.models import * \ No newline at end of file diff --git a/projects/web_demo/web_demo/common/logger.py b/projects/web_demo/web_demo/common/logger.py deleted file mode 100644 index b994afc9fa0f88d48feb7daf80642baf84f77816..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/common/logger.py +++ /dev/null @@ -1,19 +0,0 @@ -import os -from loguru import logger -from pathlib import Path -from datetime import datetime - - -def setup_log(config): - """ - Setup logging - :param config: config file - :return: - """ - log_path = os.path.join(Path(__file__).parent.parent, "log") - if not Path(log_path).exists(): - Path(log_path).mkdir(parents=True, exist_ok=True) - log_level = config.get("LOG_LEVEL") - log_name = f'log_{datetime.now().strftime("%Y-%m-%d")}.log' - log_file_path = os.path.join(log_path, log_name) - logger.add(str(log_file_path), rotation='00:00', encoding='utf-8', level=log_level, enqueue=True) diff --git a/projects/web_demo/web_demo/common/mk_markdown/__init__.py b/projects/web_demo/web_demo/common/mk_markdown/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/projects/web_demo/web_demo/common/mk_markdown/libs/__init__.py b/projects/web_demo/web_demo/common/mk_markdown/libs/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/projects/web_demo/web_demo/common/mk_markdown/libs/language.py b/projects/web_demo/web_demo/common/mk_markdown/libs/language.py deleted file mode 100644 index 396c9008d6de98038fc2047350d47c81af98013c..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/common/mk_markdown/libs/language.py +++ /dev/null @@ -1,36 +0,0 @@ -import os -import unicodedata - -if not os.getenv("FTLANG_CACHE"): - current_file_path = os.path.abspath(__file__) - current_dir = os.path.dirname(current_file_path) - root_dir = os.path.dirname(current_dir) - ftlang_cache_dir = os.path.join(root_dir, 'resources', 'fasttext-langdetect') - os.environ["FTLANG_CACHE"] = str(ftlang_cache_dir) - # print(os.getenv("FTLANG_CACHE")) - -from fast_langdetect import detect_language - - -def detect_lang(text: str) -> str: - - if len(text) == 0: - return "" - try: - lang_upper = detect_language(text) - except: - html_no_ctrl_chars = ''.join([l for l in text if unicodedata.category(l)[0] not in ['C', ]]) - lang_upper = detect_language(html_no_ctrl_chars) - try: - lang = lang_upper.lower() - except: - lang = "" - return lang - - -if __name__ == '__main__': - print(os.getenv("FTLANG_CACHE")) - print(detect_lang("This is a test.")) - print(detect_lang("This is a test")) - print(detect_lang("这个是中文测试。")) - print(detect_lang("这个是中文测试。")) diff --git a/projects/web_demo/web_demo/common/mk_markdown/libs/markdown_utils.py b/projects/web_demo/web_demo/common/mk_markdown/libs/markdown_utils.py deleted file mode 100644 index 5708b477e2cad08805155ffe7930281e77517cf3..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/common/mk_markdown/libs/markdown_utils.py +++ /dev/null @@ -1,31 +0,0 @@ -import re - - -def escape_special_markdown_char(pymu_blocks): - """ - 转义正文里对markdown语法有特殊意义的字符 - """ - special_chars = ["*", "`", "~", "$"] - for blk in pymu_blocks: - for line in blk['lines']: - for span in line['spans']: - for char in special_chars: - span_text = span['text'] - span_type = span.get("_type", None) - if span_type in ['inline-equation', 'interline-equation']: - continue - elif span_text: - span['text'] = span['text'].replace(char, "\\" + char) - - return pymu_blocks - - -def ocr_escape_special_markdown_char(content): - """ - 转义正文里对markdown语法有特殊意义的字符 - """ - special_chars = ["*", "`", "~", "$"] - for char in special_chars: - content = content.replace(char, "\\" + char) - - return content diff --git a/projects/web_demo/web_demo/common/mk_markdown/libs/ocr_content_type.py b/projects/web_demo/web_demo/common/mk_markdown/libs/ocr_content_type.py deleted file mode 100644 index 749c16f94ee7c96ca43d3fb9e10914a3aef43736..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/common/mk_markdown/libs/ocr_content_type.py +++ /dev/null @@ -1,38 +0,0 @@ -class ContentType: - Image = 'image' - Table = 'table' - Text = 'text' - InlineEquation = 'inline_equation' - InterlineEquation = 'interline_equation' - - -class BlockType: - Image = 'image' - ImageBody = 'image_body' - ImageCaption = 'image_caption' - ImageFootnote = 'image_footnote' - Table = 'table' - TableBody = 'table_body' - TableCaption = 'table_caption' - TableFootnote = 'table_footnote' - Text = 'text' - Title = 'title' - InterlineEquation = 'interline_equation' - Footnote = 'footnote' - Discarded = 'discarded' - - -class CategoryId: - Title = 0 - Text = 1 - Abandon = 2 - ImageBody = 3 - ImageCaption = 4 - TableBody = 5 - TableCaption = 6 - TableFootnote = 7 - InterlineEquation_Layout = 8 - InlineEquation = 13 - InterlineEquation_YOLO = 14 - OcrText = 15 - ImageFootnote = 101 diff --git a/projects/web_demo/web_demo/common/mk_markdown/mk_markdown.py b/projects/web_demo/web_demo/common/mk_markdown/mk_markdown.py deleted file mode 100644 index 7683efa3f69aa8840c3aef2b58f50021a462b574..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/common/mk_markdown/mk_markdown.py +++ /dev/null @@ -1,169 +0,0 @@ -import re -import wordninja -from .libs.language import detect_lang -from .libs.markdown_utils import ocr_escape_special_markdown_char -from .libs.ocr_content_type import BlockType, ContentType - - -def __is_hyphen_at_line_end(line): - """ - Check if a line ends with one or more letters followed by a hyphen. - - Args: - line (str): The line of text to check. - - Returns: - bool: True if the line ends with one or more letters followed by a hyphen, False otherwise. - """ - # Use regex to check if the line ends with one or more letters followed by a hyphen - return bool(re.search(r'[A-Za-z]+-\s*$', line)) - - -def split_long_words(text): - segments = text.split(' ') - for i in range(len(segments)): - words = re.findall(r'\w+|[^\w]', segments[i], re.UNICODE) - for j in range(len(words)): - if len(words[j]) > 10: - words[j] = ' '.join(wordninja.split(words[j])) - segments[i] = ''.join(words) - return ' '.join(segments) - - -def join_path(*args): - return ''.join(str(s).rstrip('/') for s in args) - - -def ocr_mk_mm_markdown_with_para_and_pagination(pdf_info_dict: list, - img_buket_path): - markdown_with_para_and_pagination = [] - page_no = 0 - for page_info in pdf_info_dict: - paras_of_layout = page_info.get('para_blocks') - if not paras_of_layout: - continue - page_markdown = ocr_mk_markdown_with_para_core_v2( - paras_of_layout, 'mm', img_buket_path) - markdown_with_para_and_pagination.append({ - 'page_no': - page_no, - 'md_content': - '\n\n'.join(page_markdown) - }) - page_no += 1 - return markdown_with_para_and_pagination - - -def merge_para_with_text(para_block): - def detect_language(text): - en_pattern = r'[a-zA-Z]+' - en_matches = re.findall(en_pattern, text) - en_length = sum(len(match) for match in en_matches) - if len(text) > 0: - if en_length / len(text) >= 0.5: - return 'en' - else: - return 'unknown' - else: - return 'empty' - - para_text = '' - for line in para_block['lines']: - line_text = '' - line_lang = '' - for span in line['spans']: - span_type = span['type'] - if span_type == ContentType.Text: - line_text += span['content'].strip() - if line_text != '': - line_lang = detect_lang(line_text) - for span in line['spans']: - span_type = span['type'] - content = '' - if span_type == ContentType.Text: - content = span['content'] - # language = detect_lang(content) - language = detect_language(content) - if language == 'en': # 只对英文长词进行分词处理,中文分词会丢失文本 - content = ocr_escape_special_markdown_char( - split_long_words(content)) - else: - content = ocr_escape_special_markdown_char(content) - elif span_type == ContentType.InlineEquation: - content = f" ${span['content']}$ " - elif span_type == ContentType.InterlineEquation: - content = f"\n$$\n{span['content']}\n$$\n" - - if content != '': - langs = ['zh', 'ja', 'ko'] - if line_lang in langs: # 遇到一些一个字一个span的文档,这种单字语言判断不准,需要用整行文本判断 - para_text += content # 中文/日语/韩文语境下,content间不需要空格分隔 - elif line_lang == 'en': - # 如果是前一行带有-连字符,那么末尾不应该加空格 - if __is_hyphen_at_line_end(content): - para_text += content[:-1] - else: - para_text += content + ' ' - else: - para_text += content + ' ' # 西方文本语境下 content间需要空格分隔 - return para_text - - -def ocr_mk_markdown_with_para_core_v2(paras_of_layout, - mode, - img_buket_path=''): - page_markdown = [] - for para_block in paras_of_layout: - para_text = '' - para_type = para_block['type'] - if para_type == BlockType.Text: - para_text = merge_para_with_text(para_block) - elif para_type == BlockType.Title: - para_text = f'# {merge_para_with_text(para_block)}' - elif para_type == BlockType.InterlineEquation: - para_text = merge_para_with_text(para_block) - elif para_type == BlockType.Image: - if mode == 'nlp': - continue - elif mode == 'mm': - for block in para_block['blocks']: # 1st.拼image_body - if block['type'] == BlockType.ImageBody: - for line in block['lines']: - for span in line['spans']: - if span['type'] == ContentType.Image: - para_text += f"\n![]({join_path(img_buket_path, span['image_path'])}) \n" - for block in para_block['blocks']: # 2nd.拼image_caption - if block['type'] == BlockType.ImageCaption: - para_text += merge_para_with_text(block) - for block in para_block['blocks']: # 2nd.拼image_caption - if block['type'] == BlockType.ImageFootnote: - para_text += merge_para_with_text(block) - elif para_type == BlockType.Table: - if mode == 'nlp': - continue - elif mode == 'mm': - for block in para_block['blocks']: # 1st.拼table_caption - if block['type'] == BlockType.TableCaption: - para_text += merge_para_with_text(block) - for block in para_block['blocks']: # 2nd.拼table_body - if block['type'] == BlockType.TableBody: - for line in block['lines']: - for span in line['spans']: - if span['type'] == ContentType.Table: - # if processed by table model - if span.get('latex', ''): - para_text += f"\n\n$\n {span['latex']}\n$\n\n" - elif span.get('html', ''): - para_text += f"\n\n{span['html']}\n\n" - else: - para_text += f"\n![]({join_path(img_buket_path, span['image_path'])}) \n" - for block in para_block['blocks']: # 3rd.拼table_footnote - if block['type'] == BlockType.TableFootnote: - para_text += merge_para_with_text(block) - - if para_text.strip() == '': - continue - else: - page_markdown.append(para_text.strip() + ' ') - - return page_markdown diff --git a/projects/web_demo/web_demo/common/mk_markdown/resources/fasttext-langdetect/lid.176.ftz b/projects/web_demo/web_demo/common/mk_markdown/resources/fasttext-langdetect/lid.176.ftz deleted file mode 100644 index 1fb85b357b22f67f019567f0e7003f4d49bda7a0..0000000000000000000000000000000000000000 Binary files a/projects/web_demo/web_demo/common/mk_markdown/resources/fasttext-langdetect/lid.176.ftz and /dev/null differ diff --git a/projects/web_demo/web_demo/common/web_hook.py b/projects/web_demo/web_demo/common/web_hook.py deleted file mode 100644 index 41982a0a90eb0ede49aa0e2659e2fb02d26fd99d..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/common/web_hook.py +++ /dev/null @@ -1,9 +0,0 @@ - -def before_request(): - return None - - -def after_request(response): - response.headers.add('Access-Control-Allow-Origin', '*') - response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization') - return response diff --git a/projects/web_demo/web_demo/config/__init__.py b/projects/web_demo/web_demo/config/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/projects/web_demo/web_demo/config/config.yaml b/projects/web_demo/web_demo/config/config.yaml deleted file mode 100644 index 9c48062b9c6e584256f0281e58e36f36e95fad6a..0000000000000000000000000000000000000000 --- a/projects/web_demo/web_demo/config/config.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# 基本配置 -BaseConfig: &base - DEBUG: false - PORT: 5559 - LOG_LEVEL: "DEBUG" - SQLALCHEMY_TRACK_MODIFICATIONS: true - SQLALCHEMY_DATABASE_URI: "" - PROPAGATE_EXCEPTIONS: true - SECRET_KEY: "#$%^&**$##*(*^%%$**((&" - JWT_SECRET_KEY: "#$%^&**$##*(*^%%$**((&" - JWT_ACCESS_TOKEN_EXPIRES: 3600 - PDF_UPLOAD_FOLDER: "upload_pdf" - PDF_ANALYSIS_FOLDER: "analysis_pdf" - # 前端项目打包的路径 - REACT_APP_DIST: "../../web/dist/" - # 文件访问路径 - FILE_API: "/api/v2/analysis/pdf_img?as_attachment=False" - -# 开发配置 -DevelopmentConfig: - <<: *base - database: - type: sqlite - path: config/mineru_web.db - -# 生产配置 -ProductionConfig: - <<: *base - -# 测试配置 -TestingConfig: - <<: *base - -# 当前使用配置 -CurrentConfig: "DevelopmentConfig" diff --git a/projects/web_demo/web_demo/config/mineru_web.db b/projects/web_demo/web_demo/config/mineru_web.db deleted file mode 100644 index fcac36060408e8c406a56b338c239853183f09b5..0000000000000000000000000000000000000000 Binary files a/projects/web_demo/web_demo/config/mineru_web.db and /dev/null differ diff --git a/projects/web_demo/web_demo/static/__init__.py b/projects/web_demo/web_demo/static/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..3df24e68eee05a0214bd3a5fcaa47f22d6b5dd52 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,114 @@ +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "mineru" +dynamic = ["version"] +license = {text = "AGPL-3.0"} +description = "A practical tool for converting PDF to Markdown" +readme = "README.md" +requires-python = ">=3.10,<3.14" +keywords = ["magic-pdf", "mineru", "MinerU", "convert", "pdf", "markdown"] +classifiers = [ + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", +] +dependencies = [ + "boto3>=1.28.43", + "click>=8.1.7", + "loguru>=0.7.2", + "numpy>=1.21.6", + "pdfminer.six==20250506", + "tqdm>=4.67.1", + "requests", + "httpx", + "pillow>=11.0.0", + "pypdfium2>=4.30.0", + "pypdf>=5.6.0", + "reportlab", + "pdftext>=0.6.2", + "modelscope>=1.26.0", + "huggingface-hub>=0.32.4", + "json-repair>=0.46.2", +] + +[project.optional-dependencies] +vlm = [ + "transformers>=4.51.1", + "torch>=2.6.0", + "accelerate>=1.5.1", + "pydantic", +] +sglang = [ + "sglang[all]>=0.4.7", +] +pipeline = [ + "matplotlib>=3.10,<4", + "ultralytics>=8.3.48,<9", + "doclayout_yolo==0.0.4", + "dill>=0.3.8,<1", + "rapid_table>=1.0.5,<2.0.0", + "PyYAML>=6.0.2,<7", + "ftfy>=6.3.1,<7", + "openai>=1.70.0,<2", + "shapely>=2.0.7,<3", + "pyclipper>=1.3.0,<2", + "omegaconf>=2.3.0,<3", + "torch>=2.2.2,!=2.5.0,!=2.5.1,<3", + "torchvision", + "transformers>=4.49.0,!=4.51.0,<5.0.0", + "fast-langdetect>=0.2.3,<0.3.0", +] +core = [ + "mineru[vlm]", + "mineru[pipeline]", +] +all = [ + "mineru[core]", + "mineru[sglang]", +] +pipeline_old_linux = [ + "matplotlib>=3.10,<=3.10.1", + "ultralytics>=8.3.48,<=8.3.104", + "doclayout_yolo==0.0.4", + "dill==0.3.8", + "PyYAML==6.0.2", + "ftfy==6.3.1", + "openai==1.71.0", + "shapely==2.1.0", + "pyclipper==1.3.0.post6", + "omegaconf==2.3.0", + "albumentations==1.4.20", + "rapid_table==1.0.3", + "torch>=2.2.2,!=2.5.0,!=2.5.1,<3", + "torchvision", + "transformers>=4.49.0,!=4.51.0,<5.0.0", + "fast-langdetect>=0.2.3,<0.3.0", +] + +[project.urls] +Home = "https://mineru.net/" +Repository = "https://github.com/opendatalab/MinerU" + +[project.scripts] +mineru = "mineru.cli:client.main" +mineru-sglang-server = "mineru.cli.vlm_sglang_server:main" +mineru-models-download = "mineru.cli.models_download:download_models" + +[tool.setuptools.dynamic] +version = {attr = "mineru.version.__version__"} + +[tool.setuptools.packages.find] +include = ["mineru*"] +namespaces = false + +[tool.setuptools.package-data] +"mineru" = ["resources/**"] +"mineru.model.ocr.paddleocr2pytorch.pytorchocr.utils" = ["resources/**"] + +[tool.setuptools] +include-package-data = true +zip-safe = false diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 96b47efc93eb17b9140284209e408c80037c224f..0000000000000000000000000000000000000000 --- a/requirements.txt +++ /dev/null @@ -1,15 +0,0 @@ -boto3>=1.28.43 -Brotli>=1.1.0 -click>=8.1.7 -fast-langdetect>=0.2.3,<0.3.0 -loguru>=0.6.0 -numpy>=1.21.6 -pydantic>=2.7.2,<2.11 -PyMuPDF>=1.24.9,<1.25.0 -scikit-learn>=1.0.2 -torch>=2.2.2,!=2.5.0,!=2.5.1,<3 -torchvision -transformers>=4.49.0,!=4.51.0,<5.0.0 -pdfminer.six==20250506 -tqdm>=4.67.1 -# The requirements.txt must ensure that only necessary external dependencies are introduced. If there are new dependencies to add, please contact the project administrator. diff --git a/scripts/download_models.py b/scripts/download_models.py deleted file mode 100644 index 626473d7b52a553e6f70cbdadca9365aa9601d36..0000000000000000000000000000000000000000 --- a/scripts/download_models.py +++ /dev/null @@ -1,67 +0,0 @@ -import json -import shutil -import os - -import requests -from modelscope import snapshot_download - - -def download_json(url): - # 下载JSON文件 - response = requests.get(url) - response.raise_for_status() # 检查请求是否成功 - return response.json() - - -def download_and_modify_json(url, local_filename, modifications): - if os.path.exists(local_filename): - data = json.load(open(local_filename)) - config_version = data.get('config_version', '0.0.0') - if config_version < '1.2.0': - data = download_json(url) - else: - data = download_json(url) - - # 修改内容 - for key, value in modifications.items(): - data[key] = value - - # 保存修改后的内容 - with open(local_filename, 'w', encoding='utf-8') as f: - json.dump(data, f, ensure_ascii=False, indent=4) - - -if __name__ == '__main__': - mineru_patterns = [ - # "models/Layout/LayoutLMv3/*", - "models/Layout/YOLO/*", - "models/MFD/YOLO/*", - "models/MFR/unimernet_hf_small_2503/*", - "models/OCR/paddleocr_torch/*", - # "models/TabRec/TableMaster/*", - # "models/TabRec/StructEqTable/*", - ] - model_dir = snapshot_download('opendatalab/PDF-Extract-Kit-1.0', allow_patterns=mineru_patterns) - layoutreader_model_dir = snapshot_download('ppaanngggg/layoutreader') - model_dir = model_dir + '/models' - print(f'model_dir is: {model_dir}') - print(f'layoutreader_model_dir is: {layoutreader_model_dir}') - - # paddleocr_model_dir = model_dir + '/OCR/paddleocr' - # user_paddleocr_dir = os.path.expanduser('~/.paddleocr') - # if os.path.exists(user_paddleocr_dir): - # shutil.rmtree(user_paddleocr_dir) - # shutil.copytree(paddleocr_model_dir, user_paddleocr_dir) - - json_url = 'https://gcore.jsdelivr.net/gh/opendatalab/MinerU@master/magic-pdf.template.json' - config_file_name = 'magic-pdf.json' - home_dir = os.path.expanduser('~') - config_file = os.path.join(home_dir, config_file_name) - - json_mods = { - 'models-dir': model_dir, - 'layoutreader-model-dir': layoutreader_model_dir, - } - - download_and_modify_json(json_url, config_file, json_mods) - print(f'The configuration file has been configured successfully, the path is: {config_file}') diff --git a/scripts/download_models_hf.py b/scripts/download_models_hf.py deleted file mode 100644 index 666540dad9a6b8e240f2f5cbf420bbfaa3ae79d5..0000000000000000000000000000000000000000 --- a/scripts/download_models_hf.py +++ /dev/null @@ -1,74 +0,0 @@ -import json -import os -import shutil - -import requests -from huggingface_hub import snapshot_download - - -def download_json(url): - # 下载JSON文件 - response = requests.get(url) - response.raise_for_status() # 检查请求是否成功 - return response.json() - - -def download_and_modify_json(url, local_filename, modifications): - if os.path.exists(local_filename): - data = json.load(open(local_filename)) - config_version = data.get('config_version', '0.0.0') - if config_version < '1.2.0': - data = download_json(url) - else: - data = download_json(url) - - # 修改内容 - for key, value in modifications.items(): - data[key] = value - - # 保存修改后的内容 - with open(local_filename, 'w', encoding='utf-8') as f: - json.dump(data, f, ensure_ascii=False, indent=4) - - -if __name__ == '__main__': - - mineru_patterns = [ - # "models/Layout/LayoutLMv3/*", - "models/Layout/YOLO/*", - "models/MFD/YOLO/*", - "models/MFR/unimernet_hf_small_2503/*", - "models/OCR/paddleocr_torch/*", - # "models/TabRec/TableMaster/*", - # "models/TabRec/StructEqTable/*", - ] - model_dir = snapshot_download('opendatalab/PDF-Extract-Kit-1.0', allow_patterns=mineru_patterns) - - layoutreader_pattern = [ - "*.json", - "*.safetensors", - ] - layoutreader_model_dir = snapshot_download('hantian/layoutreader', allow_patterns=layoutreader_pattern) - - model_dir = model_dir + '/models' - print(f'model_dir is: {model_dir}') - print(f'layoutreader_model_dir is: {layoutreader_model_dir}') - - # paddleocr_model_dir = model_dir + '/OCR/paddleocr' - # user_paddleocr_dir = os.path.expanduser('~/.paddleocr') - # if os.path.exists(user_paddleocr_dir): - # shutil.rmtree(user_paddleocr_dir) - # shutil.copytree(paddleocr_model_dir, user_paddleocr_dir) - - json_url = 'https://github.com/opendatalab/MinerU/raw/master/magic-pdf.template.json' - config_file_name = 'magic-pdf.json' - home_dir = os.path.expanduser('~') - config_file = os.path.join(home_dir, config_file_name) - - json_mods = { - 'models-dir': model_dir, - 'layoutreader-model-dir': layoutreader_model_dir, - } - - download_and_modify_json(json_url, config_file, json_mods) - print(f'The configuration file has been configured successfully, the path is: {config_file}') diff --git a/setup.py b/setup.py deleted file mode 100644 index dedf035e0f7ac488dedd48c2182290fcb1c2e285..0000000000000000000000000000000000000000 --- a/setup.py +++ /dev/null @@ -1,93 +0,0 @@ -from pathlib import Path -from setuptools import setup, find_packages -from magic_pdf.libs.version import __version__ - - -def parse_requirements(filename): - with open(filename) as f: - lines = f.read().splitlines() - - requires = [] - - for line in lines: - if "http" in line: - pkg_name_without_url = line.split('@')[0].strip() - requires.append(pkg_name_without_url) - else: - requires.append(line) - - return requires - - -if __name__ == '__main__': - with Path(Path(__file__).parent, - 'README.md').open(encoding='utf-8') as file: - long_description = file.read() - setup( - name="magic_pdf", # 项目名 - version=__version__, # 自动从tag中获取版本号 - license="AGPL-3.0", - packages=find_packages() + ["magic_pdf.resources"] + ["magic_pdf.model.sub_modules.ocr.paddleocr2pytorch.pytorchocr.utils.resources"], # 包含所有的包 - package_data={ - "magic_pdf.resources": ["**"], # 包含magic_pdf.resources目录下的所有文件 - "magic_pdf.model.sub_modules.ocr.paddleocr2pytorch.pytorchocr.utils.resources": ["**"], # pytorchocr.resources目录下的所有文件 - }, - install_requires=parse_requirements('requirements.txt'), # 项目依赖的第三方库 - extras_require={ - "lite": [ - "paddleocr==2.7.3", - "paddlepaddle==3.0.0b1;platform_system=='Linux'", - "paddlepaddle==2.6.1;platform_system=='Windows' or platform_system=='Darwin'", - ], - "full": [ - "matplotlib>=3.10,<4", - "ultralytics>=8.3.48,<9", # yolov8,公式检测 - "doclayout_yolo==0.0.2b1", # doclayout_yolo - "dill>=0.3.8,<1", # doclayout_yolo - "rapid_table>=1.0.5,<2.0.0", # rapid_table - "PyYAML>=6.0.2,<7", # yaml - "ftfy>=6.3.1,<7", # unimernet_hf - "openai>=1.70.0,<2", # openai SDK - "shapely>=2.0.7,<3", # imgaug-paddleocr2pytorch - "pyclipper>=1.3.0,<2", # paddleocr2pytorch - "omegaconf>=2.3.0,<3", # paddleocr2pytorch - ], - "full_old_linux": [ - "matplotlib>=3.10,<=3.10.1", - "ultralytics>=8.3.48,<=8.3.104", # yolov8,公式检测 - "doclayout_yolo==0.0.2b1", # doclayout_yolo - "dill==0.3.8", # doclayout_yolo - "PyYAML==6.0.2", # yaml - "ftfy==6.3.1", # unimernet_hf - "openai==1.71.0", # openai SDK - "shapely==2.1.0", # imgaug-paddleocr2pytorch - "pyclipper==1.3.0.post6", # paddleocr2pytorch - "omegaconf==2.3.0", # paddleocr2pytorch - "albumentations==1.4.20", # 1.4.21引入的simsimd不支持2019年及更早的linux系统 - "rapid_table==1.0.3", # rapid_table新版本依赖的onnxruntime不支持2019年及更早的linux系统 - ], - }, - description="A practical tool for converting PDF to Markdown", # 简短描述 - long_description=long_description, # 详细描述 - long_description_content_type="text/markdown", # 如果README是Markdown格式 - project_urls={ - "Home": "https://mineru.net/", - "Repository": "https://github.com/opendatalab/MinerU", - }, - keywords=["magic-pdf, mineru, MinerU, convert, pdf, markdown"], - classifiers=[ - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - ], - python_requires=">=3.10,<3.14", # 项目依赖的 Python 版本 - entry_points={ - "console_scripts": [ - "magic-pdf = magic_pdf.tools.cli:cli", - "magic-pdf-dev = magic_pdf.tools.cli_dev:cli" - ], - }, # 项目提供的可执行命令 - include_package_data=True, # 是否包含非代码文件,如数据文件、配置文件等 - zip_safe=False, # 是否使用 zip 文件格式打包,一般设为 False - ) diff --git a/update_version.py b/update_version.py index b51081625a051ded30a2f228fd67468177c59c5e..418fa5bb18d56851b42eef363e2c0936cbbfe2be 100644 --- a/update_version.py +++ b/update_version.py @@ -7,17 +7,17 @@ def get_version(): try: version = subprocess.check_output(command).decode().strip() version_parts = version.split("-") - if len(version_parts) > 1 and version_parts[0].startswith("magic_pdf"): + if len(version_parts) > 1 and version_parts[0].startswith("mineru"): return version_parts[1] else: - raise ValueError(f"Invalid version tag {version}. Expected format is magic_pdf--released.") + raise ValueError(f"Invalid version tag {version}. Expected format is mineru--released.") except Exception as e: print(e) return "0.0.0" def write_version_to_commons(version): - commons_path = os.path.join(os.path.dirname(__file__), 'magic_pdf', 'libs', 'version.py') + commons_path = os.path.join(os.path.dirname(__file__), 'mineru', 'version.py') with open(commons_path, 'w') as f: f.write(f'__version__ = "{version}"\n')