Compare commits

...

24 Commits

Author SHA1 Message Date
Anthony Stirling
bc2b15cbae Merge branch 'main' into bugFixes 2025-02-07 13:11:58 +00:00
Anthony Stirling
09c1ee0c34 formatting 2025-02-07 13:10:11 +00:00
thiagoor-cpu
242aa5eae1 Update messages_pt_BR.properties (#2905)
Up-to-date 0.40.2

# Description of Changes

Up-to-date 0.40.2

Closes #(issue_number)

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-07 13:08:31 +00:00
Anthony Stirling
72ee00a264 pipeline bug, doc bugs, auto split new URL and doc 2025-02-07 13:08:12 +00:00
a
c62008a183 Merge remote-tracking branch 'origin/main' into pdfafixes 2025-02-07 13:06:57 +00:00
Anthony Stirling
bf65c456d1 PDFA fixes (#2896)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-07 13:06:19 +00:00
Anthony Stirling
e0c83adc9f fix docker merge 2025-02-07 12:55:39 +00:00
reecebrowne
26720c5018 Fix for tab issue (#2898)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-06 17:08:33 +00:00
Anthony Stirling
1eee6ee356 use libreoffice for pdfa 2025-02-06 15:55:22 +00:00
reecebrowne
2ed07e3fcb Homepage hotfix (#2894)
# Description of Changes

Fix replace-and-invert-color-pdf nav
Fix legacy homepage search
Closes #(2888)

---

## Checklist

### General

- [ x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.

---------

Co-authored-by: Reece Browne <reece@stirling.pdf>
2025-02-06 10:38:14 +00:00
dependabot[bot]
e382d254ee Bump org.panteleyev.jpackageplugin from 1.6.0 to 1.6.1 (#2851)
Bumps org.panteleyev.jpackageplugin from 1.6.0 to 1.6.1.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.panteleyev.jpackageplugin&package-manager=gradle&previous-version=1.6.0&new-version=1.6.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2025-02-04 21:04:49 +00:00
Abdur Rahman
507d21772d Fix issue #2842: Handle qpdf exit code 3 as success with warnings (#2883)
# Description of Changes

Please provide a summary of the changes, including:

- **What was changed**:
- Modified the `ProcessExecutor` class to accept exit code `3` from
**qpdf** as a success with warnings.
- Added a check to ensure that only **qpdf**’s exit code `3` is treated
as a warning.
- Added a warning log for **qpdf** exit code `3` to provide better
visibility into the repair process.

- **Why the change was made**:
- The repair process was failing when **qpdf** returned exit code `3`,
even though the operation succeeded with warnings. This caused
unnecessary errors for users.
- The changes ensure that PDFs with minor structural issues (e.g.,
mismatched object counts) are still repaired successfully, while logging
warnings for transparency.
- Added a check to ensure that only **qpdf**’s exit code `3` is treated
as a warning, preventing potential issues with other tools that might
use exit code `3` for actual errors.

Closes #2842

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Testing (if applicable)

- [x] I have tested my changes locally.
- Verified that exit code `3` is only treated as a warning for **qpdf**
and not for other tools.

---

### Additional Notes
- The changes align with **qpdf**'s behavior, where exit code `3`
indicates a successful operation with warnings.
- Added a check to ensure that only **qpdf**’s exit code `3` is treated
as a warning, preventing potential issues with other tools.

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2025-02-04 21:01:41 +00:00
Ludy
5bf050d77f removes remnants of verification metadata (#2884)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-04 20:58:06 +00:00
Anthony Stirling
976caeb79d Update sonarqube.yml to remove depreciated cache feature (will update later) (#2885)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-04 20:50:01 +00:00
Anthony Stirling
2d3611fd00 Pipeline fix for some features missing documentation (#2882)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-04 14:07:22 +00:00
reecebrowne
118de1789a Update screenshots (#2875)
# Description of Changes
Updates screenshots for docs
Closes #(issue_number)

---

## Checklist

### General

- [x ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2025-02-04 11:24:35 +00:00
Anthony Stirling
b56d54a35a Update sync_files.yml (#2872)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-04 10:57:04 +00:00
dependabot[bot]
b9bfcd59cd Bump gradle/actions from 4.2.2 to 4.3.0 (#2870)
Bumps [gradle/actions](https://github.com/gradle/actions) from 4.2.2 to
4.3.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/gradle/actions/releases">gradle/actions's
releases</a>.</em></p>
<blockquote>
<h2>v4.3.0</h2>
<p>This release brings some significant improvements to cache-cleanup
and dependency-submission:</p>
<ul>
<li>Cleanup cache entries written by newly released Gradle versions (<a
href="https://redirect.github.com/gradle/actions/issues/436">#436</a>)</li>
<li>Use existing Gradle wrapper distribution for cache-cleanup where
possible (<a
href="https://redirect.github.com/gradle/actions/issues/515">#515</a>)</li>
<li>Automatically save each dependency-graph that is submitted by
<code>dependency-submission</code> (<a
href="https://redirect.github.com/gradle/actions/issues/519">#519</a>)</li>
<li>Fix deprecation warnings emitted by Gradle 8.12+ when:
<ul>
<li>Using <code>build-scan-publish: true</code> or Develocity injection
(<a
href="https://redirect.github.com/gradle/actions/issues/543">#543</a>)</li>
<li>Using dependency-submission with an authenticated plugin repository
with Gradle (<a
href="https://redirect.github.com/gradle/actions/issues/541">#541</a>)</li>
</ul>
</li>
<li>Fix warning when using toolchain support with Gradle 7.x (<a
href="https://redirect.github.com/gradle/actions/issues/511">#511</a>)</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Update known wrapper checksums by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>
in <a
href="https://redirect.github.com/gradle/actions/pull/493">gradle/actions#493</a></li>
<li>Fix typo in <code>cache-reporting.ts</code> by <a
href="https://github.com/SimonMarquis"><code>@​SimonMarquis</code></a>
in <a
href="https://redirect.github.com/gradle/actions/pull/492">gradle/actions#492</a></li>
<li>Bump Gradle Wrappers by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>
in <a
href="https://redirect.github.com/gradle/actions/pull/499">gradle/actions#499</a></li>
<li>Bump the github-actions group across 3 directories with 7 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/gradle/actions/pull/510">gradle/actions#510</a></li>
<li>Bump the npm-dependencies group across 1 directory with 6 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/gradle/actions/pull/512">gradle/actions#512</a></li>
<li>Clean-up missing imports for tests by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/513">gradle/actions#513</a></li>
<li>Bump the npm-dependencies group in /sources with 3 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/521">gradle/actions#521</a></li>
<li>Add npm build scans by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/517">gradle/actions#517</a></li>
<li>Avoid env-var interpolation in toolchains.xml by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/518">gradle/actions#518</a></li>
<li>Avoid saving build-results for cache cleanup by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/520">gradle/actions#520</a></li>
<li>Save dependency graph as workflow artifact by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/522">gradle/actions#522</a></li>
<li>Update to CCUDGP 2.1 by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/524">gradle/actions#524</a></li>
<li>Bump references to Develocity Gradle plugin from 3.19 to 3.19.1 by
<a
href="https://github.com/bot-githubaction"><code>@​bot-githubaction</code></a>
in <a
href="https://redirect.github.com/gradle/actions/pull/527">gradle/actions#527</a></li>
<li>Choose best Gradle version to use for cache cleanup by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/526">gradle/actions#526</a></li>
<li>Uppercase cache-encryption-key by <a
href="https://github.com/Goooler"><code>@​Goooler</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/528">gradle/actions#528</a></li>
<li>Attempt to use gradle wrapper for cache cleanup by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/525">gradle/actions#525</a></li>
<li>Document GRADLE_ACTIONS_SKIP_BUILD_RESULT_CAPTURE by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/529">gradle/actions#529</a></li>
<li>Update known wrapper checksums by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>
in <a
href="https://redirect.github.com/gradle/actions/pull/509">gradle/actions#509</a></li>
<li>Bump Gradle Wrappers by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>
in <a
href="https://redirect.github.com/gradle/actions/pull/535">gradle/actions#535</a></li>
<li>Bump the github-actions group across 2 directories with 2 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/gradle/actions/pull/538">gradle/actions#538</a></li>
<li>Update undici to resolve vulnerability by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/536">gradle/actions#536</a></li>
<li>Bump the npm-dependencies group across 1 directory with 2 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/gradle/actions/pull/539">gradle/actions#539</a></li>
<li>Update docs for dependency review by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/540">gradle/actions#540</a></li>
<li>Fix space assignment deprecations in init-scripts by <a
href="https://github.com/bigdaz"><code>@​bigdaz</code></a> in <a
href="https://redirect.github.com/gradle/actions/pull/542">gradle/actions#542</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/SimonMarquis"><code>@​SimonMarquis</code></a>
made their first contribution in <a
href="https://redirect.github.com/gradle/actions/pull/492">gradle/actions#492</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/gradle/actions/compare/v4.2.2...v4.3.0">https://github.com/gradle/actions/compare/v4.2.2...v4.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="94baf225fe"><code>94baf22</code></a>
Fix space assignment deprecations in init-scripts (<a
href="https://redirect.github.com/gradle/actions/issues/542">#542</a>)</li>
<li><a
href="6f10c21ec5"><code>6f10c21</code></a>
Make it easier to produce 'prerelease' versions</li>
<li><a
href="0b492c475f"><code>0b492c4</code></a>
Fix deprecation warnings in develocity init-script</li>
<li><a
href="79bad900c0"><code>79bad90</code></a>
Fix deprecation warnings in dependency-graph init-script</li>
<li><a
href="986922f6a6"><code>986922f</code></a>
Update docs for dependency review (<a
href="https://redirect.github.com/gradle/actions/issues/540">#540</a>)</li>
<li><a
href="65a3beb941"><code>65a3beb</code></a>
[bot] Update dist directory</li>
<li><a
href="0e67f6d83b"><code>0e67f6d</code></a>
Bump the npm-dependencies group across 1 directory with 2 updates</li>
<li><a
href="b6ac71fd86"><code>b6ac71f</code></a>
[bot] Update dist directory</li>
<li><a
href="9053a599ae"><code>9053a59</code></a>
Update undici to resolve vulnerability</li>
<li><a
href="7560c304a6"><code>7560c30</code></a>
Bump the github-actions group across 2 directories with 2 updates</li>
<li>Additional commits viewable in <a
href="0bdd871935...94baf225fe">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=gradle/actions&package-manager=github_actions&previous-version=4.2.2&new-version=4.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2025-02-04 10:42:29 +00:00
albanobattistella
f8adc0f101 Update messages_it_IT.properties (#2865)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-04 10:19:24 +00:00
Anthony Stirling
69d4b52b06 Update sonarqube.yml and removal of gradle keys (#2866)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-04 10:18:02 +00:00
Ludy
5e3612a9b0 Fix: wrong link picture_as_pdf change to img-to-pdf #2867 (#2869)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #2867

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-03 20:08:41 +00:00
kmau
b3a4597ad1 Update messages_it_IT.properties (#2861)
New translation key home.sortBy

# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [X] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [X] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-03 15:20:03 +00:00
reecebrowne
dc46172deb Fixed firefox compatibility and added missing icons to feature pages (#2863)
# Description of Changes

Fixed icon incompatibility with firefox
Added missing icons to feature pages

Closes #(2833)


![image](https://github.com/user-attachments/assets/51ba008a-f6ab-4e29-9a79-99d85d152689)


---

## Checklist

### General

- [ x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ x] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ x] I have performed a self-review of my own code
- [ x] My changes generate no new warnings

### Documentation

- [ x] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ x] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ x] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.

Co-authored-by: Reece Browne <reece@stirling.pdf>
2025-02-03 15:19:18 +00:00
Anthony Stirling
04696dc2aa Create sonarqube.yml (#2862)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-02-03 15:13:46 +00:00
58 changed files with 666 additions and 11861 deletions

View File

@@ -37,12 +37,6 @@ jobs:
java-version: ${{ matrix.jdk-version }}
distribution: "temurin"
- name: PR | Generate verification metadata with signatures and checksums for dependabot[bot]
if: github.event.pull_request.user.login == 'dependabot[bot]'
run: |
./gradlew clean dependencies buildEnvironment spotlessApply --write-verification-metadata sha256 --refresh-dependencies help
./gradlew clean dependencies buildEnvironment spotlessApply --write-verification-metadata sha256,pgp --refresh-keys --export-keys --refresh-dependencies help
- name: Build with Gradle and no spring security
run: ./gradlew clean build
env:
@@ -147,4 +141,4 @@ jobs:
run: |
chmod +x ./testing/test_webpages.sh
chmod +x ./testing/test.sh
./testing/test.sh "${{ github.event.pull_request.user.login == 'dependabot[bot]' }}"
./testing/test.sh

View File

@@ -38,7 +38,7 @@ jobs:
java-version: "17"
distribution: "adopt"
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
- name: check the licenses for compatibility
run: ./gradlew clean checkLicense

View File

@@ -63,7 +63,7 @@ jobs:
java-version: "21"
distribution: "temurin"
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
with:
gradle-version: 8.12
@@ -151,7 +151,7 @@ jobs:
java-version: "21"
distribution: "temurin"
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
with:
gradle-version: 8.12

View File

@@ -30,7 +30,7 @@ jobs:
java-version: "17"
distribution: "temurin"
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
with:
gradle-version: 8.12

View File

@@ -35,7 +35,7 @@ jobs:
java-version: "17"
distribution: "temurin"
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
with:
gradle-version: 8.12

64
.github/workflows/sonarqube.yml vendored Normal file
View File

@@ -0,0 +1,64 @@
on:
push:
branches:
- master
pull_request:
branches: [ "main" ]
workflow_dispatch:
permissions:
pull-requests: read
actions: read
name: Run Sonarqube
jobs:
sonarqube:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4
with:
egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Set up JDK
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
with:
java-version: '17'
distribution: 'temurin'
- name: Build and analyze with Gradle
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
DOCKER_ENABLE_SECURITY: true
STIRLING_PDF_DESKTOP_UI: true
run: |
./gradlew clean build sonar \
-Dsonar.projectKey=Stirling-Tools_Stirling-PDF \
-Dsonar.organization=stirling-tools \
-Dsonar.host.url=https://sonarcloud.io \
-Dsonar.log.level=DEBUG \
--info
- name: Upload Problems Report on Failure
if: failure()
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: gradle-problems-report
path: build/reports/problems/problems-report.html
retention-days: 7
- name: Upload Sonar Logs on Failure
if: failure()
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: sonar-logs
path: |
.scannerwork/report-task.txt
build/sonar/
retention-days: 7

View File

@@ -26,7 +26,7 @@ jobs:
java-version: "17"
distribution: "temurin"
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
- name: Generate Swagger documentation
run: ./gradlew generateOpenApiDocs

View File

@@ -8,8 +8,6 @@ on:
paths:
- "build.gradle"
- "README.md"
- "gradle/verification-keyring.keys"
- "gradle/verification-metadata.xml"
- "src/main/resources/messages_*.properties"
- "src/main/resources/static/3rdPartyLicenses.json"
- "scripts/ignore_translation.toml"
@@ -104,22 +102,6 @@ jobs:
git add README.md
git diff --staged --quiet || git commit -m ":memo: Sync README.md" || echo "no changes"
- name: Generate verification metadata with signatures and checksums
run: |
set -e
if [ -f ./gradle/verification-metadata.xml ]; then
rm ./gradle/verification-metadata.xml
fi
./gradlew clean dependencies buildEnvironment spotlessApply --write-verification-metadata sha256 help
./gradlew clean dependencies buildEnvironment spotlessApply --write-verification-metadata sha256,pgp --refresh-keys --export-keys --refresh-dependencies help
./gradlew clean build
- name: Run git add
run: |
git add gradle/verification-keyring.keys
git add gradle/verification-metadata.xml
git diff --staged --quiet || git commit -m ":memo: Generate verification metadata with signatures and checksums" || echo "no changes"
- name: Create Pull Request
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
with:
@@ -129,11 +111,11 @@ jobs:
author: ${{ needs.read_bot_entries.outputs.committer }}
signoff: true
branch: sync_readme
title: ":globe_with_meridians: Sync Translations + Update README Progress Table + Update Verification Metadata"
title: ":globe_with_meridians: Sync Translations + Update README Progress Table"
body: |
### Description of Changes
This Pull Request was automatically generated to synchronize updates to translation files, verification metadata, and documentation. Below are the details of the changes made:
This Pull Request was automatically generated to synchronize updates to translation files and documentation. Below are the details of the changes made:
#### **1. Synchronization of Translation Files**
- Updated translation files (`messages_*.properties`) to reflect changes in the reference file `messages_en_GB.properties`.
@@ -145,14 +127,9 @@ jobs:
- Added a summary of the current translation status for all supported languages.
- Included up-to-date statistics on translation coverage.
#### **3. Verification Metadata Updates**
- Generated or refreshed the `verification-keyring.keys` and `verification-metadata.xml` files.
- Included the latest dependency signatures and checksums to enhance the build's integrity.
#### **Why these changes are necessary**
- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.
- Strengthens dependency verification for a more secure build process.
---
@@ -166,5 +143,3 @@ jobs:
add-paths: |
README.md
src/main/resources/messages_*.properties
gradle/verification-keyring.keys
gradle/verification-metadata.xml

View File

@@ -585,41 +585,3 @@ In your Thymeleaf templates, use the `#{key}` syntax to reference the new transl
```
Remember, never hard-code text in your templates or Java code. Always use translation keys to ensure proper localization.
## Managing Dependencies
When adding new dependencies or updating existing ones in Stirling-PDF, follow these steps to ensure proper verification and security:
1. Update the dependency in `build.gradle`:
```groovy
dependencies {
// Add or update your dependency
implementation "com.example:new-library:1.2.3"
}
```
2. Generate new verification metadata and keys:
```bash
# Generate verification metadata with signatures and checksums
./gradlew clean dependencies buildEnvironment spotlessApply --write-verification-metadata sha256,pgp
# Export the .keys file
./gradlew --export-keys
```
3. Files to commit:
- `build.gradle` - Your dependency changes
- `gradle/verification-metadata.xml` - Contains verification rules and checksums
- `gradle/verification-keyring.keys` - Contains PGP keys in text format
4. Verify the build works with the new verification:
```bash
./gradlew build
```
5. Before committing, check:
- Verify any new BOM files are properly handled in verification metadata
- Review the changes in `verification-metadata.xml` to ensure they match your dependency updates
This ensures dependencies are properly verified and secure while maintaining transparency in the repository.

View File

@@ -56,13 +56,15 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
openssl-dev \
openjdk21-jre \
# Doc conversion
gcompat \
libc6-compat \
libreoffice \
# pdftohtml
poppler-utils \
# OCR MY PDF (unpaper for descew and other advanced features)
tesseract-ocr-data-eng \
# CV
py3-opencv \
py3-opencv \
# python3/pip
python3 \
py3-pip && \

View File

@@ -57,6 +57,8 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
openssl-dev \
openjdk21-jre \
# Doc conversion
gcompat \
libc6-compat \
libreoffice \
# pdftohtml
poppler-utils \
@@ -65,7 +67,7 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
tesseract-ocr-data-eng \
font-terminus font-dejavu font-noto font-noto-cjk font-awesome font-noto-extra \
# CV
py3-opencv \
py3-opencv \
# python3/pip
python3 \
py3-pip && \

View File

@@ -8,7 +8,8 @@ plugins {
id "com.diffplug.spotless" version "7.0.2"
id "com.github.jk1.dependency-license-report" version "2.9"
//id "nebula.lint" version "19.0.3"
id("org.panteleyev.jpackageplugin") version "1.6.0"
id("org.panteleyev.jpackageplugin") version "1.6.1"
id "org.sonarqube" version "6.0.1.5171"
}
import com.github.jk1.license.render.*
@@ -25,7 +26,7 @@ ext {
}
group = "stirling.software"
version = "0.40.1"
version = "0.41.0"
java {
// 17 is lowest but we support and recommend 21
@@ -34,7 +35,6 @@ java {
repositories {
mavenCentral()
maven { url = "https://jitpack.io" }
maven { url = "https://build.shibboleth.net/maven/releases" }
maven { url = "https://maven.pkg.github.com/jcefmaven/jcefmaven" }
}
@@ -269,6 +269,17 @@ spotless {
}
}
sonar {
properties {
property "sonar.projectKey", "Stirling-Tools_Stirling-PDF"
property "sonar.organization", "stirling-tools"
property "sonar.exclusions", "**/build-wrapper-dump.json, src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
property "sonar.coverage.exclusions", "src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
property "sonar.cpd.exclusions", "src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
}
}
//gradleLint {
// rules=['unused-dependency']
// }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 118 KiB

View File

@@ -265,9 +265,6 @@ public class EndpointConfiguration {
// Pdftohtml dependent endpoints
addEndpointToGroup("Pdftohtml", "pdf-to-html");
addEndpointToGroup("Pdftohtml", "pdf-to-markdown");
// disabled for now while we resolve issues
disableEndpoint("pdf-to-pdfa");
}
private void processEnvironmentConfigs() {

View File

@@ -32,7 +32,10 @@ public class AdditionalLanguageJsController {
response.setContentType("application/javascript");
PrintWriter writer = response.getWriter();
// Erstelle das JavaScript dynamisch
writer.println("const supportedLanguages = " + toJsonArray(new ArrayList<>(supportedLanguages)) + ";");
writer.println(
"const supportedLanguages = "
+ toJsonArray(new ArrayList<>(supportedLanguages))
+ ";");
// Generiere die `getDetailedLanguageCode`-Funktion
writer.println(
"""

View File

@@ -13,8 +13,8 @@ import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
import stirling.software.SPDF.service.CustomPDDocumentFactory;
import stirling.software.SPDF.utils.FileToPdf;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -28,23 +28,23 @@ public class ConvertHtmlToPDF {
private final CustomPDDocumentFactory pdfDocumentFactory;
private final ApplicationProperties applicationProperties;
private final ApplicationProperties applicationProperties;
@Autowired
public ConvertHtmlToPDF(
CustomPDDocumentFactory pdfDocumentFactory,
@Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled,
ApplicationProperties applicationProperties) {
ApplicationProperties applicationProperties) {
this.pdfDocumentFactory = pdfDocumentFactory;
this.bookAndHtmlFormatsInstalled = bookAndHtmlFormatsInstalled;
this.applicationProperties = applicationProperties;
this.applicationProperties = applicationProperties;
}
@PostMapping(consumes = "multipart/form-data", value = "/html/pdf")
@Operation(
summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF",
description =
"This endpoint takes an HTML or ZIP file input and converts it to a PDF format.")
"This endpoint takes an HTML or ZIP file input and converts it to a PDF format. Input:HTML Output:PDF Type:SISO")
public ResponseEntity<byte[]> HtmlToPdf(@ModelAttribute HTMLToPdfRequest request)
throws Exception {
MultipartFile fileInput = request.getFileInput();
@@ -60,7 +60,8 @@ public class ConvertHtmlToPDF {
throw new IllegalArgumentException("File must be either .html or .zip format.");
}
boolean disableSanitize = Boolean.TRUE.equals(applicationProperties.getSystem().getDisableSanitize());
boolean disableSanitize =
Boolean.TRUE.equals(applicationProperties.getSystem().getDisableSanitize());
byte[] pdfBytes =
FileToPdf.convertHtmlToPdf(
@@ -68,7 +69,7 @@ public class ConvertHtmlToPDF {
fileInput.getBytes(),
originalFilename,
bookAndHtmlFormatsInstalled,
disableSanitize);
disableSanitize);
pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes);

View File

@@ -23,8 +23,8 @@ import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.GeneralFile;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.api.GeneralFile;
import stirling.software.SPDF.service.CustomPDDocumentFactory;
import stirling.software.SPDF.utils.FileToPdf;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -38,16 +38,16 @@ public class ConvertMarkdownToPdf {
private final CustomPDDocumentFactory pdfDocumentFactory;
private final ApplicationProperties applicationProperties;
private final ApplicationProperties applicationProperties;
@Autowired
public ConvertMarkdownToPdf(
CustomPDDocumentFactory pdfDocumentFactory,
@Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled,
ApplicationProperties applicationProperties) {
ApplicationProperties applicationProperties) {
this.pdfDocumentFactory = pdfDocumentFactory;
this.bookAndHtmlFormatsInstalled = bookAndHtmlFormatsInstalled;
this.applicationProperties = applicationProperties;
this.applicationProperties = applicationProperties;
}
@PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
@@ -81,7 +81,8 @@ public class ConvertMarkdownToPdf {
String htmlContent = renderer.render(document);
boolean disableSanitize = Boolean.TRUE.equals(applicationProperties.getSystem().getDisableSanitize());
boolean disableSanitize =
Boolean.TRUE.equals(applicationProperties.getSystem().getDisableSanitize());
byte[] pdfBytes =
FileToPdf.convertHtmlToPdf(
@@ -89,7 +90,7 @@ public class ConvertMarkdownToPdf {
htmlContent.getBytes(),
"converted.html",
bookAndHtmlFormatsInstalled,
disableSanitize);
disableSanitize);
pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes);
String outputFilename =
originalFilename.replaceFirst("[.][^.]+$", "")

View File

@@ -73,8 +73,8 @@ public class ConvertPDFToPDFA {
// Determine PDF/A filter based on requested format
String pdfFilter =
"pdfa".equals(outputFormat)
? "writer_pdf_Export:{'SelectPdfVersion':{'Value':'2'}}:writer_pdf_Export"
: "writer_pdf_Export:{'SelectPdfVersion':{'Value':'1'}}:writer_pdf_Export";
? "pdf:writer_pdf_Export:{\"SelectPdfVersion\":{\"type\":\"long\",\"value\":\"2\"}}"
: "pdf:writer_pdf_Export:{\"SelectPdfVersion\":{\"type\":\"long\",\"value\":\"1\"}}";
// Prepare LibreOffice command
List<String> command =
@@ -84,7 +84,7 @@ public class ConvertPDFToPDFA {
"--headless",
"--nologo",
"--convert-to",
"pdf:" + pdfFilter,
pdfFilter,
"--outdir",
tempOutputDir.toString(),
tempInputFile.toString()));

View File

@@ -8,7 +8,9 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -41,8 +43,12 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class AutoSplitPdfController {
private static final String QR_CONTENT = "https://github.com/Stirling-Tools/Stirling-PDF";
private static final String QR_CONTENT_OLD = "https://github.com/Frooodle/Stirling-PDF";
private static final Set<String> VALID_QR_CONTENTS =
new HashSet<>(
Set.of(
"https://github.com/Stirling-Tools/Stirling-PDF",
"https://github.com/Frooodle/Stirling-PDF",
"https://stirlingpdf.com"));
private final CustomPDDocumentFactory pdfDocumentFactory;
@@ -120,13 +126,14 @@ public class AutoSplitPdfController {
for (int page = 0; page < document.getNumberOfPages(); ++page) {
BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 150);
String result = decodeQRCode(bim);
if ((QR_CONTENT.equals(result) || QR_CONTENT_OLD.equals(result)) && page != 0) {
boolean isValidQrCode = VALID_QR_CONTENTS.contains(result);
log.debug("detected qr code {}, code is vale={}", result, isValidQrCode);
if (isValidQrCode && page != 0) {
splitDocuments.add(new PDDocument());
}
if (!splitDocuments.isEmpty()
&& !QR_CONTENT.equals(result)
&& !QR_CONTENT_OLD.equals(result)) {
if (!splitDocuments.isEmpty() && !isValidQrCode) {
splitDocuments.get(splitDocuments.size() - 1).addPage(document.getPage(page));
} else if (page == 0) {
PDDocument firstDocument = new PDDocument();
@@ -135,7 +142,7 @@ public class AutoSplitPdfController {
}
// If duplexMode is true and current page is a divider, then skip next page
if (duplexMode && (QR_CONTENT.equals(result) || QR_CONTENT_OLD.equals(result))) {
if (duplexMode && isValidQrCode) {
page++;
}
}
@@ -168,6 +175,9 @@ public class AutoSplitPdfController {
return WebResponseUtils.bytesToWebResponse(
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
} catch (Exception e) {
log.error("Error in auto split", e);
throw e;
} finally {
// Clean up resources
if (document != null) {

View File

@@ -52,7 +52,7 @@ public class ExtractImagesController {
@Operation(
summary = "Extract images from a PDF file",
description =
"This endpoint extracts images from a given PDF file and returns them in a zip file. Users can specify the output image format. Input: PDF Output: IMAGE/ZIP Type: SIMO")
"This endpoint extracts images from a given PDF file and returns them in a zip file. Users can specify the output image format. Input:PDF Output:IMAGE/ZIP Type:SIMO")
public ResponseEntity<byte[]> extractImages(@ModelAttribute PDFExtractImagesRequest request)
throws IOException, InterruptedException, ExecutionException {
MultipartFile file = request.getFileInput();

View File

@@ -46,7 +46,7 @@ public class FlattenController {
@Operation(
summary = "Flatten PDF form fields or full page",
description =
"Flattening just PDF form fields or converting each page to images to make text unselectable. Input: PDF, Output: PDF. Type: SISO")
"Flattening just PDF form fields or converting each page to images to make text unselectable. Input:PDF, Output:PDF. Type:SISO")
public ResponseEntity<byte[]> flatten(@ModelAttribute FlattenRequest request) throws Exception {
MultipartFile file = request.getFileInput();

View File

@@ -26,6 +26,7 @@ import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.BoundedLineReader;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
@@ -65,6 +66,10 @@ public class OCRController {
}
@PostMapping(consumes = "multipart/form-data", value = "/ocr-pdf")
@Operation(
summary = "Process PDF files with OCR using Tesseract",
description =
"Takes a PDF file as input, performs OCR using specified languages and OCR type (skip-text/force-ocr), and returns the processed PDF. Input:PDF Output:PDF Type:SISO")
public ResponseEntity<byte[]> processPdfWithOCR(
@ModelAttribute ProcessPdfWithOcrRequest request)
throws IOException, InterruptedException {

View File

@@ -25,6 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.PipelineConfig;
import stirling.software.SPDF.model.PipelineResult;
import stirling.software.SPDF.model.api.HandleDataRequest;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -58,7 +59,8 @@ public class PipelineController {
if (inputFiles == null || inputFiles.size() == 0) {
return null;
}
List<Resource> outputFiles = processor.runPipelineAgainstFiles(inputFiles, config);
PipelineResult result = processor.runPipelineAgainstFiles(inputFiles, config);
List<Resource> outputFiles = result.getOutputFiles();
if (outputFiles != null && outputFiles.size() == 1) {
// If there is only one file, return it directly
Resource singleFile = outputFiles.get(0);

View File

@@ -27,6 +27,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.InstallationPathConfig;
import stirling.software.SPDF.model.PipelineConfig;
import stirling.software.SPDF.model.PipelineOperation;
import stirling.software.SPDF.model.PipelineResult;
import stirling.software.SPDF.utils.FileMonitor;
@Service
@@ -143,19 +144,64 @@ public class PipelineDirectoryProcessor {
private File[] collectFilesForProcessing(Path dir, Path jsonFile, PipelineOperation operation)
throws IOException {
List<String> inputExtensions =
apiDocService.getExtensionTypes(false, operation.getOperation());
log.info(
"Allowed extensions for operation {}: {}",
operation.getOperation(),
inputExtensions);
boolean allowAllFiles = inputExtensions.contains("ALL");
try (Stream<Path> paths = Files.list(dir)) {
if ("automated".equals(operation.getParameters().get("fileInput"))) {
return paths.filter(
path ->
!Files.isDirectory(path)
&& !path.equals(jsonFile)
&& fileMonitor.isFileReadyForProcessing(path))
.map(Path::toFile)
.toArray(File[]::new);
} else {
String fileInput = (String) operation.getParameters().get("fileInput");
return new File[] {new File(fileInput)};
}
File[] files =
paths.filter(
path -> {
if (Files.isDirectory(path)) {
return false;
}
if (path.equals(jsonFile)) {
return false;
}
// Get file extension
String filename = path.getFileName().toString();
String extension =
filename.contains(".")
? filename.substring(
filename.lastIndexOf(".")
+ 1)
.toLowerCase()
: "";
// Check against allowed extensions
boolean isAllowed =
allowAllFiles
|| inputExtensions.contains(extension);
if (!isAllowed) {
log.info(
"Skipping file with unsupported extension: {} ({})",
filename,
extension);
}
return isAllowed;
})
.filter(
path -> {
boolean isReady =
fileMonitor.isFileReadyForProcessing(path);
if (!isReady) {
log.info(
"File not ready for processing (locked/created last 5s): {}",
path);
}
return isReady;
})
.map(Path::toFile)
.toArray(File[]::new);
log.info("Collected {} files for processing", files.length);
return files;
}
}
@@ -198,19 +244,37 @@ public class PipelineDirectoryProcessor {
try {
List<Resource> inputFiles =
processor.generateInputFiles(filesToProcess.toArray(new File[0]));
if (inputFiles == null || inputFiles.size() == 0) {
if (inputFiles == null || inputFiles.isEmpty()) {
return;
}
List<Resource> outputFiles = processor.runPipelineAgainstFiles(inputFiles, config);
if (outputFiles == null) return;
moveAndRenameFiles(outputFiles, config, dir);
deleteOriginalFiles(filesToProcess, processingDir);
PipelineResult result = processor.runPipelineAgainstFiles(inputFiles, config);
if (result.isHasErrors()) {
log.error("Errors occurred during processing, retaining original files");
moveToErrorDirectory(filesToProcess, dir);
} else {
moveAndRenameFiles(result.getOutputFiles(), config, dir);
deleteOriginalFiles(filesToProcess, processingDir);
}
} catch (Exception e) {
log.error("error during processing", e);
log.error("Error during processing", e);
moveFilesBack(filesToProcess, processingDir);
}
}
private void moveToErrorDirectory(List<File> files, Path originalDir) throws IOException {
Path errorDir = originalDir.resolve("error");
if (!Files.exists(errorDir)) {
Files.createDirectories(errorDir);
}
for (File file : files) {
Path target = errorDir.resolve(file.getName());
Files.move(file.toPath(), target);
log.info("Moved failed file to error directory for investigation: {}", target);
}
}
private void moveAndRenameFiles(List<Resource> resources, PipelineConfig config, Path dir)
throws IOException {
for (Resource resource : resources) {

View File

@@ -33,6 +33,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.SPDFApplication;
import stirling.software.SPDF.model.PipelineConfig;
import stirling.software.SPDF.model.PipelineOperation;
import stirling.software.SPDF.model.PipelineResult;
import stirling.software.SPDF.model.Role;
@Service
@@ -84,8 +85,10 @@ public class PipelineProcessor {
return "http://localhost:" + port + contextPath + "/";
}
List<Resource> runPipelineAgainstFiles(List<Resource> outputFiles, PipelineConfig config)
PipelineResult runPipelineAgainstFiles(List<Resource> outputFiles, PipelineConfig config)
throws Exception {
PipelineResult result = new PipelineResult();
ByteArrayOutputStream logStream = new ByteArrayOutputStream();
PrintStream logPrintStream = new PrintStream(logStream);
boolean hasErrors = false;
@@ -130,7 +133,8 @@ public class PipelineProcessor {
if (operation.startsWith("filter-")
&& (response.getBody() == null
|| response.getBody().length == 0)) {
log.info("Skipping file due to failing {}", operation);
result.setFiltersApplied(true);
log.info("Skipping file due to filtering {}", operation);
continue;
}
if (!response.getStatusCode().equals(HttpStatus.OK)) {
@@ -208,7 +212,10 @@ public class PipelineProcessor {
if (hasErrors) {
log.error("Errors occurred during processing. Log: {}", logStream.toString());
}
return outputFiles;
result.setHasErrors(hasErrors);
result.setFiltersApplied(hasErrors);
result.setOutputFiles(outputFiles);
return result;
}
private ResponseEntity<byte[]> sendWebRequest(String url, MultiValueMap<String, Object> body) {

View File

@@ -40,8 +40,7 @@ public class RemoveCertSignController {
@Operation(
summary = "Remove digital signature from PDF",
description =
"This endpoint accepts a PDF file and returns the PDF file without the digital signature."
+ " Input: PDF, Output: PDF")
"This endpoint accepts a PDF file and returns the PDF file without the digital signature. Input:PDF, Output:PDF Type:SISO")
public ResponseEntity<byte[]> removeCertSignPDF(@ModelAttribute PDFFile request)
throws Exception {
MultipartFile pdf = request.getFileInput();

View File

@@ -0,0 +1,14 @@
package stirling.software.SPDF.model;
import java.util.List;
import org.springframework.core.io.Resource;
import lombok.Data;
@Data
public class PipelineResult {
private List<Resource> outputFiles;
private boolean hasErrors;
private boolean filtersApplied;
}

View File

@@ -1,10 +1,10 @@
package stirling.software.SPDF.service;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.Arrays;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
@@ -21,8 +21,7 @@ public class LanguageService {
private final PathMatchingResourcePatternResolver resourcePatternResolver =
new PathMatchingResourcePatternResolver();
public LanguageService(
ApplicationProperties applicationProperties) {
public LanguageService(ApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
}

View File

@@ -27,7 +27,7 @@ public class FileToPdf {
byte[] fileBytes,
String fileName,
boolean htmlFormatsInstalled,
boolean disableSanitize)
boolean disableSanitize)
throws IOException, InterruptedException {
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
@@ -36,7 +36,9 @@ public class FileToPdf {
try {
if (fileName.endsWith(".html")) {
tempInputFile = Files.createTempFile("input_", ".html");
String sanitizedHtml = sanitizeHtmlContent(new String(fileBytes, StandardCharsets.UTF_8), disableSanitize);
String sanitizedHtml =
sanitizeHtmlContent(
new String(fileBytes, StandardCharsets.UTF_8), disableSanitize);
Files.write(tempInputFile, sanitizedHtml.getBytes(StandardCharsets.UTF_8));
} else if (fileName.endsWith(".zip")) {
tempInputFile = Files.createTempFile("input_", ".zip");
@@ -93,7 +95,8 @@ public class FileToPdf {
return (!disableSanitize) ? CustomHtmlSanitizer.sanitize(htmlContent) : htmlContent;
}
private static void sanitizeHtmlFilesInZip(Path zipFilePath, boolean disableSanitize) throws IOException {
private static void sanitizeHtmlFilesInZip(Path zipFilePath, boolean disableSanitize)
throws IOException {
Path tempUnzippedDir = Files.createTempDirectory("unzipped_");
try (ZipInputStream zipIn =
ZipSecurity.createHardenedInputStream(

View File

@@ -587,9 +587,7 @@ public class GeneralUtils {
for (byte b : hash) {
fingerprint.append(String.format("%02x", b));
}
return fingerprint.toString();
} catch (Exception e) {
return "GenericID";
}

View File

@@ -218,6 +218,9 @@ public class ProcessExecutor {
errorReaderThread.join();
outputReaderThread.join();
boolean isQpdf =
command != null && !command.isEmpty() && command.get(0).contains("qpdf");
if (outputLines.size() > 0) {
String outputMessage = String.join("\n", outputLines);
messages += outputMessage;
@@ -233,20 +236,28 @@ public class ProcessExecutor {
log.warn("Command error output:\n" + errorMessage);
}
if (exitCode != 0) {
throw new IOException(
"Command process failed with exit code "
+ exitCode
+ ". Error message: "
+ errorMessage);
if (isQpdf && exitCode == 3) {
log.warn("qpdf succeeded with warnings: {}", messages);
} else {
throw new IOException(
"Command process failed with exit code "
+ exitCode
+ ". Error message: "
+ errorMessage);
}
}
}
if (exitCode != 0) {
throw new IOException(
"Command process failed with exit code "
+ exitCode
+ "\nLogs: "
+ messages);
if (isQpdf && exitCode == 3) {
log.warn("qpdf succeeded with warnings: {}", messages);
} else {
throw new IOException(
"Command process failed with exit code "
+ exitCode
+ "\nLogs: "
+ messages);
}
}
} finally {
semaphore.release();

View File

@@ -768,7 +768,6 @@ autoSplitPDF.selectText.3=Upload the single large scanned PDF file and let Stirl
autoSplitPDF.selectText.4=Divider pages are automatically detected and removed, guaranteeing a neat final document.
autoSplitPDF.formPrompt=Submit PDF containing Stirling-PDF Page dividers:
autoSplitPDF.duplexMode=Duplex Mode (Front and back scanning)
autoSplitPDF.dividerDownload1=Download 'Auto Splitter Divider (minimal).pdf'
autoSplitPDF.dividerDownload2=Download 'Auto Splitter Divider (with instructions).pdf'
autoSplitPDF.submit=Submit
@@ -1185,7 +1184,7 @@ changeMetadata.submit=Change
#pdfToPDFA
pdfToPDFA.title=PDF To PDF/A
pdfToPDFA.header=PDF To PDF/A
pdfToPDFA.credit=This service uses qpdf for PDF/A conversion
pdfToPDFA.credit=This service uses libreoffice for PDF/A conversion
pdfToPDFA.submit=Convert
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format

View File

@@ -1185,7 +1185,7 @@ changeMetadata.submit=Change
#pdfToPDFA
pdfToPDFA.title=PDF To PDF/A
pdfToPDFA.header=PDF To PDF/A
pdfToPDFA.credit=This service uses qpdf for PDF/A conversion
pdfToPDFA.credit=This service uses libreoffice for PDF/A conversion
pdfToPDFA.submit=Convert
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format

View File

@@ -27,7 +27,7 @@ bored=Stanco di aspettare?
alphabet=Alfabeto
downloadPdf=Scarica PDF
text=Testo
font=Fonte
font=Font
selectFillter=-- Seleziona --
pageNum=Numero pagina
sizes.small=Piccolo
@@ -273,7 +273,7 @@ home.legacyHomepage=Vecchia homepage
home.newHomePage=Prova la nostra nuova homepage!
home.alphabetical=Alfabetico
home.globalPopularity=Popolarità globale
home.sortBy=Sort by:
home.sortBy=Ordina per:
home.multiTool.title=Multifunzione PDF
home.multiTool.desc=Unisci, Ruota, Riordina, e Rimuovi pagine
@@ -952,7 +952,7 @@ compress.title=Comprimi
compress.header=Comprimi PDF
compress.credit=Questo servizio utilizza qpdf per la compressione/ottimizzazione dei PDF.
compress.selectText.1=Modalità manuale - Da 1 a 5
compress.selectText.1.1=In optimization levels 6 to 9, in addition to general PDF compression, image resolution is scaled down to further reduce file size. Higher levels result in stronger image compression (up to 50% of the original size), achieving greater size reduction but with potential quality loss in images.
compress.selectText.1.1=Nei livelli di ottimizzazione da 6 a 9, oltre alla compressione PDF generale, la risoluzione dell'immagine viene ridotta per ridurre ulteriormente le dimensioni del file. Livelli più alti comportano una compressione dell'immagine più forte (fino al 50% delle dimensioni originali), ottenendo una maggiore riduzione delle dimensioni ma con una potenziale perdita di qualità nelle immagini.
compress.selectText.2=Livello di ottimizzazione:
compress.selectText.3=4 (Terribile per le immagini di testo)
compress.selectText.4=Modalità automatica - Regola automaticamente la qualità per ottenere le dimensioni esatte del PDF

View File

@@ -138,7 +138,7 @@ analytics.settings=Você pode alterar as configurações de coleta de dados no a
# NAVBAR #
#############
navbar.favorite=Favoritos
navbar.recent=New and recently updated
navbar.recent=Novos e Recentemente Atualizados
navbar.darkmode=Modo Escuro
navbar.language=Idiomas
navbar.settings=Configurações
@@ -266,14 +266,14 @@ home.viewPdf.title=Visualizar PDF
home.viewPdf.desc=Visualizar, anotar, adicionar texto ou imagens ao PDF.
viewPdf.tags=visualizar,ler,anotar,texto,imagem
home.setFavorites=Set Favourites
home.hideFavorites=Hide Favourites
home.showFavorites=Show Favourites
home.legacyHomepage=Old homepage
home.newHomePage=Try our new homepage!
home.alphabetical=Alphabetical
home.globalPopularity=Global Popularity
home.sortBy=Sort by:
home.setFavorites=Adicionar Favoritos
home.hideFavorites=Ocultar Favoritos
home.showFavorites=Mostrar Favoritos
home.legacyHomepage=Homepage Antiga
home.newHomePage=Experimente nossa nova Homepage!
home.alphabetical=Alfabética
home.globalPopularity=Popularidade Global
home.sortBy=Ordenar por:
home.multiTool.title=Multiferramentas de PDF
home.multiTool.desc=Mesclar, girar, reorganizar, dividir, inserir e remover páginas.
@@ -417,7 +417,7 @@ home.pageLayout.title=Layout de Múltiplas Páginas
home.pageLayout.desc=Mesclar várias páginas de um documento PDF em uma única página.
pageLayout.tags=mesclar,composto,vista-única,organizar
home.scalePages.title=Ajustar Tamanho/Escala da Página
home.scalePages.title=Ajustar Dimensões da Página
home.scalePages.desc=Alterar o tamanho/escala da página e/ou seu conteúdo.
scalePages.tags=redimensionar,modificar,dimensão,adaptar
@@ -429,7 +429,7 @@ home.add-page-numbers.title=Adicionar Números de Página
home.add-page-numbers.desc=Adicionar números de página no documento, em um local definido.
add-page-numbers.tags=paginar,rotular,organizar,índice
home.auto-rename.title=Renomear Automaticamente o PDF
home.auto-rename.title=Renomeação Automática do PDF
home.auto-rename.desc=Renomeia automaticamente o PDF com base no cabeçalho detectado.
auto-rename.tags=detecção-automática,baseado-em-cabeçalho,organizar,relabel
@@ -738,8 +738,8 @@ addPageNumbers.submit=Adicionar Números de Página
#auto-rename
auto-rename.title=Renomear Automaticamente o PDF
auto-rename.header=Renomear Automaticamente o PDF
auto-rename.title=Renomeação Automática do PDF
auto-rename.header=Renomeação Automática do PDF
auto-rename.submit=Renomeação Automática
@@ -786,8 +786,8 @@ pageLayout.submit=Enviar
#scalePages
scalePages.title=Ajustar Tamanho/Escala da Página
scalePages.header=Ajustar Tamanho/Escala da Página
scalePages.title=Ajustar Dimensões da Página
scalePages.header=Ajustar Dimensões da Página
scalePages.pageSize=Tamanho desejado do documento:
scalePages.keepPageSize=Tamanho Original
scalePages.scaleFactor=Fator de zoom (corte) de uma página:

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
<symbol id="icon-redact-auto" viewBox="0 0 24 24"> <g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<rect width="24" height="24" style="fill: none"/>
@@ -14,4 +14,5 @@
</g>
</g>
</g>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
<symbol id="icon-redact-manual" viewBox="-2 0 24 24">
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<symbol id="icon-split-auto" viewBox="0 0 24 24"> <g id="Layer_2" data-name="Layer 2"> <g id="Layer_2" data-name="Layer 2">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
<symbol id="icon-split-auto" viewBox="0 0 24 24">
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<g>
<path d="M18.42466,20.16555,12,13.74089,9.84315,15.89774a2.45776,2.45776,0,0,1,.2524.73425,4.481,4.481,0,0,1,.06883.78013A3.53515,3.53515,0,0,1,9.086,20.00493a3.53516,3.53516,0,0,1-2.59281,1.07843,3.53516,3.53516,0,0,1-2.59281-1.07843,3.6561,3.6561,0,0,1,0-5.18561,3.53516,3.53516,0,0,1,2.59281-1.07843,4.48117,4.48117,0,0,1,.78014.06884,2.45778,2.45778,0,0,1,.73424.25239l2.15685-2.15685L8.00753,9.74842a2.45752,2.45752,0,0,1-.73424.2524,4.48117,4.48117,0,0,1-.78014.06884A3.53516,3.53516,0,0,1,3.90034,8.99123,3.53515,3.53515,0,0,1,2.82192,6.39842,3.53515,3.53515,0,0,1,3.90034,3.80561,3.53515,3.53515,0,0,1,6.49315,2.72719,3.53515,3.53515,0,0,1,9.086,3.80561a3.53515,3.53515,0,0,1,1.07842,2.59281,4.48107,4.48107,0,0,1-.06883.78014,2.45786,2.45786,0,0,1-.2524.73425L21.17808,19.24774v.91781Zm-3.67123-9.17809L12.91781,9.15185,18.42466,3.645h2.75342v.91781ZM6.49315,8.234A1.841,1.841,0,0,0,8.32877,6.39842,1.841,1.841,0,0,0,6.49315,4.56281,1.841,1.841,0,0,0,4.65753,6.39842,1.841,1.841,0,0,0,6.49315,8.234ZM12,12.36418a.47051.47051,0,1,0-.32123-.13767A.44026.44026,0,0,0,12,12.36418ZM6.49315,19.24774a1.83562,1.83562,0,1,0-1.29641-3.132,1.83562,1.83562,0,0,0,1.29641,3.132Z" style="fill: currentColor"/>
@@ -9,4 +10,5 @@
<rect width="24" height="24" style="fill: none"/>
</g>
</g>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<symbol id="icon-split-chapters" viewBox="0 0 24 24"> <g id="Layer_2" data-name="Layer 2"> <g id="Layer_2" data-name="Layer 2">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
<symbol id="icon-split-chapters" viewBox="0 0 24 24">
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<g>
<path d="M17.632,9.18527v5.44l1.94-1.16,1.94,1.16v-5.44Z" style="fill: currentColor"/>
@@ -9,4 +10,5 @@
<rect width="24" height="24" style="fill: none"/>
</g>
</g>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="padding-left: 20px; margin-right: -20px;">
<symbol id="icon-split-size" viewBox="0 0 24 24"> <g id="Layer_2" data-name="Layer 2"> <g id="Layer_2" data-name="Layer 2">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
<symbol id="icon-split-size" viewBox="0 0 24 24">
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<g>
<path d="M17.90313,20.16555l-6.42466-6.42466L9.32162,15.89774a2.45776,2.45776,0,0,1,.2524.73425,4.481,4.481,0,0,1,.06883.78013,3.53515,3.53515,0,0,1-1.07842,2.59281,3.53516,3.53516,0,0,1-2.59281,1.07843,3.53516,3.53516,0,0,1-2.59281-1.07843,3.6561,3.6561,0,0,1,0-5.18561,3.53516,3.53516,0,0,1,2.59281-1.07843,4.48117,4.48117,0,0,1,.78014.06884,2.45778,2.45778,0,0,1,.73424.25239l2.15685-2.15685L7.486,9.74842a2.45752,2.45752,0,0,1-.73424.2524,4.48117,4.48117,0,0,1-.78014.06884A3.53516,3.53516,0,0,1,3.37881,8.99123,3.53515,3.53515,0,0,1,2.30039,6.39842,3.53515,3.53515,0,0,1,3.37881,3.80561,3.53515,3.53515,0,0,1,5.97162,2.72719,3.53515,3.53515,0,0,1,8.56443,3.80561,3.53515,3.53515,0,0,1,9.64285,6.39842a4.48107,4.48107,0,0,1-.06883.78014,2.45786,2.45786,0,0,1-.2524.73425L20.65655,19.24774v.91781Zm-3.67124-9.17809L12.39628,9.15185,17.90313,3.645h2.75342v.91781ZM5.97162,8.234A1.841,1.841,0,0,0,7.80724,6.39842,1.841,1.841,0,0,0,5.97162,4.56281,1.841,1.841,0,0,0,4.136,6.39842,1.841,1.841,0,0,0,5.97162,8.234Zm5.50685,4.13014a.47051.47051,0,1,0-.32123-.13767A.44026.44026,0,0,0,11.47847,12.36418ZM5.97162,19.24774a1.83562,1.83562,0,1,0-1.29641-3.132,1.83562,1.83562,0,0,0,1.29641,3.132Z" style="fill: currentColor"/>
@@ -13,4 +14,5 @@
<rect width="24" height="24" style="fill: none"/>
</g>
</g>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -48,7 +48,7 @@ window.tooltipSetup = () => {
tooltipElements.forEach((element) => {
const tooltipText = element.getAttribute('title');
element.removeAttribute('title');
element.setAttribute('data-title', 'tooltipText');
element.setAttribute('data-title', tooltipText);
const customTooltip = document.createElement('div');
customTooltip.className = 'btn-tooltip';
customTooltip.textContent = tooltipText;

View File

@@ -17,7 +17,9 @@
<div class="row justify-content-center">
<div class="col-md-6 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">cut</span>
<svg class="material-symbols-rounded tool-header-icon advance">
<use xlink:href="/images/split-auto.svg#icon-split-auto"></use>
</svg>
<span class="tool-header-text" th:text="#{autoSplitPDF.header}"></span>
</div>
@@ -43,8 +45,6 @@
<li th:text="#{autoSplitPDF.selectText.3}"></li>
<li th:text="#{autoSplitPDF.selectText.4}"></li>
</ul>
<p><a th:href="@{'/files/Auto%20Splitter%20Divider%20(minimal).pdf'}" download
th:text="#{autoSplitPDF.dividerDownload1}"></a></p>
<p><a th:href="@{'/files/Auto%20Splitter%20Divider%20(with%20instructions).pdf'}" download
th:text="#{autoSplitPDF.dividerDownload2}"></a></p>
</div>

View File

@@ -1,19 +1,19 @@
<th:block th:fragment="navElements">
<div id="groupOrganize" class="feature-group">
<div id="groupOrganize" class="feature-group">
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.organize})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.organize})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/navbarEntry :: navbarEntry ('multi-tool', 'construction', 'home.multiTool.title', 'home.multiTool.desc', 'multiTool.tags', 'organize')}">
</div>
</div>
<div
<div
th:replace="~{fragments/navbarEntry :: navbarEntry ('merge-pdfs', 'add_to_photos', 'home.merge.title', 'home.merge.desc', 'merge.tags', 'organize')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry ('split-pdfs', 'cut', 'home.split.title', 'home.split.desc', 'split.tags', 'organize')}"></div>
<div
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry ('split-pdfs', 'cut', 'home.split.title', 'home.split.desc', 'split.tags', 'organize')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('rotate-pdf', 'rotate_right', 'home.rotate.title', 'home.rotate.desc', 'rotate.tags', 'organize')}">
</div>
<div
@@ -37,15 +37,14 @@
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-single-page', 'looks_one', 'home.PdfToSinglePage.title', 'home.PdfToSinglePage.desc', 'PdfToSinglePage.tags', 'organize')}">
</div>
</div>
</div>
</div>
<div id="groupConvertTo" class="feature-group">
<div id="groupConvertTo" class="feature-group">
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertTo})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertTo})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('img-to-pdf', 'picture_as_pdf', 'home.imageToPdf.title', 'home.imageToPdf.desc', 'imageToPdf.tags', 'convertto')}">
</div>
<div
@@ -63,14 +62,13 @@
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('book-to-pdf', 'book', 'home.BookToPDF.title', 'home.BookToPDF.desc', 'BookToPDF.tags', 'convertto')}">
</div>
</div>
</div>
<div id="groupConvertFrom" class="feature-group">
</div>
<div id="groupConvertFrom" class="feature-group">
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertFrom})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertFrom})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-img', 'photo_library', 'home.pdfToImage.title', 'home.pdfToImage.desc', 'pdfToImage.tags', 'convert')}">
</div>
<div
@@ -98,17 +96,16 @@
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-book', 'book', 'home.PDFToBook.title', 'home.PDFToBook.desc', 'PDFToBook.tags', 'convert')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-markdown', 'markdown_copy', 'home.PDFToMarkdown.title', 'home.PDFToMarkdown.desc', 'PDFToMarkdown.tags', 'convert')}">
</div>
th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-markdown', 'markdown_copy', 'home.PDFToMarkdown.title', 'home.PDFToMarkdown.desc', 'PDFToMarkdown.tags', 'convert')}">
</div>
</div>
</div>
<div id="convertGroup" class="feature-group">
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertTo})}">
</div>
<div id="convertGroup" class="feature-group">
<div class="nav-group-container">
<div
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertTo})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('img-to-pdf', 'picture_as_pdf', 'home.imageToPdf.title', 'home.imageToPdf.desc', 'imageToPdf.tags', 'convertto')}">
</div>
<div
@@ -126,12 +123,11 @@
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('book-to-pdf', 'book', 'home.BookToPDF.title', 'home.BookToPDF.desc', 'BookToPDF.tags', 'convertto')}">
</div>
</div>
</div>
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertFrom})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertFrom})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-img', 'photo_library', 'home.pdfToImage.title', 'home.pdfToImage.desc', 'pdfToImage.tags', 'convert')}">
</div>
<div
@@ -159,13 +155,12 @@
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-book', 'book', 'home.PDFToBook.title', 'home.PDFToBook.desc', 'PDFToBook.tags', 'convert')}">
</div>
</div>
</div>
<div id="groupSecurity" class="feature-group">
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.security})}">
</div>
<div id="groupSecurity" class="feature-group">
<div class="nav-group-container">
<div
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.security})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('add-password', 'lock', 'home.addPassword.title', 'home.addPassword.desc', 'addPassword.tags', 'security')}">
</div>
<div
@@ -182,34 +177,34 @@
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('validate-signature', 'verified', 'home.validateSignature.title', 'home.validateSignature.desc', 'validateSignature.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-cert-sign', 'remove_moderator', 'home.removeCertSign.title', 'home.removeCertSign.desc', 'removeCertSign.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('sanitize-pdf', 'sanitizer', 'home.sanitizePdf.title', 'home.sanitizePdf.desc', 'sanitizePdf.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('auto-redact', '/images/redact-auto.svg#icon-redact-auto', 'home.autoRedact.title', 'home.autoRedact.desc', 'autoRedact.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('redact', '/images/redact-manual.svg#icon-redact-manual', 'home.redact.title', 'home.redact.desc', 'redact.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('stamp', 'approval', 'home.AddStampRequest.title', 'home.AddStampRequest.desc', 'AddStampRequest.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('add-watermark', 'water_drop', 'home.watermark.title', 'home.watermark.desc', 'watermark.tags', 'security')}">
</div>
th:replace="~{fragments/navbarEntry :: navbarEntry('validate-signature', 'verified', 'home.validateSignature.title', 'home.validateSignature.desc', 'validateSignature.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-cert-sign', 'remove_moderator', 'home.removeCertSign.title', 'home.removeCertSign.desc', 'removeCertSign.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('sanitize-pdf', 'sanitizer', 'home.sanitizePdf.title', 'home.sanitizePdf.desc', 'sanitizePdf.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('auto-redact', '/images/redact-auto.svg#icon-redact-auto', 'home.autoRedact.title', 'home.autoRedact.desc', 'autoRedact.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('redact', '/images/redact-manual.svg#icon-redact-manual', 'home.redact.title', 'home.redact.desc', 'redact.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('stamp', 'approval', 'home.AddStampRequest.title', 'home.AddStampRequest.desc', 'AddStampRequest.tags', 'security')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('add-watermark', 'water_drop', 'home.watermark.title', 'home.watermark.desc', 'watermark.tags', 'security')}">
</div>
</div>
</div>
<div id="groupView" class="feature-group">
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.edit})}">
</div>
<div class="nav-group-container">
<div
<div id="groupView" class="feature-group">
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.edit})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('view-pdf', 'menu_book', 'home.viewPdf.title', 'home.viewPdf.desc', 'viewPdf.tags', 'other')}">
</div>
<div
@@ -246,16 +241,15 @@ th:replace="~{fragments/navbarEntryCustom :: navbarEntry('redact', '/images/reda
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-image-pdf', 'remove_selection', 'home.removeImagePdf.title', 'home.removeImagePdf.desc', 'removeImagePdf.tags', 'other')}">
</div>
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('replace-color-pdf', 'format_color_fill', 'home.replaceColorPdf.title', 'home.replaceColorPdf.desc', 'replaceColorPdf.tags', 'other')}">
</div>
th:replace="~{fragments/navbarEntry :: navbarEntry('replace-and-invert-color-pdf', 'format_color_fill', 'home.replaceColorPdf.title', 'home.replaceColorPdf.desc', 'replaceColorPdf.tags', 'other')}">
</div>
</div>
<div id="groupAdvanced" class="feature-group">
</div>
<div id="groupAdvanced" class="feature-group">
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.advance})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.advance})}">
</div>
<div class="nav-group-container">
<div
th:replace="~{fragments/navbarEntry :: navbarEntry('pipeline', 'family_history', 'home.pipeline.title', 'home.pipeline.desc', 'pipeline.tags', 'advance')}">
</div>
<div
@@ -291,6 +285,6 @@ th:replace="~{fragments/navbarEntryCustom :: navbarEntry('redact', '/images/reda
<div
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('split-pdf-by-chapters', '/images/split-chapters.svg#icon-split-chapters', 'home.splitPdfByChapters.title', 'home.splitPdfByChapters.desc', 'splitPdfByChapters.tags', 'advance')}">
</div>
</div>
</div>
</div>
</th:block>
</th:block>

View File

@@ -1,13 +1,14 @@
<th:block th:fragment="navbarEntry(endpoint, toolIcon, titleKey, descKey, tagKey, toolGroup)"
th:if="${@endpointConfiguration.isEndpointEnabled(endpoint)}">
th:if="${@endpointConfiguration.isEndpointEnabled(endpoint)}">
<a th:id="@{${endpoint}}" class="dropdown-item" style="position:relative" th:href="@{${endpoint}}"
th:data-bs-link="@{${endpoint}}"
th:classappend="${endpoint.equals(currentPage)} ? ${toolGroup} + ' active' : '' + ${toolGroup}"
th:data-bs-tags="#{${tagKey}}" th:data-bs-title='#{${titleKey}}'>
<div style="height:2.5rem;align-items: center;display: flex" th:title="#{${descKey}}" class="icon" alt="icon"
th:class="@{${toolGroup}}">
<svg class="nav-icon" style="height: 2.7rem; width:2.7rem; align-items:center; display: flex; justify-content: center;">
<use th:href="@{${toolIcon}}"></use>
<svg class="nav-icon"
style="height: 2.7rem; width:2.7rem; align-items:center; display: flex; justify-content: center;">
<use th:xlink:href="@{${toolIcon}}"></use>
</svg>
<span class="icon-text" th:text="#{${titleKey}}"></span>
</div>

View File

@@ -27,15 +27,16 @@
<span class="material-symbols-rounded search-icon">
search
</span>
<input type="text" id="searchBar" onkeyup="filterCards()" th:placeholder="#{home.searchBar}" autofocus>
<input type="text" id="searchBar" onkeyup="filterCardsLegacy()" th:placeholder="#{home.searchBar}" autofocus>
<div style="display: flex; align-items: center;">
<a href="home" onclick="setAsDefault('home')" style="text-decoration: none; color: inherit; cursor: pointer; display: flex; align-items: center;">
<span th:text="#{home.newHomePage}">
</span>
<span class="material-symbols-rounded toggle-favourites" style="font-size: 2rem; margin-left: 0.2rem;" >
home
</span>
</a>
<a href="home" onclick="setAsDefault('home')"
style="text-decoration: none; color: inherit; cursor: pointer; display: flex; align-items: center;">
<span th:text="#{home.newHomePage}">
</span>
<span class="material-symbols-rounded toggle-favourites" style="font-size: 2rem; margin-left: 0.2rem;">
home
</span>
</a>
</div>
<div id="filtersContainer">
<span class="material-symbols-rounded filter-button" onclick="toggleFavoritesOnly()">
@@ -70,7 +71,8 @@
</div>
<div id="groupFavorites" class="feature-group-legacy">
<div th:replace="~{fragments/featureGroupHeaderLegacy :: featureGroupHeader(groupTitle=#{navbar.favorite})}">
<div
th:replace="~{fragments/featureGroupHeaderLegacy :: featureGroupHeader(groupTitle=#{navbar.favorite})}">
</div>
<div class="feature-group-container">
</div>
@@ -148,7 +150,7 @@
</div>
<div class="feature-group-container">
<div
th:replace="~{fragments/card :: card(id='img-to-pdf', cardTitle=#{home.imageToPdf.title}, cardText=#{home.imageToPdf.desc}, cardLink='picture_as_pdf', toolIcon='picture_as_pdf', tags=#{imageToPdf.tags}, toolGroup='image')}">
th:replace="~{fragments/card :: card(id='img-to-pdf', cardTitle=#{home.imageToPdf.title}, cardText=#{home.imageToPdf.desc}, cardLink='img-to-pdf', toolIcon='picture_as_pdf', tags=#{imageToPdf.tags}, toolGroup='image')}">
</div>
<div
th:replace="~{fragments/card :: card(id='file-to-pdf', cardTitle=#{home.fileToPDF.title}, cardText=#{home.fileToPDF.desc}, cardLink='file-to-pdf', toolIcon='draft', tags=#{fileToPDF.tags}, toolGroup='convert')}">
@@ -248,7 +250,8 @@
</div>
<div id="groupView" class="feature-group-legacy">
<div th:replace="~{fragments/featureGroupHeaderLegacy :: featureGroupHeader(groupTitle=#{navbar.sections.edit})}">
<div
th:replace="~{fragments/featureGroupHeaderLegacy :: featureGroupHeader(groupTitle=#{navbar.sections.edit})}">
</div>
<div class="feature-group-container">
<div
@@ -289,7 +292,7 @@
th:replace="~{fragments/card :: card(id='remove-image-pdf', cardTitle=#{home.removeImagePdf.title}, cardText=#{home.removeImagePdf.desc}, cardLink='remove-image-pdf', toolIcon='remove_selection', tags=#{removeImagePdf.tags}, toolGroup='other')}">
</div>
<div
th:replace="~{fragments/card :: card(id='replace-color-pdf', cardTitle=#{home.replaceColorPdf.title}, cardText=#{home.replaceColorPdf.desc}, cardLink='replace-and-invert-color-pdf', toolIcon='format_color_fill', tags=#{replaceColorPdf.tags}, toolGroup='other')}">
th:replace="~{fragments/card :: card(id='replace-and-invert-color-pdf', cardTitle=#{home.replaceColorPdf.title}, cardText=#{home.replaceColorPdf.desc}, cardLink='replace-and-invert-color-pdf', toolIcon='format_color_fill', tags=#{replaceColorPdf.tags}, toolGroup='other')}">
</div>
</div>
@@ -513,7 +516,7 @@
function setAsDefault(value) {
localStorage.setItem('defaultView', value);
console.log(`Default view set to: ${value}`);
}
}
</script>

View File

@@ -1,86 +1,96 @@
<!DOCTYPE html>
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}" xmlns:th="https://www.thymeleaf.org">
<head>
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}"
xmlns:th="https://www.thymeleaf.org">
<head>
<th:block th:insert="~{fragments/common :: head(title=#{autoRedact.title}, header=#{autoRedact.header})}"></th:block>
</head>
</head>
<body>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">playlist_remove</span>
<span class="tool-header-text" th:text="#{autoRedact.header}"></span>
</div>
<form th:action="@{'api/v1/security/auto-redact'}" method="post" enctype="multipart/form-data">
<div class="mb-3">
<input type="file" class="form-control" id="fileInput" name="fileInput" required accept="application/pdf">
</div>
<div class="mb-3">
<label for="listOfText" class="form-label" th:text="#{autoRedact.textsToRedactLabel}"></label>
<textarea class="form-control" id="listOfText" name="listOfText" rows="4" required th:placeholder="#{autoRedact.textsToRedactPlaceholder}"></textarea>
</div>
<div class="mb-3">
<label for="defaultColor" class="form-label" th:text="#{autoRedact.colorLabel}">Color</label>
<select class="form-control" id="defaultColor" name="defaultColor" onchange="handleColorChange(this.value)">
<option value="#000000" th:text="#{black}">Black</option>
<option value="#FFFFFF" th:text="#{white}">White</option>
<option value="#FF0000" th:text="#{red}">Red</option>
<option value="#00FF00" th:text="#{green}">Green</option>
<option value="#0000FF" th:text="#{blue}">Blue</option>
<option value="custom" th:text="#{custom}">Custom...</option>
</select>
</div>
<!-- Custom Color Input -->
<div class="mb-3" id="customColorContainer" style="display: none;">
<label for="customColor" class="form-label" th:text="#{autoRedact.colorLabel}">Custom Color</label>
<input type="text" class="form-control" id="customColor" name="redactColor" placeholder="#FF00FF">
</div>
<script>
function handleColorChange(selectedValue) {
if (selectedValue === "custom") {
document.getElementById('customColorContainer').style.display = 'block';
} else {
document.getElementById('customColorContainer').style.display = 'none';
document.getElementById('customColor').value = selectedValue;
}
}
</script>
<div class="mb-3 form-check">
<input type="checkbox" id="useRegex" name="useRegex">
<label for="useRegex" th:text="#{autoRedact.useRegexLabel}"></label>
</div>
<div class="mb-3 form-check">
<input type="checkbox" id="wholeWordSearch" name="wholeWordSearch">
<label for="wholeWordSearch" th:text="#{autoRedact.wholeWordSearchLabel}"></label>
</div>
<div class="mb-3">
<label for="customPadding" class="form-label" th:text="#{autoRedact.customPaddingLabel}"></label>
<input type="number" step="0.1" class="form-control" id="customPadding" name="customPadding" value="0.1">
</div>
<div class="mb-3 form-check">
<input type="checkbox" id="convertPDFToImage" name="convertPDFToImage" checked>
<label for="convertPDFToImage" th:text="#{autoRedact.convertPDFToImageLabel}"></label>
</div>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{autoRedact.submitButton}"></button>
</form>
<body>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 bg-card">
<div class="tool-header">
<svg class="material-symbols-rounded tool-header-icon security">
<use xlink:href="/images/redact-auto.svg#icon-redact-auto"></use>
</svg>
<span class="tool-header-text" th:text="#{autoRedact.header}"></span>
</div>
<form th:action="@{'api/v1/security/auto-redact'}" method="post" enctype="multipart/form-data">
<div class="mb-3">
<input type="file" class="form-control" id="fileInput" name="fileInput" required
accept="application/pdf">
</div>
<div class="mb-3">
<label for="listOfText" class="form-label" th:text="#{autoRedact.textsToRedactLabel}"></label>
<textarea class="form-control" id="listOfText" name="listOfText" rows="4" required
th:placeholder="#{autoRedact.textsToRedactPlaceholder}"></textarea>
</div>
<div class="mb-3">
<label for="defaultColor" class="form-label" th:text="#{autoRedact.colorLabel}">Color</label>
<select class="form-control" id="defaultColor" name="defaultColor"
onchange="handleColorChange(this.value)">
<option value="#000000" th:text="#{black}">Black</option>
<option value="#FFFFFF" th:text="#{white}">White</option>
<option value="#FF0000" th:text="#{red}">Red</option>
<option value="#00FF00" th:text="#{green}">Green</option>
<option value="#0000FF" th:text="#{blue}">Blue</option>
<option value="custom" th:text="#{custom}">Custom...</option>
</select>
</div>
<!-- Custom Color Input -->
<div class="mb-3" id="customColorContainer" style="display: none;">
<label for="customColor" class="form-label" th:text="#{autoRedact.colorLabel}">Custom Color</label>
<input type="text" class="form-control" id="customColor" name="redactColor" placeholder="#FF00FF">
</div>
<script>
function handleColorChange(selectedValue) {
if (selectedValue === "custom") {
document.getElementById('customColorContainer').style.display = 'block';
} else {
document.getElementById('customColorContainer').style.display = 'none';
document.getElementById('customColor').value = selectedValue;
}
}
</script>
<div class="mb-3 form-check">
<input type="checkbox" id="useRegex" name="useRegex">
<label for="useRegex" th:text="#{autoRedact.useRegexLabel}"></label>
</div>
<div class="mb-3 form-check">
<input type="checkbox" id="wholeWordSearch" name="wholeWordSearch">
<label for="wholeWordSearch" th:text="#{autoRedact.wholeWordSearchLabel}"></label>
</div>
<div class="mb-3">
<label for="customPadding" class="form-label" th:text="#{autoRedact.customPaddingLabel}"></label>
<input type="number" step="0.1" class="form-control" id="customPadding" name="customPadding"
value="0.1">
</div>
<div class="mb-3 form-check">
<input type="checkbox" id="convertPDFToImage" name="convertPDFToImage" checked>
<label for="convertPDFToImage" th:text="#{autoRedact.convertPDFToImageLabel}"></label>
</div>
<button type="submit" id="submitBtn" class="btn btn-primary"
th:text="#{autoRedact.submitButton}"></button>
</form>
</div>
</div>
</div>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
</html>

View File

@@ -31,7 +31,9 @@
<div class="row justify-content-center">
<div class="col-md-6 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon security">playlist_remove</span>
<svg class="material-symbols-rounded tool-header-icon security">
<use xlink:href="/images/redact-manual.svg#icon-redact-manual"></use>
</svg>
<span class="tool-header-text" th:text="#{redact.header}"></span>
</div>
<form th:action="@{'api/v1/security/redact'}" method="post" enctype="multipart/form-data">

View File

@@ -1,41 +1,52 @@
<!DOCTYPE html>
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}" xmlns:th="https://www.thymeleaf.org">
<head>
<th:block th:insert="~{fragments/common :: head(title=#{split-by-size-or-count.title}, header=#{split-by-size-or-count.header})}"></th:block>
</head>
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}"
xmlns:th="https://www.thymeleaf.org">
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon advance">vertical_split</span>
<span class="tool-header-text" th:text="#{split-by-size-or-count.header}"></span>
</div>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/general/split-by-size-or-count'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<label for="splitType" th:text="#{split-by-size-or-count.type.label}">Split Type</label>
<select id="splitType" name="splitType" class="form-control">
<option value="0" th:text="#{split-by-size-or-count.type.size}">Size</option>
<option value="1" th:text="#{split-by-size-or-count.type.pageCount}">Page Count</option>
<option value="2" th:text="#{split-by-size-or-count.type.docCount}">Document Count</option>
</select>
<br>
<label for="splitValue" th:text="#{split-by-size-or-count.value.label}">Split Value</label>
<input type="text" id="splitValue" name="splitValue" class="form-control" required th:placeholder="#{split-by-size-or-count.value.placeholder}">
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{split-by-size-or-count.submit}">Submit</button>
</form>
<head>
<th:block
th:insert="~{fragments/common :: head(title=#{split-by-size-or-count.title}, header=#{split-by-size-or-count.header})}">
</th:block>
</head>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 bg-card">
<div class="tool-header">
<svg class="material-symbols-rounded tool-header-icon advance">
<use xlink:href="/images/split-size.svg#icon-split-size"></use>
</svg>
<span class="tool-header-text" th:text="#{split-by-size-or-count.header}"></span>
</div>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/general/split-by-size-or-count'}">
<div
th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}">
</div>
<label for="splitType" th:text="#{split-by-size-or-count.type.label}">Split Type</label>
<select id="splitType" name="splitType" class="form-control">
<option value="0" th:text="#{split-by-size-or-count.type.size}">Size</option>
<option value="1" th:text="#{split-by-size-or-count.type.pageCount}">Page Count</option>
<option value="2" th:text="#{split-by-size-or-count.type.docCount}">Document Count</option>
</select>
<br>
<label for="splitValue" th:text="#{split-by-size-or-count.value.label}">Split Value</label>
<input type="text" id="splitValue" name="splitValue" class="form-control" required
th:placeholder="#{split-by-size-or-count.value.placeholder}">
<br>
<button type="submit" id="submitBtn" class="btn btn-primary"
th:text="#{split-by-size-or-count.submit}">Submit</button>
</form>
</div>
</div>
</div>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
</html>

View File

@@ -1,66 +1,72 @@
<!DOCTYPE html>
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}"
xmlns:th="https://www.thymeleaf.org">
xmlns:th="https://www.thymeleaf.org">
<head>
<th:block th:insert="~{fragments/common :: head(title=#{splitByChapters.title}, header=#{splitByChapters.header})}"></th:block>
<th:block th:insert="~{fragments/common :: head(title=#{splitByChapters.title}, header=#{splitByChapters.header})}">
</th:block>
</head>
<body>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">book</span>
<span class="tool-header-text" th:text="#{splitByChapters.header}"></span>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 bg-card">
<div class="tool-header">
<svg class="material-symbols-rounded tool-header-icon advance">
<use xlink:href="/images/split-chapters.svg#icon-split-chapters"></use>
</svg>
<span class="tool-header-text" th:text="#{splitByChapters.header}"></span>
</div>
<form th:action="@{'/api/v1/general/split-pdf-by-chapters'}" method="post" enctype="multipart/form-data">
<div
th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}">
</div>
<div class="mb-3">
<label for="bookmarkLevel" th:text="#{splitByChapters.bookmarkLevel}"></label>
<input type="number" class="form-control" id="bookmarkLevel" name="bookmarkLevel" min="0" value="0"
required>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="includeMetadata" name="includeMetadata">
<label class="form-check-label" for="includeMetadata"
th:text="#{splitByChapters.includeMetadata}"></label>
<input type="hidden" name="includeMetadata" value="false" />
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="allowDuplicates" name="allowDuplicates">
<label class="form-check-label" for="allowDuplicates"
th:text="#{splitByChapters.allowDuplicates}"></label>
<input type="hidden" name="allowDuplicates" value="false" />
</div>
<p>
<a class="btn btn-outline-primary" data-bs-toggle="collapse" href="#info" role="button"
aria-expanded="false" aria-controls="info" th:text="#{info}"></a>
</p>
<div class="collapse" id="info">
<p th:text="#{splitByChapters.desc.1}"></p>
<p th:text="#{splitByChapters.desc.2}"></p>
<p th:text="#{splitByChapters.desc.3}"></p>
<p th:text="#{splitByChapters.desc.4}"></p>
</div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{splitByChapters.submit}"></button>
</form>
</div>
<form th:action="@{'/api/v1/general/split-pdf-by-chapters'}" method="post" enctype="multipart/form-data">
<div
th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}">
</div>
<div class="mb-3">
<label for="bookmarkLevel" th:text="#{splitByChapters.bookmarkLevel}"></label>
<input type="number" class="form-control" id="bookmarkLevel" name="bookmarkLevel" min="0" value="0" required>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="includeMetadata" name="includeMetadata">
<label class="form-check-label" for="includeMetadata" th:text="#{splitByChapters.includeMetadata}"></label>
<input type="hidden" name="includeMetadata" value="false" />
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="allowDuplicates" name="allowDuplicates">
<label class="form-check-label" for="allowDuplicates" th:text="#{splitByChapters.allowDuplicates}"></label>
<input type="hidden" name="allowDuplicates" value="false" />
</div>
<p>
<a class="btn btn-outline-primary" data-bs-toggle="collapse" href="#info" role="button"
aria-expanded="false" aria-controls="info" th:text="#{info}"></a>
</p>
<div class="collapse" id="info">
<p th:text="#{splitByChapters.desc.1}"></p>
<p th:text="#{splitByChapters.desc.2}"></p>
<p th:text="#{splitByChapters.desc.3}"></p>
<p th:text="#{splitByChapters.desc.4}"></p>
</div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{splitByChapters.submit}"></button>
</form>
</div>
</div>
</div>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
</html>

View File

@@ -1,8 +1,5 @@
#!/bin/bash
# Default value for the Boolean parameter
VERIFICATION=${1:-false} # Default is "false" if no parameter is passed
# Find project root by locating build.gradle
find_root() {
local dir="$PWD"
@@ -26,18 +23,18 @@ check_health() {
local end=$((SECONDS+60))
echo -n "Waiting for $service_name to become healthy..."
until [ "$(docker inspect --format='{{json .State.Health.Status}}' "$service_name")" == '"healthy"' ] || [ $SECONDS -ge $end ]; do
sleep 3
echo -n "."
if [ $SECONDS -ge $end ]; then
echo -e "\n$service_name health check timed out after 80 seconds."
echo "Printing logs for $service_name:"
until [ "$(docker inspect --format='{{json .State.Health.Status}}' "$service_name")" == '"healthy"' ] || [ $SECONDS -ge $end ]; do
sleep 3
echo -n "."
if [ $SECONDS -ge $end ]; then
echo -e "\n$service_name health check timed out after 80 seconds."
echo "Printing logs for $service_name:"
docker logs "$service_name"
return 1
fi
done
echo -e "\n$service_name is healthy!"
echo "Printing logs for $service_name:"
return 1
fi
done
echo -e "\n$service_name is healthy!"
echo "Printing logs for $service_name:"
docker logs "$service_name"
return 0
}
@@ -81,16 +78,10 @@ run_tests() {
# Main testing routine
main() {
SECONDS=0
SECONDS=0
cd "$PROJECT_ROOT"
# Run the gradlew build command and check if it fails
if [[ "$VERIFICATION" == "true" ]]; then
./gradlew clean dependencies buildEnvironment spotlessApply --write-verification-metadata sha256 --refresh-dependencies help
./gradlew clean dependencies buildEnvironment spotlessApply --write-verification-metadata sha256,pgp --refresh-keys --export-keys --refresh-dependencies help
fi
export DOCKER_ENABLE_SECURITY=false
# Run the gradlew build command and check if it fails
if ! ./gradlew clean build; then
@@ -98,28 +89,26 @@ main() {
exit 1
fi
# Building Docker images
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile .
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite .
# Test each configuration
run_tests "Stirling-PDF-Ultra-Lite" "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml"
echo "Testing webpage accessibility..."
cd "testing"
if ./test_webpages.sh -f webpage_urls.txt -b http://localhost:8080; then
passed_tests+=("Webpage-Accessibility-lite")
else
failed_tests+=("Webpage-Accessibility-lite")
echo "Webpage accessibility lite tests failed"
fi
cd "$PROJECT_ROOT"
docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml" down
#run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml"
#docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down
echo "Testing webpage accessibility..."
cd "testing"
if ./test_webpages.sh -f webpage_urls.txt -b http://localhost:8080; then
passed_tests+=("Webpage-Accessibility-lite")
else
failed_tests+=("Webpage-Accessibility-lite")
echo "Webpage accessibility lite tests failed"
fi
cd "$PROJECT_ROOT"
docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml" down
# run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml"
# docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down
export DOCKER_ENABLE_SECURITY=true
# Run the gradlew build command and check if it fails
@@ -128,72 +117,68 @@ main() {
exit 1
fi
# Building Docker images with security enabled
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile .
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite .
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile .
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite .
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat .
# Test each configuration with security
# run_tests "Stirling-PDF-Ultra-Lite-Security" "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml"
#docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" down
# run_tests "Stirling-PDF-Security" "./exampleYmlFiles/docker-compose-latest-security.yml"
# docker-compose -f "./exampleYmlFiles/docker-compose-latest-security.yml" down
# run_tests "Stirling-PDF-Ultra-Lite-Security" "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml"
# docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" down
# run_tests "Stirling-PDF-Security" "./exampleYmlFiles/docker-compose-latest-security.yml"
# docker-compose -f "./exampleYmlFiles/docker-compose-latest-security.yml" down
run_tests "Stirling-PDF-Security-Fat" "./exampleYmlFiles/docker-compose-latest-fat-security.yml"
echo "Testing webpage accessibility..."
cd "testing"
if ./test_webpages.sh -f webpage_urls_full.txt -b http://localhost:8080; then
passed_tests+=("Webpage-Accessibility-full")
else
failed_tests+=("Webpage-Accessibility-full")
echo "Webpage accessibility full tests failed"
fi
cd "$PROJECT_ROOT"
docker-compose -f "./exampleYmlFiles/docker-compose-latest-fat-security.yml" down
run_tests "Stirling-PDF-Security-Fat" "./exampleYmlFiles/docker-compose-latest-fat-security.yml"
echo "Testing webpage accessibility..."
cd "testing"
if ./test_webpages.sh -f webpage_urls_full.txt -b http://localhost:8080; then
passed_tests+=("Webpage-Accessibility-full")
else
failed_tests+=("Webpage-Accessibility-full")
echo "Webpage accessibility full tests failed"
fi
cd "$PROJECT_ROOT"
run_tests "Stirling-PDF-Security-Fat-with-login" "./exampleYmlFiles/test_cicd.yml"
docker-compose -f "./exampleYmlFiles/docker-compose-latest-fat-security.yml" down
run_tests "Stirling-PDF-Security-Fat-with-login" "./exampleYmlFiles/test_cicd.yml"
if [ $? -eq 0 ]; then
cd "testing/cucumber"
if python -m behave; then
passed_tests+=("Stirling-PDF-Regression")
else
failed_tests+=("Stirling-PDF-Regression")
echo "Printing docker logs of failed regression"
docker logs "Stirling-PDF-Security-Fat-with-login"
echo "Printed docker logs of failed regression"
fi
cd "$PROJECT_ROOT"
fi
docker-compose -f "./exampleYmlFiles/test_cicd.yml" down
if [ $? -eq 0 ]; then
cd "testing/cucumber"
if python -m behave; then
passed_tests+=("Stirling-PDF-Regression")
else
failed_tests+=("Stirling-PDF-Regression")
echo "Printing docker logs of failed regression"
docker logs "Stirling-PDF-Security-Fat-with-login"
echo "Printed docker logs of failed regression"
fi
cd "$PROJECT_ROOT"
fi
docker-compose -f "./exampleYmlFiles/test_cicd.yml" down
# Report results
echo "All tests completed in $SECONDS seconds."
if [ ${#passed_tests[@]} -ne 0 ]; then
echo "Passed tests:"
fi
if [ ${#passed_tests[@]} -ne 0 ]; then
echo "Passed tests:"
fi
for test in "${passed_tests[@]}"; do
echo -e "\e[32m$test\e[0m" # Green color for passed tests
done
if [ ${#failed_tests[@]} -ne 0 ]; then
echo "Failed tests:"
fi
if [ ${#failed_tests[@]} -ne 0 ]; then
echo "Failed tests:"
fi
for test in "${failed_tests[@]}"; do
echo -e "\e[31m$test\e[0m" # Red color for failed tests
done
# Check if there are any failed tests and exit with an error code if so
if [ ${#failed_tests[@]} -ne 0 ]; then
echo "Some tests failed."
@@ -202,7 +187,6 @@ main() {
echo "All tests passed successfully."
exit 0
fi
}
main
main