Compare commits

..

545 Commits

Author SHA1 Message Date
calixteman
b4ba666b0c
Merge pull request #21694 from calixteman/improve_font_familly_san
Safely serialize CSS font family names
2026-08-03 21:12:10 +02:00
calixteman
4c4e8feafd
Merge pull request #21693 from calixteman/fix/quad-regex-autolinker
Bound the email parts in the autolinker regex
2026-08-03 18:03:43 +02:00
calixteman
f21fe34747
Safely serialize CSS font family names 2026-08-03 18:02:10 +02:00
calixteman
ba7bf7b26c
Merge pull request #21683 from calixteman/fix/quad-regex-writer
Don't write numbers in exponential notation when saving a pdf
2026-08-03 17:49:23 +02:00
calixteman
1da36fb6bf
Merge pull request #21686 from calixteman/fix/quad-regex-xfa-path
Anchor the regex used to extract the XFA path positions
2026-08-03 17:46:24 +02:00
calixteman
92d027eaeb
Anchor the regex used to extract the XFA path positions
Matching the name with a leading `.+` is quadratic in the length of
a component which doesn't end with a position, and every AcroForm
field name goes through this.
2026-08-03 17:07:48 +02:00
calixteman
5375bff642
Don't write numbers in exponential notation when saving a pdf
`toFixed(10)` switches to the exponential notation from 1e21 on, which isn't
valid PDF syntax, and removing the trailing zeros then dropped a digit of the
exponent: 1e30 was written "1e+3" and 1e100 "1e+1". Such a number, necessarily
an integer, is now written with all its digits.

The trailing zeros are removed with a backward scan, since `toFixed(10)` always
produces exactly 10 decimals. Below the 1e21 limit its output is at most 33
characters long, so the previous `$`-anchored regex wasn't a performance issue.
2026-08-03 16:59:12 +02:00
calixteman
b1f51818ae
Bound the email parts in the autolinker regex
The local part and the domain labels were unbounded, making the
search quadratic in the length of a run of characters preceding
an "@": scanning the text of a single page could take seconds.
2026-08-03 16:38:02 +02:00
Tim van der Meij
ae976b924b
Merge pull request #21671 from Snuffleupagus/getFieldObjects-Map
[api-minor] Convert `getFieldObjects` to return data in a Map
2026-08-02 22:37:22 +02:00
Tim van der Meij
ec691130e6
Merge pull request #21692 from calixteman/fix/quad-regex-xml-entities
Exclude "&" from the XML entity names
2026-08-02 22:24:11 +02:00
Jonas Jenwald
88716313d6 Bump library version to 6.3
See commit ce4ff55faaa83b39b0137dc458af6eea6f96235f
2026-08-02 21:27:09 +02:00
Jonas Jenwald
82624a5e50 [api-minor] Convert getFieldObjects to return data in a Map
Compared to regular Objects there's a number of advantages to using Maps:
 - They support proper iteration.
 - They have a simple way to check for the existence of data.
 - They have a simple/efficient way to check the number of elements.

If this functionality was added today, I cannot imagine that we'd choose an Object for this data.

In the Firefox PDF Viewer sending Maps to the scripting-implementation should be fine, since it uses the browser `Cu.cloneInto` functionality; see https://searchfox.org/firefox-main/source/toolkit/components/pdfjs/content/PdfSandbox.sys.mjs
However with QuickJS, used by the GENERIC viewer, all data needs to be stringified and Maps are converted into regular Objects (see also PR 21664). Hence the `objects` property, in the scripting-implementation, is converted back into a Map using the (renamed) `createMap` helper function.
2026-08-02 21:27:07 +02:00
Jonas Jenwald
7590ad5312
Merge pull request #21689 from timvandermeij/updates
Update dependencies to the most recent versions
2026-08-02 21:25:38 +02:00
Jonas Jenwald
923d48ead4
Merge pull request #21691 from Snuffleupagus/Field-setAction-Map
Add scripts correctly in `Field.prototype.setAction` (PR 12569 follow-up)
2026-08-02 21:24:24 +02:00
Jonas Jenwald
1f9fbc764e Add scripts correctly in Field.prototype.setAction (PR 12569 follow-up)
In PR 12569 the `_actions` class-field was changed from an Object into a Map, with *most* of the code updated to reflect that.
However, in the `setAction` method it's still treated as an Object which means that any added script will simply be ignored. Most likely that part of the scripting-implementation isn't being used, since this code has been "wrong" for close to six years now.
2026-08-02 20:31:15 +02:00
calixteman
f7f30dd844
Exclude "&" from the XML entity names
Scanning to the end of the string for every "&" made the entity
resolution quadratic. Stopping at the next "&" also fixes a bare
ampersand swallowing the reference which follows it.
2026-08-02 18:59:19 +02:00
Tim van der Meij
d2ebbd10de
Fix vulnerability in the brace-expansion dependency
This patch is automatically generated with `npm audit fix` and fixes
CVE-2026-14257.
2026-08-02 13:23:04 +02:00
Tim van der Meij
09ad726a3f
Update dependencies to the most recent versions 2026-08-02 13:22:33 +02:00
Tim van der Meij
d0779c411e
Merge pull request #21687 from calixteman/fix/quad-regex-delete-word
Scan backwards to delete a word in a text field
2026-08-02 13:04:00 +02:00
Tim van der Meij
89852881b8
Merge pull request #21685 from calixteman/fix/quad-regex-pdf-filename
Find the PDF filename in a URL hash in two linear steps
2026-08-02 12:57:49 +02:00
Tim van der Meij
eb8f6af8cc
Merge pull request #21684 from calixteman/fix/quad-regex-headers
Trim the response headers with a backward scan
2026-08-02 12:46:03 +02:00
Tim van der Meij
f73978083d
Merge pull request #21680 from calixteman/fix/quad-regex
Fix the regex used to normalize css fonts in XFA
2026-08-02 12:43:14 +02:00
Tim van der Meij
5dc1d0c5d5
Merge pull request #21682 from calixteman/fix/xml-invalid-char-ref
Don't throw on an invalid XML character reference
2026-08-02 12:26:49 +02:00
Tim van der Meij
2475c4ec91
Merge pull request #21678 from Snuffleupagus/ViewHistory-findIndex
Shorten the `ViewHistory` class a little bit
2026-08-02 12:10:21 +02:00
calixteman
08f6769390
Scan backwards to delete a word in a text field
Finding the word to delete with a regex is quadratic in the value
length, so each "delete word backward" keystroke could take a long
time in a large field.
2026-08-01 22:13:27 +02:00
calixteman
7862875438
Find the PDF filename in a URL hash in two linear steps
Searching for a name followed by ".pdf" is quadratic on a hash which
doesn't contain one, so locate the last ".pdf" first and then extend
it to the left.
2026-08-01 21:17:43 +02:00
calixteman
cba911df86
Trim the response headers with a backward scan
Removing the trailing whitespace with a `$`-anchored regex is
quadratic in the length of the run, which a server controls.
The helper lives in network_utils.js, to be unit testable.
2026-08-01 20:56:01 +02:00
calixteman
cec8d2eed6
Don't throw on an invalid XML character reference
`String.fromCodePoint` throws on anything which isn't a code point,
so e.g. "&#xZZ;" or "�" aborted the whole parsing. Such a
reference is now kept as-is, like an unknown named entity.
2026-08-01 16:24:03 +02:00
calixteman
491792f0e2
Fix the regex used to normalize css fonts in XFA
The regex was quadratic in the number of consecutive spaces,
which caused performance issues when normalizing fonts with
a large number of spaces.
2026-08-01 15:11:43 +02:00
Jonas Jenwald
664526ee65 Shorten the ViewHistory class a little bit
- Replace the manual loop, used to find an existing entry, with the native [`findIndex` method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex).

 - Remove the `fingerprint`/`cacheSize` class fields, since they are completely unused.
2026-08-01 12:19:20 +02:00
Tim van der Meij
7fc7072f9c
Merge pull request #21674 from calixteman/touch/fix-swallowed-pointerup
Let pointerup/cancel propagate in TouchManager
2026-07-31 20:16:07 +02:00
Tim van der Meij
bb1a948397
Merge pull request #21672 from Snuffleupagus/more-ternary
Replace simple return `if` statements with ternary operators
2026-07-31 19:59:46 +02:00
Tim van der Meij
4b4c784a85
Merge pull request #21673 from Snuffleupagus/EventBus-Map-Set
Re-factor the `EventBus` to use Map/Set internally
2026-07-31 19:50:16 +02:00
calixteman
0f999e27b5 Let pointerup/cancel propagate in TouchManager
During two-finger gestures, keep preventing the default action on pointerup/pointercancel, but don't stop propagation. Resize/drag sessions need those bubble events to clean up.
2026-07-31 19:26:53 +02:00
calixteman
af38789499
Merge pull request #21659 from calixteman/fix/pinch-zoom-origin
Use the client coordinates for the pinch-zoom origin
2026-07-31 18:00:52 +02:00
Jonas Jenwald
0d5df9d96e Re-factor the EventBus to use Map/Set internally
Especially the Array to Set conversion should be helpful, since adding/removing elements from a Set is more efficient.
2026-07-31 17:37:05 +02:00
Calixte Denizet
8960eddfc1 Use the client coordinates for the pinch-zoom origin
`TouchManager` computes the pinch distances with the screen coordinates, but it
was passing the pinch center in that space too, while the viewer expects a
client coordinate, like the origin coming from a wheel event.

Since a two-finger gesture can be synthesized with WebDriver BiDi, the
pinch-zoom test doesn't have to rely on CDP anymore and can run in Chrome, where
it fails without the above fix.
2026-07-31 16:44:28 +02:00
Jonas Jenwald
ee59db5018 Replace simple return if statements with ternary operators
In a couple of cases, where a boolean is returned, it's also possible to use an OR operator rather a ternary.

*Note:* This patch reduces the size of the `gulp mozcentral` bundle by `960` bytes.
2026-07-31 12:24:08 +02:00
Jonas Jenwald
ce4ff55faa
Merge pull request #21664 from Snuffleupagus/getJSActions-api
[api-minor] Convert `getJSActions` to return data in a Map
2026-07-31 11:29:21 +02:00
calixteman
40f6492997
Merge pull request #21665 from calixteman/sync_firefox_css
Sync the viewer chrome with the Firefox design system
2026-07-31 09:48:01 +02:00
calixteman
613e004b2e
Merge pull request #21669 from mozilla/update-locales
l10n: Update locale files
2026-07-31 09:19:53 +02:00
github-actions[bot]
734b21e61e l10n: Update locale files 2026-07-31 00:39:04 +00:00
Calixte Denizet
b4d028132b Sync the viewer chrome with the Firefox design system
The chrome is now authored against Firefox design-token names with the shipped
value as a fallback `var(--fx-token, <literal>)` so colors, borders and radii
follow Firefox instead of having to be re-synced by hand.

In MOZCENTRAL viewer.css imports chrome://global/skin/design-system/tokens-brand.css,
gated on the new pdfjs.enableNova pref (default false, read straight from CSS via -moz-pref()).
With the pref off the sheet isn't applied, every fallback resolves, and the
viewer renders as before, as it also does in the GENERIC and components builds,
which never see the chrome sheet.

Consuming a token means never declaring its name in an unlayered rule, which
would shadow Firefox's for the whole subtree; --focus-outline, --border-color and
--text-color/--button-border-color are therefore renamed to
--editor-selection-outline, --signature-border-color and --views-*. In forced
colors each state reads a matching background/foreground/border triple so it
can't collapse to a single system color.

The dialog button styling also moves out of `.dialog .mainContainer button` into
a shared .primaryButton/.secondaryButton primitive (buttons.css, imported from
pdf_viewer.css so the components build gets it too). The password,
document-properties, print and undo-bar buttons use it in place of .dialogButton,
and the custom radio appearance gives way to native controls tinted with
accent-color.
2026-07-30 23:13:43 +02:00
Tim van der Meij
a80897dc9a
Merge pull request #21666 from calixteman/bug2054348
Fix the selection rendering when a page has been destroyed and rendered again (bug 2054348)
2026-07-30 21:12:47 +02:00
Tim van der Meij
0163438e1a
Merge pull request #21660 from calixteman/fix/pdf-editor-preserve-widget-parent
Avoid mutating source widget parents
2026-07-30 21:02:29 +02:00
Tim van der Meij
f70f55d743
Merge pull request #21658 from calixteman/fix/pdf-editor-clone-reference-race
Avoid duplicate shared object clones
2026-07-30 20:52:35 +02:00
Calixte Denizet
9e02ceed09 Fix the selection rendering when a page has been destroyed and rendered again (bug 2054348)
The draw layer keeps a reference on the text layer div in order to render the
selection, but it was destroyed only along with the annotation editor layer.
Hence, when the editor is disabled, like in Firefox for Android, scrolling far
enough to destroy a page view left the draw layer with a reference on a removed
text layer: the new one was never registered, consequently no selection was
rendered anymore on that page.
2026-07-30 18:37:03 +02:00
Jonas Jenwald
803c9d7d21 [api-minor] Convert getJSActions to return data in a Map
Compared to regular Objects there's a number of advantages to using Maps:
 - They support proper iteration.
 - They have a simple way to check for the existence of data.
 - They have a simple/efficient way to check the number of elements.

If this functionality was added today, I cannot imagine that we'd choose an Object for this data.

Note also how in the scripting-implementation the `actions` were already converted into a Map, via the `createActionsMap` helper.
In the Firefox PDF Viewer sending `Map`s to the scripting-implementation should be fine, since it uses the browser `Cu.cloneInto` functionality; see https://searchfox.org/firefox-main/source/toolkit/components/pdfjs/content/PdfSandbox.sys.mjs
However with QuickJS, used by the GENERIC viewer, all data needs to be stringified and unfortunately `JSON.stringify()` doesn't support Maps. Hence we convert Maps to Objects, via a [`replacer` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#replacer), since the existing `createActionsMap` usage will convert the actions-Objects back to Maps.
2026-07-30 16:04:58 +02:00
Jonas Jenwald
73707b62e9
Merge pull request #21661 from Snuffleupagus/more-optional-chaining-6
Use more more optional chaining in the `src/` folder
2026-07-30 10:35:17 +02:00
Jonas Jenwald
1813ab0774 Use more more optional chaining in the src/ folder 2026-07-29 18:28:41 +02:00
Calixte Denizet
aa812b531a Avoid mutating source widget parents 2026-07-29 16:03:15 +02:00
calixteman
61acf93172
Merge pull request #21644 from calixteman/editor/pinch-lost-after-undo
[Editor] Restore pinch-to-resize on an editor which came back from an undo
2026-07-29 15:27:54 +02:00
calixteman
822d3ea809 [Editor] Restore pinch-to-resize on an editor which came back from an undo
`AnnotationEditor.remove()` destroys the editor's `TouchManager`, but `remove()`
is also the undo half of an edit: deleting a drawing and undoing it, or undoing
the drawing itself and redoing it, brings the very same editor back.
2026-07-29 14:45:02 +02:00
Calixte Denizet
3a19a20d50 Avoid duplicate shared object clones 2026-07-28 22:39:35 +02:00
Tim van der Meij
4d9007e6f9
Merge pull request #21655 from timvandermeij/bump
Bump the stable version in `pdfjs.config`
2026-07-28 21:59:15 +02:00
Tim van der Meij
7f5fd4eba4
Bump the stable version in pdfjs.config 2026-07-28 21:53:58 +02:00
Tim van der Meij
0365cbde02
Merge pull request #21654 from calixteman/fix/cycles
Avoid cycles when walking some trees
2026-07-28 21:34:49 +02:00
Tim van der Meij
f704f2ef02
Merge pull request #21652 from Snuffleupagus/signatures-async-helpers
Update the signatures-helpers to actually handle `MissingDataException`s
2026-07-28 21:34:14 +02:00
Tim van der Meij
01ba4c476d
Merge pull request #21646 from calixteman/update/pdf.js.qcms
Update qcms wrapper
2026-07-28 20:25:15 +02:00
Tim van der Meij
0299cdcab9
Merge pull request #21653 from Snuffleupagus/jsActions-_getElementsByName-shorten
Shorten `Catalog.prototype.jsActions getter` and `AnnotationElement.prototype._getElementsByName` a tiny bit
2026-07-28 20:23:07 +02:00
Tim van der Meij
8c3e1014f4
Merge pull request #21650 from mozilla/dependabot/github_actions/github/codeql-action/autobuild-4.37.2
Bump github/codeql-action/autobuild from 4.37.0 to 4.37.2
2026-07-28 20:20:18 +02:00
Tim van der Meij
14afb8669f
Merge pull request #21649 from mozilla/dependabot/github_actions/github/codeql-action/analyze-4.37.2
Bump github/codeql-action/analyze from 4.37.0 to 4.37.2
2026-07-28 20:20:08 +02:00
Tim van der Meij
14fc73bf05
Merge pull request #21648 from mozilla/dependabot/github_actions/github/codeql-action/init-4.37.2
Bump github/codeql-action/init from 4.37.0 to 4.37.2
2026-07-28 20:19:56 +02:00
Tim van der Meij
257f4c2a5e
Merge pull request #21647 from mozilla/dependabot/github_actions/actions/setup-python-7.0.0
Bump actions/setup-python from 6.3.0 to 7.0.0
2026-07-28 20:18:56 +02:00
Tim van der Meij
93958e4ff6
Merge pull request #21640 from Snuffleupagus/defaultOptions-Map
Change `defaultOptions`, in the `web/app_options.js` file, to a Map
2026-07-28 20:18:03 +02:00
Tim van der Meij
bc6b5b0f44
Merge pull request #21651 from mozilla/dependabot/github_actions/actions/checkout-7.0.1
Bump actions/checkout from 7.0.0 to 7.0.1
2026-07-28 20:15:10 +02:00
Calixte Denizet
ac51b29777 Avoid cycles when walking some trees 2026-07-28 19:51:34 +02:00
Jonas Jenwald
3736000aee Shorten the AnnotationElement.prototype._getElementsByName method a tiny bit 2026-07-28 19:07:31 +02:00
Jonas Jenwald
8d1afad39b Shorten the Catalog.prototype.jsActions getter, and related code, a tiny bit
This is possible thanks to modern language features.
2026-07-28 19:01:47 +02:00
Jonas Jenwald
c9eaf13ae4 Lookup more data in parallel in the PDFDocument.prototype.#parseSignatureDict method 2026-07-28 16:18:01 +02:00
Jonas Jenwald
1ce8e8a320 Move the ByteRange validation earlier when parsing signatures
Given that these checks are synchronous, we can avoid a little bit of unnecessary data-fetching if the `ByteRange` is invalid.
2026-07-28 16:18:01 +02:00
Jonas Jenwald
f38e8b659e Update the signatures-helpers to actually handle MissingDataExceptions
The `PDFDocument.prototype.signatures` getter returns a (shadowed) Promise, however the way that it invokes various helper-methods can lead to *intermittent* failures to parse the signature data.
These helper-methods will lookup a fair amount of Dictionary data, however any one of those cases could throw `MissingDataException` during document loading.

To avoid having to re-factor those methods a lot, and adding a bunch more `pdfManager.ensureDoc()` calls, they are instead made asynchronous and the Dictionary lookups changed to use `Dict.prototype.getAsync` (similar to the existing `fieldObjects` handling).
Technically this additional asynchronicity may be ever so slightly slower, however I don't think it matters in practice since: most PDFs don't have any signatures, the signature-UI is initialized lazily in the viewer, and finally fetching/parsing of signatures do not block rendering.
Also, note how multiple values are being fetched in parallel in order to attempt to reduce overall asynchronicity.

*Note:* The unit-test changes are essentially fixing pre-existing bugs, that this patch exposed, since the test-only `Dict` instances weren't able to fetch indirect objects.
2026-07-28 16:17:52 +02:00
dependabot[bot]
4b924df453
Bump actions/checkout from 7.0.0 to 7.0.1
Bumps [actions/checkout](https://github.com/actions/checkout) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](9c091bb21b...3d3c42e5aa)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-28 12:16:57 +00:00
dependabot[bot]
2f873ef13a
Bump github/codeql-action/autobuild from 4.37.0 to 4.37.2
Bumps [github/codeql-action/autobuild](https://github.com/github/codeql-action) from 4.37.0 to 4.37.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](99df26d4f1...e0647621c2)

---
updated-dependencies:
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.37.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-28 12:16:45 +00:00
dependabot[bot]
4a11934d1e
Bump github/codeql-action/analyze from 4.37.0 to 4.37.2
Bumps [github/codeql-action/analyze](https://github.com/github/codeql-action) from 4.37.0 to 4.37.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](99df26d4f1...e0647621c2)

---
updated-dependencies:
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-28 12:15:26 +00:00
dependabot[bot]
31d49e18de
Bump github/codeql-action/init from 4.37.0 to 4.37.2
Bumps [github/codeql-action/init](https://github.com/github/codeql-action) from 4.37.0 to 4.37.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](99df26d4f1...e0647621c2)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-28 12:14:05 +00:00
dependabot[bot]
5d93c1bdff
Bump actions/setup-python from 6.3.0 to 7.0.0
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6.3.0 to 7.0.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](ece7cb06ca...5fda3b95a4)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-28 12:12:46 +00:00
calixteman
e7acffcef3
Update qcms wrapper
Few performance improvements have been made in the qcms wrapper, see:
2ae4ee7233
2026-07-27 20:33:49 +02:00
calixteman
1609bd87c5
Merge commit from fork
Harden the XFA layer and restrict scripting updates to known fields
2026-07-27 19:38:24 +02:00
Jonas Jenwald
a03ec7e8c5
Merge pull request #21642 from Snuffleupagus/normalizeBlendMode-shorten
Reduce a tiny bit of duplication in the `normalizeBlendMode` helper
2026-07-27 19:02:26 +02:00
Jonas Jenwald
63a0f285b8 Reduce a tiny bit of duplication in the normalizeBlendMode helper 2026-07-27 13:59:38 +02:00
Jonas Jenwald
5406d3159b Change defaultOptions, in the web/app_options.js file, to a Map
Compared to regular Objects there's a number of advantages to using Maps, e.g. they support proper iteration.

Additionally the conditionally defined options are moved into the main list, to maintain alphabetical order for each individual `OptionKind`.
Finally, the `enableSelectionRendering` option is moved to its "correct" position and the `enableFakeMLManager` option is limited to TESTING builds (since that's consistent with its usage in `web/app.js`).

*Note:* Despite making the source-code larger, the size of the `gulp mozcentral` bundle is *reduced* by `686` bytes.
2026-07-27 12:53:13 +02:00
Tim van der Meij
2ea8820d92
Merge pull request #21641 from calixteman/perf/pattern-color
Convert shading colors in bulk, rather than one at a time
2026-07-26 17:49:24 +02:00
calixteman
526b69651f
Convert shading colors in bulk, rather than one at a time
The axial/radial ramps and the function-based lattice converted one color per
call, i.e. one Wasm round-trip each for `IccColorSpace` (hence for
`/DeviceCMYK`). Add `ColorSpace.getRgbItems`, overridden by `IccColorSpace` and
`AlternateCS`, to convert a whole batch at once.
2026-07-26 17:02:22 +02:00
calixteman
ce59339829
Merge pull request #21637 from calixteman/perf/indexed-cs-palette-lookup
Convert the /Indexed palette in a single base color space call
2026-07-26 15:38:49 +02:00
Tim van der Meij
fd612d86bd
Merge pull request #21639 from timvandermeij/updates
Update dependencies to the most recent versions
2026-07-26 15:36:26 +02:00
calixteman
a0f100c4a8
Convert the /Indexed palette in a single base color space call
`IndexedCS` invoked the base color space once per palette entry, which is
cheap for e.g. `DeviceRgbCS` but not for `IccColorSpace` where every call
is a Wasm round-trip.
2026-07-26 14:54:24 +02:00
Tim van der Meij
010da074af
Fix vulnerability in the brace-expansion dependency
This patch is automatically generated with `npm audit fix` and fixes
CVE-2026-13149.
2026-07-26 14:33:10 +02:00
Tim van der Meij
f7578565ef
Update dependencies to the most recent versions 2026-07-26 14:30:13 +02:00
calixteman
f38ea2d4cc
Merge pull request #21629 from calixteman/notification_bar
Add the Firefox features notification bar to the viewer (bug 2057608)
2026-07-26 14:24:22 +02:00
Tim van der Meij
1012c3e500
Merge pull request #21627 from mozilla/dependabot/npm_and_yarn/fast-uri-3.1.4
Bump fast-uri from 3.1.2 to 3.1.4
2026-07-26 11:59:37 +02:00
Tim van der Meij
d246a6c495
Merge pull request #21630 from calixteman/fix/formInfo-inherited-document-signatures
Detect inherited signature fields in form info
2026-07-26 11:57:59 +02:00
Tim van der Meij
150fbba6e0
Merge pull request #21628 from calixteman/fix/pdf-editor-inherited-signature-flags
Preserve inherited signature flags
2026-07-26 11:56:38 +02:00
Jonas Jenwald
e2d602122d
Merge pull request #21635 from Snuffleupagus/test-toBeTrue
Use the `toBeTrue()` matcher consistently in the unit/font/integration tests
2026-07-26 00:48:40 +02:00
Jonas Jenwald
62d211ee8d Use the toBeTrue() matcher consistently in the unit/font/integration tests
This replaces all `toEqual(true)` and `toBe(true)` occurrences.
2026-07-25 23:52:28 +02:00
Jonas Jenwald
a97d0aa682
Merge pull request #21634 from Snuffleupagus/test-toBeFalse
Use the `toBeFalse()` matcher consistently in the unit/integration tests
2026-07-25 23:36:28 +02:00
Jonas Jenwald
6963b0ef4f Use the toBeFalse() matcher consistently in the unit/integration tests
This replaces all `toEqual(false)` and `toBe(false)` occurrences.
2026-07-25 22:49:03 +02:00
Jonas Jenwald
b75ca17e85
Merge pull request #21636 from Snuffleupagus/test-toThrowError
Use the `toThrowError()` matcher consistently in the unit tests
2026-07-25 22:34:59 +02:00
Jonas Jenwald
dd41cd487d
Merge pull request #21633 from Snuffleupagus/test-toBeUndefined
Use the `toBeUndefined()` matcher consistently in the unit tests
2026-07-25 22:34:29 +02:00
Jonas Jenwald
503632a382
Merge pull request #21632 from Snuffleupagus/test-toBeNull
Use the `toBeNull()` matcher consistently in the unit/integration tests
2026-07-25 22:34:00 +02:00
Jonas Jenwald
83844f1261
Merge pull request #21631 from Snuffleupagus/XRef-private-fields
Re-factor the `XRef` class to use private fields
2026-07-25 22:33:32 +02:00
Jonas Jenwald
432d5c57a4 Use the toThrowError() matcher consistently in the unit tests
Currently we mostly use `toThrow()`, which seems intended for things that throw non-Errors (something that we "forbid" with ESLint).
Hence `toThrowError()` seems more appropriate, and it also simplifies things slightly; see https://jasmine.github.io/api/edge/matchers.html#toThrowError
2026-07-25 14:30:55 +02:00
Jonas Jenwald
a9672298fc Use the toBeUndefined() matcher consistently in the unit tests
This replaces all `toEqual(undefined)` and `toBe(undefined)` occurrences.
2026-07-25 13:30:13 +02:00
Jonas Jenwald
60340d9f28 Use the toBeNull() matcher consistently in the unit/integration tests
This replaces all `toEqual(null)` and `toBe(null)` occurrences.
2026-07-25 12:58:43 +02:00
Jonas Jenwald
a7b7cec2e7 Re-factor the "nested trailer dictionary" check (PR 4731 follow-up)
In the `pr4731.pdf` document the trailer is actually a Stream, rather than the expected Dictionary, hence update the "nested trailer dictionary" check to make that clearer.

*Note:* This is something that I happened to noticed while working on the previous patch.
2026-07-25 12:18:45 +02:00
Jonas Jenwald
1ee8705093 Re-factor the XRef class to use private fields
Part of this is very old code, hence modernizing it a little bit more really shouldn't hurt.
This patch also shortens some `XRef` code by using nullish coalescing assignment respectively ternary operators more.

Finally, adds the recently introduced `countUpdatesAfter` method to the `XRefMock`/`XRefWrapper` classes to avoid having to check for its existence.
2026-07-25 12:18:43 +02:00
Calixte Denizet
f195bec9b2
Add the Firefox features notification bar to the viewer (bug 2057608)
The bar itself (`<pdf-features-notification>`) ships from mozilla-central, so
the viewer only hosts it.

Finally the maximum number of preferences is raised to 60, to match the change
made in mozilla-central in bug 2056102, since this adds a 51st one.
2026-07-25 08:43:01 +02:00
Calixte Denizet
ac75b10be1 Detect inherited signature fields in form info 2026-07-24 21:43:32 +02:00
Calixte Denizet
27cf9e24f3 Preserve inherited signature flags 2026-07-24 20:42:26 +02:00
Tim van der Meij
05e100c76e
Merge pull request #21626 from calixteman/fix/pdf-editor-inherited-default-appearance
Preserve inherited text field appearances
2026-07-24 20:35:14 +02:00
dependabot[bot]
b0f73a321a
Bump fast-uri from 3.1.2 to 3.1.4
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.2 to 3.1.4.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.2...v3.1.4)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-24 18:32:47 +00:00
Tim van der Meij
586c3095d8
Merge pull request #21624 from Snuffleupagus/rm-objectSize
Remove the `objectSize` helper function
2026-07-24 20:31:54 +02:00
Tim van der Meij
be87eab392
Merge pull request #21625 from mozilla/dependabot/npm_and_yarn/linkify-it-5.0.2
Bump linkify-it from 5.0.1 to 5.0.2
2026-07-24 20:30:27 +02:00
Calixte Denizet
a97939b0d7 Preserve inherited text field appearances 2026-07-24 18:58:01 +02:00
dependabot[bot]
da713dfdd0
Bump linkify-it from 5.0.1 to 5.0.2
Bumps [linkify-it](https://github.com/markdown-it/linkify-it) from 5.0.1 to 5.0.2.
- [Changelog](https://github.com/markdown-it/linkify-it/blob/master/CHANGELOG.md)
- [Commits](https://github.com/markdown-it/linkify-it/compare/5.0.1...5.0.2)

---
updated-dependencies:
- dependency-name: linkify-it
  dependency-version: 5.0.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-24 13:26:08 +00:00
Jonas Jenwald
675e9219b5 Remove the objectSize helper function
Given that Maps are used a lot more these days, this helper function is now used very sparingly and inlining the necessary code seems reasonable.

*Note:* Once [this proposal](https://github.com/tc39/proposal-object-keys-length) makes it into Firefox, we should be able to simplify all `Object.keys(...).length` call-sites.
2026-07-24 12:49:44 +02:00
calixteman
fe0b880926
Merge pull request #21623 from mozilla/update-locales
l10n: Update locale files
2026-07-24 08:08:38 +02:00
github-actions[bot]
01642ed10c l10n: Update locale files 2026-07-24 00:34:42 +00:00
Tim van der Meij
63329559d3
Merge pull request #21622 from LuShadowX/document-recordoperation-params
Document the preserve and dependencyLists params for recordOperation
2026-07-23 21:21:53 +02:00
Tim van der Meij
47969a5953
Merge pull request #21620 from calixteman/improve_modif_detections
Improve the detection of the changes made after a document has been signed
2026-07-23 20:57:59 +02:00
Tim van der Meij
e58091a769
Merge pull request #21621 from Snuffleupagus/openAction-Map
[api-minor] Convert `getOpenAction` to return data in a Map
2026-07-23 20:57:42 +02:00
Tim van der Meij
890f2add63
Merge pull request #21618 from Snuffleupagus/Ref-str
Improve the `Ref.prototype.toString` method a tiny bit
2026-07-23 20:31:48 +02:00
LuShadowX
388168a2b8 Document the preserve and dependencyLists params for recordOperation 2026-07-23 19:31:33 +05:30
Jonas Jenwald
c474a97932 [api-minor] Convert getOpenAction to return data in a Map
Compared to regular Objects there's a number of advantages to using Maps:
 - They support proper iteration.
 - They have a simple way to check for the existence of data.
 - They have a simple/efficient way to check the number of elements.

If this functionality was added today, I cannot imagine that we'd choose an Object for this data.
2026-07-23 13:52:02 +02:00
Calixte Denizet
ed81227557 Improve the detection of the changes made after a document has been signed 2026-07-23 12:44:20 +02:00
Calixte Denizet
4ea07c2431
Only handle scripting updates that target a known field
Collect the ids of the document field annotations and ignore any id
coming from the scripting sandbox that isn't among them.
2026-07-22 16:11:57 +02:00
Jonas Jenwald
27a8002f7e Improve the Ref.prototype.toString method a tiny bit
When getting/creating a new `Ref` instance, via the static `Ref.get` method, we already need to compute a cache-key.
Since this key is identical to the format used by the `toString` method, we can avoid having to re-create that string (a lot) by also providing it to the `Ref` constructor.
2026-07-22 13:27:26 +02:00
Calixte Denizet
6c18df5768
Restrict the elements, attributes and styles the XFA layer can render
Only create a known set of HTML/SVG elements, and only apply a known set
of attributes and CSS properties, when building the XFA/rich-text DOM;
anything else is now ignored.
2026-07-22 12:12:08 +02:00
calixteman
0c8f67059e
Merge pull request #21616 from calixteman/fix/pdf-editor-indirect-default-resources
Preserve indirect AcroForm resources
2026-07-21 21:45:13 +02:00
Tim van der Meij
f988c56394
Merge pull request #21615 from Snuffleupagus/Binder-reuse-NS_DATASETS
Re-use the `NS_DATASETS` constant more in the `src/core/xfa/bind.js` file
2026-07-21 20:16:39 +02:00
Tim van der Meij
1b48daa461
Merge pull request #21614 from mozilla/dependabot/github_actions/github/codeql-action/autobuild-4.37.0
Bump github/codeql-action/autobuild from 4.36.3 to 4.37.0
2026-07-21 20:10:19 +02:00
Tim van der Meij
2bdd9e3d9c
Merge pull request #21613 from mozilla/dependabot/github_actions/github/codeql-action/init-4.37.0
Bump github/codeql-action/init from 4.36.3 to 4.37.0
2026-07-21 20:10:05 +02:00
Tim van der Meij
34268e38fc
Merge pull request #21611 from mozilla/dependabot/github_actions/github/codeql-action/analyze-4.37.0
Bump github/codeql-action/analyze from 4.36.3 to 4.37.0
2026-07-21 20:09:53 +02:00
Tim van der Meij
876ec4bd96
Merge pull request #21612 from mozilla/dependabot/github_actions/actions/setup-node-7.0.0
Bump actions/setup-node from 6.4.0 to 7.0.0
2026-07-21 20:06:47 +02:00
Calixte Denizet
f0bbfa6f9e Preserve indirect AcroForm resources 2026-07-21 19:41:45 +02:00
Jonas Jenwald
69e26ad319 Re-use the NS_DATASETS constant more in the src/core/xfa/bind.js file 2026-07-21 16:04:24 +02:00
dependabot[bot]
cfb92313fa
Bump github/codeql-action/autobuild from 4.36.3 to 4.37.0
Bumps [github/codeql-action/autobuild](https://github.com/github/codeql-action) from 4.36.3 to 4.37.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](54f647b7e1...99df26d4f1)

---
updated-dependencies:
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 12:16:47 +00:00
dependabot[bot]
569bae5900
Bump github/codeql-action/init from 4.36.3 to 4.37.0
Bumps [github/codeql-action/init](https://github.com/github/codeql-action) from 4.36.3 to 4.37.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](54f647b7e1...99df26d4f1)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 12:15:32 +00:00
dependabot[bot]
6509517da3
Bump actions/setup-node from 6.4.0 to 7.0.0
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.4.0 to 7.0.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](48b55a011b...8207627860)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 12:14:16 +00:00
dependabot[bot]
f97e61a7a2
Bump github/codeql-action/analyze from 4.36.3 to 4.37.0
Bumps [github/codeql-action/analyze](https://github.com/github/codeql-action) from 4.36.3 to 4.37.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](54f647b7e1...99df26d4f1)

---
updated-dependencies:
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 12:14:00 +00:00
Jonas Jenwald
028c02f539
Merge pull request #21607 from Snuffleupagus/viewerPreferences-Map
[api-minor] Convert `getViewerPreferences` to return data in a Map
2026-07-20 22:14:55 +02:00
Tim van der Meij
d314788368
Merge pull request #21604 from calixteman/issue21593
Copy the backdrop for non-isolated groups with a soft mask
2026-07-20 20:00:28 +02:00
Tim van der Meij
1a1090a0ae
Merge pull request #21602 from timvandermeij/updates
Update dependencies to the most recent versions
2026-07-20 19:53:39 +02:00
Tim van der Meij
559ab148a9
Merge pull request #21603 from timvandermeij/gitattributes
Update the file format entries in `.gitattributes`
2026-07-20 19:53:15 +02:00
calixteman
997dabf5a9
Merge pull request #21606 from calixteman/fix/ambiguous-date-format
Fix parsing of ambiguous date formats like `Hm`
2026-07-20 17:05:01 +02:00
Jonas Jenwald
67ed457bb8 Bump library version to 6.2
See commit eddd70a2ca1054ad2e0792972c3f2774b89f0cd2
2026-07-20 16:52:39 +02:00
Jonas Jenwald
de3eecca11 [api-minor] Convert getViewerPreferences to return data in a Map
Compared to regular Objects there's a number of advantages to using Maps:
 - They support proper iteration.
 - They have a simple way to check for the existence of data.
 - They have a simple/efficient way to check the number of elements.

If this functionality was added today, I cannot imagine that we'd choose an Object for this data.
2026-07-20 16:52:36 +02:00
calixteman
09a45ad2af
Merge pull request #21601 from uwezkhan/fix-postscript-wasm-i32const-sleb128
Encode i32.const immediates as signed LEB128 in the PostScript Wasm compiler
2026-07-20 15:29:20 +02:00
Calixte Denizet
d5661f801f Fix parsing of ambiguous date formats like Hm
We support having hours/minutes numbers with one or two digits for strings like "1:30:31" but
if the format is for example Hm, then "12" is really ambiguous.
So the idea is to match the longest string as possible.
2026-07-20 15:23:23 +02:00
uwezkhan
778aa450d9 Encode i32.const immediates as signed LEB128 in the PostScript Wasm compiler
The Type-4 PostScript -> Wasm compiler emitted i32.const immediates with the
unsigned LEB128 encoder (_emitULEB128). Wasm decodes i32.const as a *signed*
LEB128, so any immediate whose final 7-bit group has bit 0x40 set is
mis-decoded (e.g. 64 -> single byte 0x40 -> read back as -64).

The output-store address for the i-th result is emitted as i32.const (i*8).
For a function with >= 9 outputs the 9th offset is 64, which decodes as -64, so
f64.store targets 0xFFFFFFC0 and traps (memory access out of bounds). The module
still validates and instantiates, so the JS fallback in function.js is not
engaged; the trap only surfaces at render time (the affected shading / tint
transform silently fails to render). The same mis-encoding affects the constant
bitshift amount.

Add a signed-LEB128 emitter (_emitSLEB128) and use it for the three i32.const
immediate sites; local/import/type indices remain unsigned (correct). Add a unit
test covering functions with 9+ outputs, and a reference test rendering a shading
whose colour function has 9 outputs.
2026-07-20 14:56:04 +05:30
Jonas Jenwald
cd03276d60
Merge pull request #21594 from Snuffleupagus/issue-21582
Ignore Annotations with `fieldValue = null` when saving (issue 21582)
2026-07-20 11:13:03 +02:00
calixteman
547236bcd5
Merge pull request #21605 from calixteman/followup_21598
Address follow-up review comments in coverage_search.mjs
2026-07-19 23:19:55 +02:00
Jonas Jenwald
ee56dc7719 Ignore Annotations with fieldValue = null when saving (issue 21582)
Some Annotations, e.g. `SignatureWidgetAnnotation`, set `fieldValue = null` which may causing saving to fail during `writeXFADataForAcroform`, hence we simply ignore any such Annotation-data during saving.
2026-07-19 23:00:31 +02:00
calixteman
850020a84e
Address follow-up review comments in coverage_search.mjs
Use a Headers object for the request and log informational progress
messages via console.log instead of console.error.
2026-07-19 21:54:45 +02:00
calixteman
50601d0341
Copy the backdrop for non-isolated groups with a soft mask
PR #21455 drew non-isolated blend-mode groups against their backdrop via a
direct path on the parent canvas, but a soft mask forces the group onto an
intermediate canvas instead. There the inner blend modes composited against
transparency, so e.g. a /Multiply highlight was painted opaquely over the
text behind it, hiding it.

Copy the backdrop into that intermediate canvas so the blends see the real
background. The copy is limited to groups that would otherwise have taken
the direct path (source-over, alpha 1, not knockout/gray) but were displaced
onto the intermediate canvas by the soft mask.

It fixes #21593.
2026-07-19 21:01:28 +02:00
Tim van der Meij
154e82871a
Update the file format entries in .gitattributes
Several extensions (`.coffee`, `.jade`, `.inc` and others) became
obsolete in e.g. the conversion to Wintersmith/Fluent/other tools, while
other new extensions (`.mjs`, `.njk`, `.py` and others) were missing.

This commit removes all obsolete file format entries, adds all missing
ones and orders the list alphatically (so it can more easily be matched
against tooling that lists all in-use file extensions in the repository).
2026-07-19 19:33:10 +02:00
Tim van der Meij
a3a0d5d9a0
Upgrade eslint-plugin-unicorn to version 72.0.0
This is a major version bump, but the changelog at
https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v72.0.0
doesn't indicate any breaking changes that should impact us.
2026-07-19 18:53:34 +02:00
Tim van der Meij
299624a2d3
Update dependencies to the most recent versions 2026-07-19 18:52:20 +02:00
Tim van der Meij
5266f13ea4
Merge pull request #21599 from Snuffleupagus/CompiledFont-rm-hasBuiltPath
Combine the `getPathJs` and `hasBuiltPath` methods in the `CompiledFont` class
2026-07-19 18:39:16 +02:00
Jonas Jenwald
02027ba381 Combine the getPathJs and hasBuiltPath methods in the CompiledFont class
This avoids duplicating the charCode/glyphId lookup, and (slightly) shortens the code. In particular:
 - Given that the path-data is returned as a TypedArray, it's easy enough to instead return `null` to indicate that the glyph was previously compiled.

 - The charCode-cache can be changed into a Set, since we only need to track the "seen" charCodes and not their relation to the glyphIds.

 - The `compileFontPathInfo` call is moved into `CompiledFont` class, since that simplifies the `src/core/evaluator.js` code a tiny bit.
2026-07-19 16:48:07 +02:00
calixteman
ee6d5f2102
Merge pull request #21598 from calixteman/use_per_test
Download the per-test coverage index
2026-07-19 16:45:19 +02:00
calixteman
e6c7ab5425
Skip the cache existence check when --no-download is set
Move the `fs.existsSync(indexPath)` check below the `--no-download`
early return: in that mode the check is unused (the read after
refreshIndex already validates existence), so it's wasted disk I/O.
2026-07-19 16:42:05 +02:00
calixteman
c7dc7d7dd0
Sanitize the cached ETag and index to satisfy CodeQL
Address two CodeQL findings on the per-test index downloader:

- "File data in outbound network request": validate the cached ETag
  against the RFC 7232 grammar before sending it as If-None-Match, so
  the cache file's contents can't be injected into the request header.
- "Network data written to file": cache the re-serialized JSON
  (JSON.stringify(JSON.parse(...))) instead of the raw response body,
  so only well-formed JSON produced by our own serializer is written.
2026-07-19 16:13:20 +02:00
Jonas Jenwald
eddd70a2ca
Merge pull request #21597 from Snuffleupagus/destinations-Map
[api-minor] Convert `getDestinations` to return data in a Map
2026-07-19 16:06:12 +02:00
calixteman
d504000012
Download the per-test coverage index
`coverage_search` now fetches `per-test-index.json` from the pdf.js.refs
gh-pages branch, caches it locally, and only re-downloads it (via ETag)
when it changed, so querying which ref tests cover a line/function no
longer needs a local `--coverage-per-test` build. `--no-download` reuses
the cached index offline and `--index` points at a local one.

`browsertest` and `makeref` accept the same `--code` filter to run (or
regenerate refs for) only the covering tests, dropping any covered IDs
that aren't in this branch's manifest so the run isn't rejected.
2026-07-19 15:37:05 +02:00
Tim van der Meij
b83274803c
Merge pull request #21588 from calixteman/fix/pdf-editor-struct-attribute-revisions
Handle revisioned structure attributes
2026-07-19 14:11:08 +02:00
Tim van der Meij
fd77b3ea9f
Merge pull request #21591 from calixteman/fix/pdf-editor-missing-acroform-fields
Rebuild missing AcroForm fields
2026-07-19 14:08:40 +02:00
Tim van der Meij
4f7f3baed4
Merge pull request #21587 from calixteman/smask_in_data
Implement SmaskInData == 2 for JPX images
2026-07-19 13:57:41 +02:00
Tim van der Meij
8c3941a0d5
Merge pull request #21595 from Snuffleupagus/CompiledFont-Maps
Change the `CompiledFont` glyph/charCode caches to use `Map`s
2026-07-19 13:53:12 +02:00
Tim van der Meij
0a3ed983be
Merge pull request #21596 from Snuffleupagus/pattern-bCache-Map
Re-factor the `bCache`, used with /Mesh Shadings
2026-07-19 13:50:44 +02:00
Tim van der Meij
be89d6475d
Merge pull request #21585 from Snuffleupagus/Iterator-join
Start using `Iterator.prototype.join` in the code-base
2026-07-19 13:48:06 +02:00
Tim van der Meij
f12c6f64ad
Merge pull request #21592 from Snuffleupagus/Iterator-helpers
Use Iterator methods to avoid some unnecessary Array creation
2026-07-19 13:46:58 +02:00
Tim van der Meij
e624336b2e
Merge pull request #21590 from Snuffleupagus/canvas-_getPattern-getOrInsertComputed
Use `getOrInsertComputed` in the `CanvasGraphics.prototype._getPattern` method
2026-07-19 13:45:56 +02:00
Jonas Jenwald
6fbd2227db [api-minor] Convert getDestinations to return data in a Map
Compared to regular Objects there's a number of advantages to using Maps:
 - They support proper iteration.
 - They have a simple way to check for the existence of data.
 - They have a simple/efficient way to check the number of elements.

If this functionality was added today, I cannot imagine that we'd choose an Object for this data.
2026-07-19 12:07:08 +02:00
Jonas Jenwald
344736bcad Re-factor the bCache, used with /Mesh Shadings
- Initialize the `bCache` lazily, since many/most PDF documents don't need it.
 - Change the `bCache` to a `Map`, rather than an Object, which thanks to `getOrInsertComputed` allows the `buildB` function to be inlined.

Also, while unrelated here, move the `this.matrix = null;` definition to the `BaseShadingPattern` class to reduce (a tiny bit of) unnecessary duplication.
2026-07-18 14:15:24 +02:00
Jonas Jenwald
b2cf8527c6 Change the CompiledFont glyph/charCode caches to use Maps
This code is old enough that it predates the general availability of `Map`, and these changes allow us to shorten the code a tiny bit.
2026-07-18 11:44:27 +02:00
Jonas Jenwald
47f2b22842 Use Iterator methods to avoid some unnecessary Array creation
Currently there are some spots in the code-base where intermediate Arrays are unnecessarily created from Iterators, before `filter` and `map` is used to create a final Array.
Thanks to newer Iterators methods, see e.g. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/filter, that can be now be avoided.
2026-07-17 21:23:08 +02:00
Calixte Denizet
922d57631b Rebuild missing AcroForm fields 2026-07-17 13:51:08 +02:00
Jonas Jenwald
0f060e1e64 Use getOrInsertComputed in the CanvasGraphics.prototype._getPattern method 2026-07-17 12:49:29 +02:00
calixteman
dd7e3731d1
Merge pull request #21589 from mozilla/update-locales
l10n: Update locale files
2026-07-17 08:08:07 +02:00
github-actions[bot]
9720182511 l10n: Update locale files 2026-07-17 00:38:00 +00:00
Calixte Denizet
eb58ccc100 Handle revisioned structure attributes 2026-07-16 22:18:26 +02:00
Calixte Denizet
f554d0c9c8 Implement SmaskInData == 2 for JPX images 2026-07-16 21:04:45 +02:00
Jonas Jenwald
9a7335d26b Start using Iterator.prototype.join in the code-base
This is an upcoming JavaScript feature, which helps avoid creating intermediate Arrays in some cases; see https://github.com/tc39/proposal-iterator-join

Firefox implemented this in [bug 2004803](https://bugzilla.mozilla.org/show_bug.cgi?id=2004803), and it was enabled by default in [bug 2047995](https://bugzilla.mozilla.org/show_bug.cgi?id=2047995).

This patch changes two Objects to Maps, in the XFA-parsing respectively the find-implementation, to make use of the new feature.
2026-07-16 20:45:01 +02:00
Tim van der Meij
16290afa3b
Merge pull request #21586 from Snuffleupagus/web-more-getOrInsertComputed
Use `Map.prototype.getOrInsertComputed` more in the `web/` folder
2026-07-16 20:32:34 +02:00
Tim van der Meij
d473678201
Merge pull request #21577 from calixteman/fix/pdf-editor-acroform-resource-xref
Fix AcroForm appearance resources when merging pages
2026-07-16 20:13:44 +02:00
Tim van der Meij
f472cb081c
Merge pull request #21575 from calixteman/fix/signature-fields-with-widget-kids
Fix signature fields with widget children
2026-07-16 20:08:35 +02:00
Jonas Jenwald
6d7bca521b Use Map.prototype.getOrInsertComputed more in the web/ folder 2026-07-16 19:37:13 +02:00
calixteman
6e18a52b86
Merge pull request #21583 from calixteman/sasl_prep
Support SASLprep for AES-256 revision 6 passwords
2026-07-16 19:21:39 +02:00
Jonas Jenwald
244fb9e822
Merge pull request #21581 from Snuffleupagus/createCipherTransform-rm-AES256Cipher-duplication
Reduce duplication in `CipherTransformFactory.prototype.createCipherTransform`
2026-07-16 17:03:26 +02:00
Calixte Denizet
2ea9c26d77 Support SASLprep for AES-256 revision 6 passwords 2026-07-16 16:58:58 +02:00
calixteman
e909f1f64f
Merge pull request #21580 from calixteman/issue21579
Fix decryption of AES-256 revision 5 PDFs with non-ASCII passwords
2026-07-16 16:42:42 +02:00
Calixte Denizet
5f09f797ab Fix decryption of AES-256 revision 5 PDFs with non-ASCII passwords
It fixes #21579.
2026-07-16 16:34:15 +02:00
Jonas Jenwald
01454570a7 Reduce duplication in CipherTransformFactory.prototype.createCipherTransform
After PR 21485 the `AES256Cipher` case is effectively duplicated, and while it's not a lot of code it's easy enough to avoid that.
2026-07-16 15:31:36 +02:00
Jonas Jenwald
e39b23904c
Merge pull request #21576 from Snuffleupagus/RefSetCache-getOrPutComputed
Add a `getOrPutComputed` method in the `RefSetCache` class
2026-07-15 17:45:47 +02:00
Calixte Denizet
914545dea3 Fix AcroForm appearance resources when merging pages
Merging pages with conflicting AcroForm /DR must inline the resources
each field's appearance relies on, since only one /DR survives in the
output. That fixup:
- resolved the appearance /Resources ref against the source document's
  xref instead of the merged one, so the lookup failed and merging threw
  (null.has(...));
- skipped checkbox/radio widgets, whose /AP /N is a sub-dictionary of
  appearance states rather than a single stream;
- threw on a non-dictionary /Resources (e.g. a stray name) instead of
  falling back to the default resources.
2026-07-15 16:56:04 +02:00
Jonas Jenwald
a3a7247366 Add a makeSet helper, to reduce function creation
This replaces inline `() => new Set()` statements, and also makes some `getOrInsertComputed` calls slightly shorter.
2026-07-15 15:24:25 +02:00
Jonas Jenwald
a18b581f00 Add a getOrPutComputed method in the RefSetCache class
This is equivalent to the native `Map.prototype.getOrInsertComputed()` method, and it helps simplify/shorten some existing code.
2026-07-15 15:24:22 +02:00
calixteman
82c6046e1d
Fix signature fields with widget children 2026-07-14 22:38:43 +02:00
Tim van der Meij
c661ba1408
Merge pull request #21573 from mozilla/dependabot/github_actions/github/codeql-action/analyze-4.36.3
Bump github/codeql-action/analyze from 4.36.2 to 4.36.3
2026-07-14 19:41:34 +02:00
Tim van der Meij
ff075a9c67
Merge pull request #21572 from mozilla/dependabot/github_actions/github/codeql-action/autobuild-4.36.3
Bump github/codeql-action/autobuild from 4.36.2 to 4.36.3
2026-07-14 19:41:24 +02:00
Tim van der Meij
4c0dcff572
Merge pull request #21571 from mozilla/dependabot/github_actions/github/codeql-action/init-4.36.3
Bump github/codeql-action/init from 4.36.2 to 4.36.3
2026-07-14 19:41:09 +02:00
Tim van der Meij
f62702068a
Merge pull request #21574 from Snuffleupagus/issue-21570
Skip setFillColorN/setStrokeColorN operators without valid arguments (issue 21570)
2026-07-14 19:39:55 +02:00
Jonas Jenwald
2cf7d30763 Skip setFillColorN/setStrokeColorN operators without valid arguments (issue 21570)
The PDF document in question is corrupt, and note that even Adobe Reader (i.e. the PDF reference implementation) cannot render it correctly.

Also, guard all other set fill/stroke color operators similarly.
2026-07-14 16:08:59 +02:00
dependabot[bot]
d12d215302
Bump github/codeql-action/analyze from 4.36.2 to 4.36.3
Bumps [github/codeql-action/analyze](https://github.com/github/codeql-action) from 4.36.2 to 4.36.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](8aad20d150...54f647b7e1)

---
updated-dependencies:
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-14 12:17:00 +00:00
dependabot[bot]
127470d994
Bump github/codeql-action/autobuild from 4.36.2 to 4.36.3
Bumps [github/codeql-action/autobuild](https://github.com/github/codeql-action) from 4.36.2 to 4.36.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](8aad20d150...54f647b7e1)

---
updated-dependencies:
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-14 12:15:31 +00:00
dependabot[bot]
e5c0130b80
Bump github/codeql-action/init from 4.36.2 to 4.36.3
Bumps [github/codeql-action/init](https://github.com/github/codeql-action) from 4.36.2 to 4.36.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](8aad20d150...54f647b7e1)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-14 12:14:01 +00:00
calixteman
accfa9a162
Merge pull request #21569 from calixteman/fix/pdf-editor-struct-tree-objr
Preserve OBJR children without restoring deleted pages
2026-07-13 22:55:15 +02:00
Calixte Denizet
8070e9dce1 Preserve OBJR children without restoring deleted pages
Skip OBJR entries whose targets were not copied with a retained page.
2026-07-13 22:25:28 +02:00
calixteman
0b613612ed
Merge pull request #21567 from calixteman/fix/pdf-editor-struct-tree-root-k
Handle indirect and dangling structure tree root kids
2026-07-13 22:01:59 +02:00
Calixte Denizet
dae773d74a Handle indirect and dangling structure tree root kids
Preserve indirect root kids and marked content from removed link annotations. Ignore dangling kid references instead of throwing.
2026-07-13 21:48:30 +02:00
calixteman
b19cc7c746
Merge pull request #21566 from calixteman/fix/pdf-editor-unicode-name-trees
Preserve Unicode destination and attachment names
2026-07-13 21:46:35 +02:00
Calixte Denizet
850dccbc17 Preserve Unicode destination and attachment names
Name-tree keys are PDF text strings, so encode named destinations with
stringToAsciiOrUTF16BE when writing the /Dests tree; otherwise a non-ASCII
name (e.g. "名") is truncated to a single byte and lost on round-trip. Sort
the name/number tree by byte value rather than localeCompare, matching the
order used when the tree is read back.

Apply the same encoding to deduplicated /EmbeddedFiles names: those are
rebuilt from a decoded display string, so a non-ASCII attachment name would
otherwise be corrupted when its duplicate is written.
2026-07-13 21:19:23 +02:00
Tim van der Meij
7505eeaeb4
Merge pull request #21565 from calixteman/fix/pdf-editor-link-destinations
Preserve non-local PDF link destinations
2026-07-13 21:05:13 +02:00
Tim van der Meij
ac25471588
Merge pull request #21568 from calixteman/bug2047516
Commit the current editing session before saving (bug 2047516)
2026-07-13 21:02:58 +02:00
Calixte Denizet
125f692589 Commit the current editing session before saving (bug 2047516)
When saving or downloading a document, an annotation that was still
being edited (e.g. an in-progress ink drawing) wasn't committed first,
so its content was missing from the saved file.
2026-07-13 19:08:42 +02:00
Calixte Denizet
a36e5acb30 Preserve non-local PDF link destinations 2026-07-13 14:27:47 +02:00
Tim van der Meij
5e3272c929
Merge pull request #21562 from timvandermeij/workflow-improvements
Improve the GitHub Actions workflow triggers and requirements
2026-07-12 18:06:41 +02:00
Tim van der Meij
e6a80f4893
Merge pull request #21563 from Snuffleupagus/src-core-return-await
Use direct `return await` a bit more in the `src/core/` folder
2026-07-12 18:06:20 +02:00
Tim van der Meij
ae179be764
Pin the full dependency trees of the font/Fluent linter test requirements
The `requirements.txt` files of the two Python-based builds only listed
the top-level dependency, and thus not the full dependency tree, and
only limited it via a version range. This means that the actual versions
we use for the builds are determined at runtime, and can thus easily
change if a new version gets published. This causes the builds to not be
deterministic, and it's in contrast to the JavaScript-based builds where
`package-lock.json` pins the full dependency tree with fixed versions.

This commit changes the `requirements.txt` files to follow the same
approach as `package-lock.json` and thus pin the full dependency tree to
fixed versions. This ensures deterministic builds, improves consistency
and provides better protection against e.g. supply chain attacks by not
automatically pulling in new versions as they are published (but rather
make updating versions a conscious and verifiable/auditable action). To
simplify the update process, and make it repeatable, we document the
full one-line generation commands inline.
2026-07-12 16:27:31 +02:00
Tim van der Meij
ebaa98b854
Run the font/Fluent linter tests if their Python requirements change
The `requirements.txt` files of the two Python-based workflows were not
included in the file-based allowlist, which prevented the font/Fluent
linter tests from running if their contents changed. This commit fixes
that oversight from the original introduction of the workflows.
2026-07-12 16:27:27 +02:00
Tim van der Meij
174fd47973
Run all tests if package-lock.json changes
If one of our dependencies changes it can have an effect on all tests we
have, for instance via the test runner, bundler or coverage collector.
This commit therefore updates all workflows that work with a file-based
allowlist to also trigger on `package-lock.json` changes so that we have
more certainty that any unintended effects of dependency updates can't
go by unnoticed, and thus improve stability.
2026-07-12 16:27:17 +02:00
Tim van der Meij
cbdea64c8a
Merge pull request #21561 from timvandermeij/updates
Update dependencies to the most recent versions
2026-07-12 16:25:02 +02:00
Tim van der Meij
abae23d6aa
Upgrade eslint-plugin-unicorn to version 71.0.0
This is a major version bump, but the changelog at
https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v71.0.0
doesn't indicate any breaking changes that should impact us.
2026-07-12 16:19:58 +02:00
Tim van der Meij
3435fb0da0
Update dependencies to the most recent versions 2026-07-12 16:19:30 +02:00
Jonas Jenwald
5b26d8d413 Use direct return await a bit more in the src/core/ folder
In these cases there's no need for a temporary variable, since the result of the asynchronous operation is returned as-is without any additional parsing.
2026-07-12 15:59:57 +02:00
Tim van der Meij
54af145989
Merge pull request #21560 from Snuffleupagus/more-for-of-3
Use `for...of` even more in the code-base
2026-07-11 18:14:46 +02:00
calixteman
612fa34760
Merge pull request #21553 from nicolo-ribaudo/fix-text-selection-dark-mode
Bug 2048531 - Improve selection contrast in dark mode
2026-07-11 16:09:41 +02:00
Jonas Jenwald
c46720d893 Use for...of even more in the code-base
This replaces a couple of "standard" `for` loops with the shorter `for...of` format instead.
2026-07-11 13:15:36 +02:00
Nicolò Ribaudo
199d738917
Bug 2048531 - Improve selection contrast in dark mode
On some OSes, the current approach of using `Highlight`/`HighlightText`
colors to draw selected text doesn't work when the OS is set to dark
mode, as we revert the `color-scheme` to `light` to compute them
(because PDFs are normally in light mode) but that does not affect the
`HighlightText` color (which depends not on the `color-scheme` but on
the `currentColor`).

Other than forcing the `color-scheme` to `light`, set the `color` to
`black` and use the `backgroud-color` to compute the `HighlightText`
color instead.

In OSes where `HighlightText` is theme-dependent this will result in the
OS-provided text color, while in OSes where it is `currentColor`-dependent
it will be based on the default color for light themes (i.e. black).
2026-07-10 18:19:28 +02:00
Jonas Jenwald
c4574a5470
Merge pull request #21554 from Snuffleupagus/more-startsWith
Replace a couple of `indexOf` calls with `startsWith`
2026-07-10 15:27:54 +02:00
calixteman
bd845483ac
Merge pull request #21555 from mozilla/update-locales
l10n: Update locale files
2026-07-10 11:06:52 +02:00
github-actions[bot]
4e43e7f1af l10n: Update locale files 2026-07-10 00:42:44 +00:00
Jonas Jenwald
f0822e527e Replace a couple of indexOf calls with startsWith
These cases weren't detected/fixed by the following ESLint plugin rule; see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-starts-ends-with.md

Additionally, replace the `if` with a ternary statement in the `external/builder/builder.mjs` file since this patch touches that code anyway.
2026-07-09 13:56:24 +02:00
Tim van der Meij
8bc2fe68e5
Merge pull request #21550 from Snuffleupagus/WorkerMessageHandler-more-async
Change Promise-returning worker message-handler functions to be asynchronous
2026-07-07 20:10:12 +02:00
Jonas Jenwald
d13c28a044 Change Promise-returning worker message-handler functions to be asynchronous
A number of these functions are old enough that they predate async/await, and making them asynchronous is ever so slightly shorter/simpler.
2026-07-07 13:25:28 +02:00
Jonas Jenwald
f0b5fc3b73 Remove unused parameters from worker message-handler functions
A lot of these (often old) handlers don't need any parameters, hence their `data` parameters needlessly increase code-size.

Also, for the functions that do need parameters, use parameter destructuring consistently throughout the message-handler functions.
2026-07-07 13:25:26 +02:00
Jonas Jenwald
d29293622e Shorten the info-logging in the "GetOperatorList" and "GetTextContent" handlers
By re-using the `WorkerTask`-names these disabled-by-default logging statements become ever so slightly shorter, which cannot hurt.
2026-07-07 13:09:58 +02:00
Jonas Jenwald
0d5a7d8adc Remove TODO-comments in the "GetOperatorList" and "GetTextContent" handlers
Any errors are already propagated via the stream-sinks, since these handlers use `ReadableStream`, and as mentioned in the TODO-comments re-throwing errors will lead to "spam" in the console; hence let's just remove them.
2026-07-07 12:51:49 +02:00
Jonas Jenwald
18f9aa91b6
Merge pull request #21547 from timvandermeij/core-utils-test
Implement unit tests for the `getRotationMatrix` core utility function
2026-07-07 11:02:28 +02:00
Tim van der Meij
67d591f413
Implement unit tests for the getRotationMatrix core utility function
This function is mostly covered indirectly by higher-level tests, but
unlike the other core utility functions it lacked dedicated unit tests.
This commit implements unit tests for it that also cover the previously
uncovered exception case, which brings coverage of the function to 100%
and ever so slighly increases coverage of the overarching file.
2026-07-06 20:43:03 +02:00
Jonas Jenwald
6689097a0a
Merge pull request #21543 from Snuffleupagus/FakeSignatureVerifier
Add a `FakeSignatureVerifier` for development mode and TESTING builds (PR 21247 follow-up)
2026-07-05 23:20:58 +02:00
Jonas Jenwald
98ccc87fdc
Merge pull request #21546 from timvandermeij/murmurhash-test
Implement a unit test for passing unsupported data types to `MurmurHash3_64.update()`
2026-07-05 23:03:05 +02:00
Tim van der Meij
f0818c1860
Implement a unit test for passing unsupported data types to MurmurHash3_64.update()
This commit brings the coverage of `src/shared/murmurhash3.js` to 100%.
2026-07-05 19:55:06 +02:00
calixteman
bf924ff31b
Merge pull request #21521 from calixteman/issue21520
Use `Intl.Segmenter` for the entire-word search matching
2026-07-05 19:20:36 +02:00
Tim van der Meij
f03e18f336
Merge pull request #21544 from Snuffleupagus/extractFontProgram-lenIV
Lookup "lenIV" inline in the `Type1Parser.prototype.extractFontProgram` method
2026-07-05 19:20:02 +02:00
Tim van der Meij
d008aba0b1
Merge pull request #21545 from Snuffleupagus/TextLayer-setAttribute-id-string
Don't needlessly wrap the marked content `id`-attribute in a string
2026-07-05 19:19:09 +02:00
Jonas Jenwald
cde4f9a7ed Don't needlessly wrap the marked content id-attribute in a string
When the marked content `id` is defined it'll always be a string, hence wrapping it in a string when setting the attribute is pointless; note e148b154cd/src/core/evaluator.js (L3529-L3531)
2026-07-05 18:23:43 +02:00
Jonas Jenwald
a4ed5b39f4 Lookup "lenIV" inline in the Type1Parser.prototype.extractFontProgram method
Using an intermediate variable seems completely unnecessary here.

Also, while unrelated, move a `HINTING_ENABLED` check to avoid pointless Array-length checks.
2026-07-05 17:12:09 +02:00
Tim van der Meij
e148b154cd
Merge pull request #21538 from greymoth-jp/fix/font-encodeString-fffe-fffff
Do not drop the character after U+FFFE or U+FFFF in Font.prototype.encodeString
2026-07-05 16:13:19 +02:00
Calixte Denizet
0c97aa7555
Use Intl.Segmenter for the entire-word search matching
`getCharacterType` was a port of the old `WordBreaker::GetClass`,
which has been removed and replaced with ICU4X word segmentation.
Use `Intl.Segmenter` instead, testing each match boundary on the two
adjacent grapheme clusters in isolation like Firefox's find.

It fixes #21520.
2026-07-05 14:37:21 +02:00
Jonas Jenwald
c188012280 Add a FakeSignatureVerifier for development mode and TESTING builds (PR 21247 follow-up)
Despite the `enableSignatureVerification` option/preference being enabled in development mode and TESTING builds, the lack of any `SignatureVerifier` implementation still renders the UI disabled.
This seems unfortunate, since it makes it more difficult to check that the digital signature UI works correctly:
 - That the button is visible when it's supposed to be, and that the panel can be opened/closed.
 - That the UI looks correct, w.r.t. the HTML elements and their CSS rules.
 - Currently the viewer JS code is effectively uncovered, with overall test-coverage dropping from `90` to `89` percent when PR 21247 landed.

To improve the current situation this patch adds a `FakeSignatureVerifier` class, limited to only development mode and TESTING builds, that treats every digital signature as invalid.
This allows easier manual testing, and also the addition of a few *very rudimentary* integration-tests.

*Note:* It probably wouldn't be all that difficult to add additional integration-tests for *valid* certificates, by having the test-cases instruct (during setup) the `FakeSignatureVerifier` how to respond to simulate verified certificates.
2026-07-05 13:43:25 +02:00
Tim van der Meij
330cc4f2f4
Merge pull request #21541 from Snuffleupagus/signature-api-unittests
Add API unit-tests for `getSignatures` and `getSignatureData` (PR 21247 follow-up)
2026-07-05 11:29:47 +02:00
Tim van der Meij
139d5a2951
Merge pull request #21539 from timvandermeij/updates
Update dependencies to the most recent versions
2026-07-05 11:27:08 +02:00
Jonas Jenwald
ac101f0381 Add API unit-tests for getSignatures and getSignatureData (PR 21247 follow-up)
Note that PR 21247 did include "local" unit-tests, however they don't cover all of the relevant API/Worker code-paths (which is noticeable in the coverage data).
The new unit-test added here uses a PDF document already present in the test-suite, and generally speaking testing a real-world PDF shouldn't hurt.
2026-07-04 17:08:39 +02:00
Tim van der Meij
d62118073b
Fix vulnerability in the js-yaml dependency
This patch is generated automatically using `npm audit fix` and fixes
GHSA-h67p-54hq-rp68.
2026-07-04 14:51:22 +02:00
Tim van der Meij
86dad16df3
Upgrade eslint-plugin-unicorn to version 70.0.0
This is a major version bump, but the changelog at
https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v69.0.0 and
https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v70.0.0
doesn't indicate any breaking changes that should impact us.
2026-07-04 14:51:22 +02:00
Tim van der Meij
4fd232a124
Update dependencies to the most recent versions
Note that the `prettier` update introduces a handful of formatting
changes (see https://prettier.io/blog/2026/06/27/3.9.0).

Moreover, the `tsc-alias` update requires explicitly defining the root
URL in the compiler options now, otherwise it errors with `tsc-alias
error: compilerOptions.rootDir is required with implicit baseUrl` (see
https://github.com/justkey007/tsc-alias/pull/259/changes).
2026-07-04 14:49:36 +02:00
greymoth-jp
2bbf32d83d Do not drop the character after U+FFFE or U+FFFF in Font.prototype.encodeString
encodeString has the same surrogate-pair guard that encodeToXmlString had
before #21526: `unicode > 0xd7ff && (unicode < 0xe000 || unicode > 0xfffd)`.
That predicate is also true for U+FFFE and U+FFFF, which are single UTF-16
code units, not surrogate pairs. The extra `i++` then steps over the
character that follows them, so it is silently dropped from the
font-encoded output used when saving or printing a PDF.

For example, encoding a string that is U+FFFF followed by "A", with a font
that has a glyph for both, returns an encoded result ending in "A" on this
branch but drops the "A" on master.

Same fix as #21526: the correct test for a real surrogate pair is
`unicode > 0xffff`, since codePointAt only returns a value at or above
0x10000 for an actual pair. This keeps existing behavior for real surrogate
pairs (e.g. emoji) and the U+FFFD boundary, and only stops the character
after U+FFFE/U+FFFF from being dropped.

Added test/unit/fonts_spec.js, since Font.prototype.encodeString had no
direct unit test. It calls the method on a minimal fake `this` (only
toUnicode/cMap are read), since building a full Font requires a complete
properties/font-file setup that this bug doesn't depend on.
2026-07-04 21:37:12 +09:00
Tim van der Meij
36835d919d
Merge pull request #21537 from Snuffleupagus/getComponents-MathClamp
Use the `MathClamp` helper in the `PDFImage.prototype.getComponents` method
2026-07-04 14:21:54 +02:00
Tim van der Meij
cb70c93e8a
Merge pull request #21536 from Snuffleupagus/PDFDocument-rm-unneeded-signatureData-null
Remove unneeded `this.#signatureData = null;` lines in `src/core/document.js`
2026-07-04 13:47:16 +02:00
Tim van der Meij
c79b005db7
Merge pull request #21511 from Snuffleupagus/eslint-logical-assignment-operators
Enable the unicorn/logical-assignment-operators ESLint plugin rule
2026-07-04 13:46:55 +02:00
Tim van der Meij
9c46f48f88
Merge pull request #21526 from spokodev/w33/pdfjs-encodexml-surrogate
Do not drop the character after U+FFFE or U+FFFF in encodeToXmlString
2026-07-04 13:38:22 +02:00
Jonas Jenwald
be90aa4f46 Use the MathClamp helper in the PDFImage.prototype.getComponents method 2026-07-04 13:23:37 +02:00
Jonas Jenwald
20e0d6de08 Remove unneeded this.#signatureData = null; lines in src/core/document.js
Given that this is the *initial value* of the field, setting it again when no signatures exist is pointless.
2026-07-04 12:57:04 +02:00
Jonas Jenwald
046e68d140 Extend the unicorn/logical-assignment-operators rule to if-statements
Please see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/logical-assignment-operators.md and https://eslint.org/docs/latest/rules/logical-assignment-operators#enforceforifstatements
2026-07-04 12:25:57 +02:00
Jonas Jenwald
2bc64ec330 Enable the unicorn/logical-assignment-operators ESLint plugin rule
Please see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/logical-assignment-operators.md and https://eslint.org/docs/latest/rules/logical-assignment-operators
2026-07-04 12:25:56 +02:00
Tim van der Meij
5b100c4509
Merge pull request #21525 from calixteman/20504_skia_followup
Apply the appearance-stream scale factor when text is shown, not on setFont
2026-07-03 20:17:53 +02:00
Tim van der Meij
cca78c1d32
Merge pull request #21475 from nicolo-ribaudo/babel-8
Update to Babel 8
2026-07-03 20:14:36 +02:00
Tim van der Meij
32f3906960
Merge pull request #21533 from Snuffleupagus/SignaturePropertiesManager-#bannerState
Move the `bannerStateForResults` helper into the `SignaturePropertiesManager` class (PR 21247 follow-up)
2026-07-03 20:13:58 +02:00
Tim van der Meij
e414f74375
Merge pull request #21534 from Snuffleupagus/addPasteButton-#getPageL10nArgs
Use the `#getPageL10nArgs` helper in the `PDFThumbnailView.prototype.addPasteButton` method
2026-07-03 20:11:49 +02:00
Tim van der Meij
70c52132af
Merge pull request #21514 from nicolo-ribaudo/remove-selection-conflict-chrome
Avoid text selection workaround in modern Chromium
2026-07-03 20:10:28 +02:00
Jonas Jenwald
0c076f5f0b Use the #getPageL10nArgs helper in the PDFThumbnailView.prototype.addPasteButton method
Rather than effectively duplicating code, we can re-use the existing helper here as well.
2026-07-03 16:18:25 +02:00
Jonas Jenwald
14f4cce29d Move the bannerStateForResults helper into the SignaturePropertiesManager class (PR 21247 follow-up)
This has a couple of advantages:
 - It allows accessing and iterating `this.#results` directly, without having to (needlessly) create a temporary array.

 - By moving the "worst status" computation into its own getter, it can be re-used from the `#updateButtonState` method as well which reduces code duplication.
2026-07-03 12:41:15 +02:00
calixteman
0cc1718b02
Merge pull request #21527 from Snuffleupagus/issue-21523
Add basic support for non-embedded TrebuchetMS fonts (issue 21523)
2026-07-03 10:21:11 +02:00
calixteman
ab90210aa4
Merge pull request #21531 from Snuffleupagus/PDFThumbnailViewer-#updateStatus-isCopy
Reduce duplication when updating undoButton/undoCloseButton in `PDFThumbnailViewer.prototype.#updateStatus`
2026-07-03 08:14:23 +02:00
calixteman
44ae5b0e9a
Merge pull request #21529 from Snuffleupagus/SignaturePropertiesManager-geckoview
[GeckoView] Add `web-digital_signature_properties_manager` import map (PR 21247 follow-up)
2026-07-03 08:13:08 +02:00
calixteman
394a08f8b0
Merge pull request #21532 from mozilla/update-locales
l10n: Update locale files
2026-07-03 08:12:10 +02:00
calixteman
4952e4d5eb
Merge pull request #21530 from beurdouche/dedupe-signature-properties-warn-icon
Deduplicate the signature-properties warn/error toolbar icon
2026-07-03 08:11:56 +02:00
github-actions[bot]
95604a3401 l10n: Update locale files 2026-07-03 00:42:56 +00:00
Jonas Jenwald
f373fbfa5b Reduce duplication when updating undoButton/undoCloseButton in PDFThumbnailViewer.prototype.#updateStatus 2026-07-03 00:03:17 +02:00
Benjamin Beurdouche
34629bd2cf Deduplicate the signature-properties warn/error toolbar icon
The warn and error state badges shipped as byte-identical files (an
X-in-circle glyph). Drop the redundant
toolbarButton-signaturePropertiesWarn.svg and point the warn state at
the error icon instead; the amber-vs-red distinction is preserved via
background-color (--sig-icon-warn vs --sig-icon-error), not the glyph.
2026-07-02 23:00:08 +02:00
Jonas Jenwald
12691fdf50 Remove unnecessary class-field resetting in SignaturePropertiesManager.prototype.setDocument (PR 21247 follow-up)
This corresponds to the initial values of these fields, and they were *already* reset when a (previous) PDF document was closed.
2026-07-02 19:44:35 +02:00
Jonas Jenwald
a1f1a56080 [GeckoView] Add web-digital_signature_properties_manager import map (PR 21247 follow-up)
Currently the GeckoView development viewer, i.e. http://localhost:8888/web/viewer-geckoview.html, is completely broken with the following error:
```
Uncaught TypeError: The specifier “web-digital_signature_properties_manager” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “../” or “/”. app.js:97:44
```
2026-07-02 19:44:28 +02:00
calixteman
a0061817e6
Merge pull request #21528 from calixteman/serialize-pages-deploy
Serialize GitHub Pages deployments to avoid concurrent deploy failures
2026-07-02 18:54:29 +02:00
Calixte Denizet
6f2dcd3955 Serialize GitHub Pages deployments to avoid concurrent deploy failures 2026-07-02 18:48:09 +02:00
Jonas Jenwald
f7a4abf9a7
Merge pull request #21524 from Snuffleupagus/SignaturePropertiesManager-setDocument
A couple of `SignaturePropertiesManager` improvements (PR 21247 follow-up)
2026-07-02 18:29:17 +02:00
calixteman
d5dafc3fb3
Merge pull request #21522 from spokodev/w32/pdfjs-escapepdfname
Fix escapePDFName producing malformed name escapes for control characters
2026-07-02 18:11:21 +02:00
Jonas Jenwald
15969fbe19 Add basic support for non-embedded TrebuchetMS fonts (issue 21523) 2026-07-02 15:13:01 +02:00
Yarchik
0aee1d5382 Do not drop the character after U+FFFE or U+FFFF in encodeToXmlString
encodeToXmlString skips surrogate pairs with the guard
`char > 0xd7ff && (char < 0xe000 || char > 0xfffd)` and then does `i++` to step
over the low surrogate. That predicate is also true for U+FFFE and U+FFFF, which
are single UTF-16 code units, not surrogate pairs. The `i++` then skips the
character that follows them, so it is silently dropped.

For example, encodeToXmlString of U+FFFF followed by "A" returned "&#xFFFF;"
instead of "&#xFFFF;A". The function serializes XML text nodes and attribute
values in xml_parser.js and xfa_object.js, so this corrupts round-tripped XML
and XFA content.

The correct test for a surrogate pair is `char > 0xffff`, since codePointAt
returns a value at or above 0x10000 only for a real pair. This preserves the
existing behavior for emoji, the U+FFFD boundary, and lone surrogates, and stops
dropping the character after U+FFFE and U+FFFF.
2026-07-02 14:03:49 +01:00
Calixte Denizet
d9999dcedd Apply the appearance-stream scale factor when text is shown, not on setFont
The font size (Tf) and the text matrix (Tm) can appear in any order in an
appearance stream. Applying the scale factor eagerly in setFont missed the
case where Tf precedes Tm (e.g. Skia-generated FreeText), yielding a wrong
guessed font size.
2026-07-02 14:51:10 +02:00
Jonas Jenwald
d66bd324fa
Merge pull request #21519 from timvandermeij/fix-workflow-version
Fix the version comment in the font tests GitHub Actions workflow
2026-07-02 14:09:50 +02:00
Jonas Jenwald
fa207b4ce8 A couple of SignaturePropertiesManager improvements (PR 21247 follow-up)
- Replace the `loadFromDocument` and `reset` methods with a single `setDocument` method, since that's consistent with many other viewer components.

 - Replace the internal `#loadToken` field with simple `pdfDocument` checks, when checking if the document is still current, which again is consistent with (all) other viewer components.

 - Remove a couple of comments, which didn't add a lot of value and sounded a whole lot like "AI speak".
2026-07-02 14:07:04 +02:00
calixteman
43c29379de
Merge pull request #20505 from calixteman/issue20504
Take into account the current transform when getting font size for FreeText
2026-07-02 12:30:10 +02:00
Yarchik
9710372a1b Fix escapePDFName producing malformed name escapes for control characters
escapePDFName emitted a single hex digit for character codes below 0x10
(TAB became #9, not #09). PDF 32000-1 7.3.5 requires exactly two hex digits
after #. On re-save (annotations, form fields, font names) such a Name is
written malformed and the lexer mis-parses it on reload, dropping bytes.
Pad the hex to two digits; a no-op for codes 0x10 to 0xFF.
2026-07-02 10:48:57 +01:00
calixteman
89836b76f0 Take into account the current transform when getting font size for FreeText
Fixes issue #20504.

And the text position in Arabic FreeText annotations.
2026-07-02 11:04:34 +02:00
Nicolò Ribaudo
ea43bb43fb
Avoid text selection workaround in modern Chromium
Chromium 148+ improved their selection behavior when it comes to absolutely
positioned elements, thus making text selectino in PDF.js much better.

Unfortunately this does not only mean that the workaround we currently have
for Chromium is unnecessary, but it actually become harmful. It conflicts
with Chromium's new behavior, making text selection *worse* on mobile.

As the change has been released in Chrome only a month ago, this patch keeps
the workaround for older Chromium versions. There is no easy way to
feture-detect is, so unfortunately we need to do user agent version detection.
2026-07-01 13:14:34 +02:00
Tim van der Meij
f9aacb1ba1
Fix the version comment in the font tests GitHub Actions workflow
It looks like Dependabot somehow didn't match, and thus update, the
version number correctly in the most recent bump.

Fixes 6b0777d5.
2026-06-30 20:23:53 +02:00
Tim van der Meij
614349086b
Merge pull request #21517 from mozilla/dependabot/github_actions/actions/cache/restore-6.1.0
Bump actions/cache/restore from 5.0.5 to 6.1.0
2026-06-30 20:11:06 +02:00
Tim van der Meij
3a3047efc8
Merge pull request #21515 from mozilla/dependabot/github_actions/actions/cache/save-6.1.0
Bump actions/cache/save from 5.0.5 to 6.1.0
2026-06-30 20:10:57 +02:00
Tim van der Meij
4d3b747a17
Merge pull request #21518 from mozilla/dependabot/github_actions/actions/checkout-7.0.0
Bump actions/checkout from 6.0.3 to 7.0.0
2026-06-30 20:09:55 +02:00
Tim van der Meij
9d4f06129c
Merge pull request #21516 from mozilla/dependabot/github_actions/actions/setup-python-6.3.0
Bump actions/setup-python from 6.2.0 to 6.3.0
2026-06-30 20:08:22 +02:00
calixteman
2578f6bff6
Merge pull request #21247 from beurdouche/master
Digital Signature and Certificate verification
2026-06-30 18:36:10 +02:00
dependabot[bot]
bb9c4af462
Bump actions/checkout from 6.0.3 to 7.0.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.3 to 7.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](df4cb1c069...9c091bb21b)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-30 12:16:46 +00:00
dependabot[bot]
2ce10c68d5
Bump actions/cache/restore from 5.0.5 to 6.1.0
Bumps [actions/cache/restore](https://github.com/actions/cache) from 5.0.5 to 6.1.0.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](27d5ce7f10...55cc834586)

---
updated-dependencies:
- dependency-name: actions/cache/restore
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-30 12:16:27 +00:00
dependabot[bot]
6b0777d55f
Bump actions/setup-python from 6.2.0 to 6.3.0
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6.2.0 to 6.3.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](a309ff8b42...ece7cb06ca)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-30 12:16:16 +00:00
dependabot[bot]
642f4d1b7a
Bump actions/cache/save from 5.0.5 to 6.1.0
Bumps [actions/cache/save](https://github.com/actions/cache) from 5.0.5 to 6.1.0.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](27d5ce7f10...55cc834586)

---
updated-dependencies:
- dependency-name: actions/cache/save
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-30 12:12:46 +00:00
Benjamin Beurdouche
07b1c625e1 Add Digital signature properties verification panel
Adds a new "Digital signature properties" doorhanger to the pdf.js
toolbar that lists every digital signature found in the opened PDF,
verifies each one (via NSS in the Firefox build through a new chrome
bridge), and shows per-signature status + certificate state.

The viewer side parses /Sig dicts in the worker
(`PDFDocument.signatures`), strict-validates the /ByteRange offsets
before slicing, and ships only signature metadata across the worker
boundary. The PKCS#7 blob and signed-data byte spans live in a
worker-side map and are fetched lazily one signature at a time via
a new `getSignatureData(id)` RPC, immediately before verification
runs, so the bytes never sit in main-thread memory for the
document's lifetime.

The panel is feature-gated by `pdfjs.enableSignatureVerification`
(true in MOZCENTRAL/TESTING, off by default in the GENERIC build).
External services expose a `createSignatureVerifier()` factory that
the Firefox build wires up to `nsIX509CertDB.asyncVerifyPKCS7Object`;
GENERIC builds return null and the toolbar button stays hidden.

UI summary:
- Toolbar button states: loading dots while in flight, then green
  check, orange `!`, or red `✕` based on the worst aggregate
  signature status.
- Doorhanger contains a banner summarising the document state, then
  one card per signature with status row + certificate row (sub-
  signatures nested under their outer revision via /ByteRange
  containment).
- Icons are mono SVGs themed via `mask-image` + `background-color`
  so they pick up light/dark/HCM via `--sig-icon-*` vars; flipped
  under RTL via `scaleX(var(--dir-factor))`. The HCM mapping reuses
  the alt-text vocabulary (ButtonFace / ButtonText / ButtonBorder /
  GrayText / AccentColor / LinkText) so this panel reads the same
  as the rest of the editor toolbar in high-contrast mode.
- All visible strings are localized via Fluent
  (`pdfjs-digital-signature-properties-*`); status row, banner, and
  certificate row use explicit lookup tables instead of generated
  ids so a grep finds them.
- Esc + outside-click close the panel through the viewer's existing
  handlers; the manager exposes `isOpen`, `close()`, and
  `shouldCloseOnClick(target)` for that.

This commit also adds a `test/pdfs/sig_corpus/` directory holding a
Python generator that produces a corpus of signed PDFs covering
every visible state of the doorhanger (verified / untrusted /
expired / invalid / unknown / multi-signature variants). The corpus
is intentionally NOT part of the automated test suite — it is a
manual-test tool. Generated `.pdf` files are gitignored; only the
generator, README, and a `user.js.example` snippet are tracked.
The generator shells out to mozilla-central's
`security/manager/tools/pycms.py` (resolved via `--mozilla-central
<path>` or the `MOZILLA_CENTRAL_SRC` env var) and the embedded test
trust anchors (`pdf-sign-ca` / `pdf-sign-ca-expired`), gated by
`security.pdf_signature_verification.enable_test_trust_anchors` so
the test certificates never validate in shipping Firefox.
2026-06-30 13:25:09 +02:00
Nicolò Ribaudo
b9609d0365
Update to Babel 8 2026-06-30 10:45:15 +02:00
calixteman
25eae30e4e
Merge pull request #21513 from calixteman/bug2051221
Remove the BOM from html files (bug 2051221)
2026-06-29 22:21:29 +02:00
calixteman
649fb9c970
Merge pull request #21501 from calixteman/sound
Add support for Sound annotations playing embedded audio
2026-06-29 13:21:08 +02:00
Calixte Denizet
3ccc3ec65c Add support for Sound annotations playing embedded audio
Wrap uncompressed PCM sound streams (Raw/Signed, 8/16-bit, mono/stereo)
in WAV and play them through the shared media overlay.
2026-06-29 12:30:48 +02:00
Calixte Denizet
d142fd2451 Remove the BOM from html files (bug 2051221)
Add add a linter in order to avoid future regressions.
2026-06-29 11:20:34 +02:00
calixteman
1651e57e61
Merge pull request #21507 from calixteman/publish-coverage-index
Add a workflow to publish the per-test coverage index
2026-06-29 11:15:38 +02:00
Calixte Denizet
e4846726ee Add a workflow to publish the per-test coverage index
This index is useful to know what are the tests hitting a specific part of the code.
The next step is to update coverage_search in order to use it instead of having to create
a local one.
2026-06-29 10:07:06 +02:00
Tim van der Meij
f2f3a7fdce
Merge pull request #21510 from timvandermeij/bump
Bump the stable version in `pdfjs.config`
2026-06-27 18:36:56 +02:00
Tim van der Meij
a20c46eca0
Bump the stable version in pdfjs.config 2026-06-27 18:33:07 +02:00
Tim van der Meij
6353acefe5
Merge pull request #21508 from Snuffleupagus/optional-chaining-not-length
Use more optional chaining in the `src/` and `web/` folders
2026-06-27 13:51:54 +02:00
Jonas Jenwald
b7b3a4c454 Use more optional chaining in the src/ and web/ folders
There's a few spots where we check if something is either undefined or if its length is zero, which can be simplified by instead using optional chaining.
2026-06-27 12:20:36 +02:00
Tim van der Meij
8bdd159699
Merge pull request #21505 from Snuffleupagus/StructTreeRoot-rm-init
Inline the `init` method in the `StructTreeRoot` constructor
2026-06-26 20:14:46 +02:00
Tim van der Meij
195226e3a6
Merge pull request #21500 from calixteman/bug2050191
Disable selection rendering when backdrop-filter is unsupported (bug 2050191)
2026-06-26 20:12:48 +02:00
Tim van der Meij
d8526132f5
Merge pull request #21487 from calixteman/issue17333
Render non-empty glyph 0 for char code 0
2026-06-26 20:08:51 +02:00
Jonas Jenwald
82324408cd Inline the init method in the StructTreeRoot constructor
Currently the constructor only set various class fields and the class instance thus needs to be "manually" initialized, which seems unnecessary.
Given how short/simple the `init` and `readRoleMap` methods are we can just inline their code in the constructor, thus simplifying the code overall.
2026-06-26 14:19:35 +02:00
calixteman
86ffd68c05
Merge pull request #21504 from nicolo-ribaudo/move-selection-styles
Move SVG text selection styles to pdf_viewer.css (bug 2049302)
2026-06-26 10:14:51 +02:00
Nicolò Ribaudo
5d81fe5098
Move SVG text selection styles to pdf_viewer.css
draw_layer_builder.css, which originally included these styles, is not
loaded in GECKOVIEW. This is because it also includes all the styles
related to highlights and drawing, which are only supported in the main
viewer.

The new SVG-based highlights are also used in GECKOVIEW, so even though
the JS logic for them lives in the DrawLayer builder, we need to move the CSS
somewhere where we know it's going to be loaded.
2026-06-25 15:55:26 +02:00
Jonas Jenwald
a1953e7c3c
Merge pull request #21502 from Snuffleupagus/issue17906-test-forms
Change `issue17906` to test "forms" rendering
2026-06-25 13:44:33 +02:00
Jonas Jenwald
beb332a245 Change issue17906 to test "forms" rendering
Looking at the coverage data the code-path added in PR 17908 isn't actually covered by tests; note 10844326c7/blob/src/core/annotation.js (L1250)
2026-06-25 11:59:57 +02:00
Jonas Jenwald
10844326c7
Merge pull request #21497 from Snuffleupagus/substring-tweaks
Tweak some `String.prototype.substring()` usage
2026-06-24 20:32:34 +02:00
Calixte Denizet
7f9c54a259 Disable selection rendering when backdrop-filter is unsupported (bug 2050191)
Selection rendering relies on the CSS backdrop-filter property, so it must
be gated on browser support for it.
2026-06-24 20:16:44 +02:00
Jonas Jenwald
eee03693a0
Merge pull request #21499 from Snuffleupagus/version-6.1
Bump library version to `6.1`
2026-06-24 19:47:37 +02:00
Jonas Jenwald
7414f6ed5a Bump library version to 6.1
See commit b168293c173b0b9befe462c0b254136cf038c3ef
2026-06-24 19:32:42 +02:00
Jonas Jenwald
5964e88be1
Merge pull request #21488 from Snuffleupagus/annotationGlobals-catalog
Include the `catalog` instance in the `annotationGlobals` data
2026-06-24 18:57:53 +02:00
Jonas Jenwald
6718c2924c Tweak some String.prototype.substring() usage
In a few spots the `indexEnd` parameter is explicitly set to the string-length, which is unnecessary since that's the default value if the parameter is omitted; note https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring#description

In the `XMLParserBase.prototype._resolveEntities` method the `substring` usage can be replaced with an updated (and cached) regular expression that directly finds numbers.
2026-06-24 18:52:46 +02:00
Jonas Jenwald
44e637a064 Remove explicit xref usage in the ScreenAnnotation.prototype.#renditionActions method
Rather than fetching "raw" dictionary-data and then manually resolving any references, we can simply use `Dict.prototype.get` and `Dict`-iteration to access the needed data *directly* instead.
2026-06-24 10:46:07 +02:00
Jonas Jenwald
15d93e1f34 Introduce a helper method, in the Annotation class, for determining the attachment fileId
This avoids duplication between the `FileAttachmentAnnotation` and `MediaAnnotation` classes, since they currently include essentially the same code for determining the attachment `fileId`.
2026-06-24 10:45:52 +02:00
Jonas Jenwald
8a2c112c20 Simplify the Annotation.prototype.setAppearance method a tiny bit
It's not necessary to check if the /AS entry exists first, and it can just be fetched directly, since in that case the existing "is stream"-check won't be true anyway.

Also, move the `appearance` field definition to the top of the class instead.
2026-06-24 10:42:38 +02:00
Jonas Jenwald
f07a106529 Include the catalog instance in the annotationGlobals data
The `FileAttachmentAnnotation` and `MediaAnnotation` code needs to (synchronously) access a `catalog` method, which leads to unnecessarily verbose code.
This can be avoided by including the `catalog` instance in the `annotationGlobals` data, which is safe since it already includes data that's fetched asynchronously from the `catalog` instance.
2026-06-24 10:42:38 +02:00
calixteman
04eeeec4a4
Merge pull request #21492 from timvandermeij/updates
Update dependencies to the most recent versions
2026-06-24 08:06:07 +02:00
calixteman
078b96229d
Render non-empty glyph 0 for char code 0
It fixes #17333.
2026-06-23 21:38:57 +02:00
calixteman
e6539f6516
Merge pull request #21490 from calixteman/screen_rendition
Add support for Screen annotations playing embedded media
2026-06-23 21:34:30 +02:00
Tim van der Meij
7a9abfb2dc
Fix vulnerability in the js-yaml dependency
This patch is generated automatically using `npm audit fix`, and
partially fixes GHSA-h67p-54hq-rp68.
2026-06-23 20:53:19 +02:00
Tim van der Meij
048331b09a
Upgrade @types/node to version 26.0.0
This is a major version bump, but the patch at
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/75025
doesn't indicate any breaking changes that should impact us as it mainly
includes support for Node.js 26.
2026-06-23 20:50:02 +02:00
Tim van der Meij
56843f9b42
Upgrade eslint-plugin-unicorn to version 68.0.0
This is a major version bump, but the changelog at
https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v67.0.0 and
https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v68.0.0
doesn't indicate any breaking changes that should impact us.
2026-06-23 20:50:02 +02:00
Tim van der Meij
7818ab1b9d
Update dependencies to the most recent versions 2026-06-23 20:50:02 +02:00
Calixte Denizet
d8ea2afe47 Add support for Screen annotations playing embedded media
Screen annotations whose rendition action resolves to an embedded audio/video
file now play through the same play-button overlay as RichMedia.
Factor the shared resolution logic into a MediaAnnotation base (used by both RichMedia and Screen).

It fixes #6078 and #2787.
2026-06-23 20:48:35 +02:00
Tim van der Meij
4117b75a10
Merge pull request #21486 from Snuffleupagus/getTextContent-sink-fixes
Improve the `sink` handling in `getTextContent` for Highlight annotations (PR 20019 follow-up)
2026-06-23 20:02:34 +02:00
Jonas Jenwald
813d1949ba
Merge pull request #21491 from Snuffleupagus/readCmapTable-sort-last
Sort the mappings *last* in the `readCmapTable` function (PR 19321 follow-up)
2026-06-23 16:01:09 +02:00
Jonas Jenwald
a1acf4fc9f
Merge pull request #21489 from Snuffleupagus/editor-tools-rm-testing-reset
Remove the `AnnotationEditorUIManager` and `IdManager` test-only `reset` methods (PR 19809 follow-up)
2026-06-23 14:03:46 +02:00
Jonas Jenwald
9ca13c9a23 Sort the mappings *last* in the readCmapTable function (PR 19321 follow-up)
This improves performance of `issue19319.pdf` even more, and locally the rendering time of the second page goes from ~300 ms to ~250 ms, since we avoid sorting a bunch of duplicate entries.
2026-06-23 13:51:37 +02:00
Jonas Jenwald
09c9f7f2fe Remove the AnnotationEditorUIManager and IdManager test-only reset methods (PR 19809 follow-up)
These test-only methods became unused in PR 19809.
2026-06-23 12:09:12 +02:00
calixteman
d71fe9025d
Merge pull request #21474 from calixteman/rich_media
Add support for RichMedia annotations
2026-06-22 22:29:14 +02:00
Calixte Denizet
d537f5ba4b
Add support for RichMedia annotations
Render `/Subtype /RichMedia` annotations so embedded video and audio can
be played in the viewer.

The core layer parses the `RichMediaContent` dictionary to locate the
primary playable asset and its MIME type. The display layer overlays a
play button on the annotation's poster; clicking it swaps in a
`<video>`/`<audio>` element backed by a `blob:` URL. Presentation mode
lets events reach the media controls instead of advancing the page.

It fixes #2787.
2026-06-22 21:27:52 +02:00
Tim van der Meij
b6469341c1
Merge pull request #21485 from calixteman/bug2046659
Use AES256 for V=5 documents with a mislabeled AESV2 crypt filter (bug 2046659)
2026-06-22 20:44:48 +02:00
Tim van der Meij
7ac6dff4b7
Merge pull request #21483 from calixteman/issue21430
Reset alpha before drawing a colored glyph in type 3 font
2026-06-22 20:40:55 +02:00
Jonas Jenwald
22871eef23 Improve the sink handling in getTextContent for Highlight annotations (PR 20019 follow-up)
Currently there's a couple of issues related to the `sink` handling:
 - The `Page.prototype.extractTextContent` method is invoked with options that it doesn't actually use; note 1ddf6449ac/src/core/document.js (L669-L676)

 - When parsing "nested" textContent, i.e. /Form /XObjects, we end up wrongly treating repeated /XObjects as empty for the annotations use-case since `enqueue` is never invoked; note 1ddf6449ac/src/core/evaluator.js (L3439) and 1ddf6449ac/src/core/evaluator.js (L3449-L3451)

 - The `getTextContent` method might become ever so slightly slower by having to defer parsing at every step, given the "bad" fallback value when comparing with the `TEXT_CONTENT_CHUNK_SIZE` constant (in the API), note 1ddf6449ac/src/display/api.js (L1705) and 1ddf6449ac/src/core/evaluator.js (L3566)

 - Having the `sink` now be effectively optional, in the `getTextContent` method, does complicate the code slightly overall.

To address these things this patch ensures that a `sink` will always be available, by re-using the `sinkWrapper` structure from the "nested" textContent case, and with reasonable default values.
2026-06-22 14:56:17 +02:00
Calixte Denizet
7f7e63333d Use AES256 for V=5 documents with a mislabeled AESV2 crypt filter (bug 2046659)
Some producers wrongly set the crypt filter CFM to AESV2 for V=5 documents;
per the spec these must be decrypted with AES256 using the file encryption key directly.
2026-06-22 14:54:24 +02:00
calixteman
1ddf6449ac
Merge pull request #21478 from calixteman/comb-field-vertical-centering
Vertically center the glyphs in comb text fields
2026-06-22 09:57:55 +02:00
Jonas Jenwald
28a7606c14
Merge pull request #21480 from Snuffleupagus/mathML-FileSpec
A couple of small tweaks of the `StructElementNode.prototype.mathML` getter
2026-06-21 23:44:28 +02:00
calixteman
623e6d9476
Reset alpha before drawing a colored glyph in type 3 font
It fixes #21430.
2026-06-21 23:06:43 +02:00
Jonas Jenwald
9c9b465fd2 A couple of small tweaks of the StructElementNode.prototype.mathML getter
- Use `FileSpec.pickPlatformItem` when getting the fileStream, to ensure that /EF-entries are handled in a consistent way across the code-base.

 - Combine a couple of the data-validation steps, to reduce a tiny bit of duplication. Also, use the `isDict` helper a little more.

 - Finally, avoid using a temporary variable when returning data in the `Page.prototype.getStructTree` method.
2026-06-21 22:47:13 +02:00
Tim van der Meij
8ebc2382e3
Merge pull request #21479 from Snuffleupagus/Annotation-#setOptionalContent-MissingDataException
Don't swallow `MissingDataException`s in the `Annotation.prototype.#setOptionalContent` method (PR 21313 follow-up)
2026-06-21 19:11:54 +02:00
Tim van der Meij
38daede697
Merge pull request #21481 from Snuffleupagus/metadata-isDict
Use the `isDict` helper in the `Catalog.prototype.metadata` getter
2026-06-21 19:10:54 +02:00
Tim van der Meij
86b901fcde
Merge pull request #21470 from Snuffleupagus/AnnotationEditorUIManager-rm-isSelected
Remove the unused `AnnotationEditorUIManager.prototype.isSelected` method
2026-06-21 19:09:32 +02:00
Tim van der Meij
1d8e952062
Merge pull request #21482 from Snuffleupagus/password-input-Enter-preventDefault
Stop event propagation, for the `Enter` key, in the passwordPrompt input
2026-06-21 19:05:50 +02:00
Tim van der Meij
018ba66228
Merge pull request #21472 from mozilla/dependabot/npm_and_yarn/undici-7.28.0
Bump undici from 7.24.3 to 7.28.0
2026-06-21 19:04:29 +02:00
Jonas Jenwald
a911ce22e5 Stop event propagation, for the Enter key, in the passwordPrompt input
**Steps to reproduce:**
 1. Open the viewer.
 2. Show the sidebar, and switch to the "Pages" view if necessary.
 3. Click on the "Add file" button.
 4. Choose a password-protected PDF, e.g. the `issue6010_1.pdf` file, via the "File Upload" dialog opened by the browser.
 5. Enter the password, i.e. `abc`, and press the <kbd>Enter</kbd> key.

**Expected result:**
That the new PDF document is merged into the existing one, without UI side-effects.

**Actual result:**
Merging works, *however* the "File Upload" dialog is re-opened.

---

It seems that when the passwordPrompt dialog closes, the <kbd>Enter</kbd> key press (from the input) is forwarded to the previously focused element which naturally is the "Add file" button.

*Note:* This doesn't seem (easily) possible to test, since the integration-tests directly populate the `viewsManagerAddFilePicker` and doesn't actually "click" on the `viewsManagerAddFileButton` first.
2026-06-21 15:30:05 +02:00
Jonas Jenwald
a46ee2b647 Use the isDict helper in the Catalog.prototype.metadata getter 2026-06-21 12:26:21 +02:00
Jonas Jenwald
bd6541864b Don't swallow MissingDataExceptions in the Annotation.prototype.#setOptionalContent method (PR 21313 follow-up)
Unless the entire document has been loaded, the dictionary lookups in `parseMarkedContentProps` may throw `MissingDataException`s and in that case we need to re-parse the current Annotation rather than ignoring the optionalContent.
2026-06-21 09:13:33 +02:00
Jonas Jenwald
124228e318
Merge pull request #21473 from Snuffleupagus/showText-rm-return-undefined
Remove unnecessary explicit return statements in `CanvasGraphics.prototype.showText`
2026-06-20 22:31:58 +02:00
Jonas Jenwald
bff30726fa
Merge pull request #21476 from Snuffleupagus/relative-URI-action-test
Add a unit-test for relative URI actions specified as /Name instances
2026-06-20 22:31:02 +02:00
Calixte Denizet
34516bcec3 Vertically center the glyphs in comb text fields 2026-06-20 18:47:24 +02:00
Jonas Jenwald
bade1f3190 Add a unit-test for relative URI actions specified as /Name instances
The following branch was added to fix issue 4159, however looking at the coverage data it's not actually tested; see 59df671552/src/core/catalog.js (L1866-L1869) and 59df671552/blob/src/core/catalog.js (L1866)
2026-06-19 23:58:50 +02:00
Jonas Jenwald
00e1aabe93 Remove unnecessary explicit return statements in CanvasGraphics.prototype.showText 2026-06-19 10:58:14 +02:00
dependabot[bot]
dfa673290b
Bump undici from 7.24.3 to 7.28.0
Bumps [undici](https://github.com/nodejs/undici) from 7.24.3 to 7.28.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v7.24.3...v7.28.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 7.28.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-19 07:33:31 +00:00
calixteman
59df671552
Merge pull request #21471 from mozilla/update-locales
l10n: Update locale files
2026-06-19 08:10:32 +02:00
github-actions[bot]
87361aa094 l10n: Update locale files 2026-06-19 01:04:57 +00:00
Jonas Jenwald
786019eb0d Remove the unused AnnotationEditorUIManager.prototype.isSelected method
According to the coverage data this method is unused, see e20c810dd4/blob/src/display/editor/tools.js (L2552), and searching through the entire code-base reveals no call-site invoking an `isSelected` method.
2026-06-18 23:21:53 +02:00
calixteman
e20c810dd4
Merge pull request #21469 from calixteman/issue21466
Avoid too long BlueScale value when rewriting a CFF font
2026-06-18 21:43:05 +02:00
calixteman
07d4c1018a
Avoid too long BlueScale value when rewriting a CFF font
It fixes #21466.
2026-06-18 20:48:13 +02:00
Jonas Jenwald
e74be44919
Merge pull request #21467 from Snuffleupagus/canvas-rm-unused
Remove unused branches in the `src/display/canvas.js` file
2026-06-18 19:57:51 +02:00
Jonas Jenwald
b4b0a3fa04 Remove the unused ImageData branch in the putBinaryImageData function
This branch isn't covered by any tests, and looking at the two existing call-sites we only ever pass in a `CanvasRenderingContext2D` interface to this function.
Based on the git history this branch was added in PR 3312, however as far as I can tell it doesn't actually appear to have been necessary even back then!?
2026-06-18 18:22:55 +02:00
Jonas Jenwald
a443a635a1 Remove the unused HTMLElement branch in the paintInlineImageXObject method
This branch isn't covered by any tests, and as far as I can tell it's been unused ever since PR 11601 which simplified the JPEG image handling.
Prior to that we'd create an `Image` instance in one case, see [this code](https://github.com/mozilla/pdf.js/pull/11601/changes#diff-082d6b37ad01db7ac97cc07c6ddb0dc52040484c5ef91b110b072f50144d9f39L2312-L2314), which is why that branch was necessary since `new Image()` creates a `HTMLImageElement` instance which in itself is an instance of `HTMLElement`; note [this](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image) respectively [this](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement).
2026-06-18 17:47:26 +02:00
calixteman
3956ac1b39
Merge pull request #21465 from calixteman/fix_attachments
Re-derive annotation attachment content from the xref after cleanup
2026-06-18 16:48:13 +02:00
Calixte Denizet
9d9fb06d7f Re-derive annotation attachment content from the xref after cleanup
Annotation-local attachments (those not in the catalog `/Names` tree) were
resolved through a dictionary cache that `Catalog.cleanup` clears, so their
content became unreachable once the idle cleanup had run.

Encode the reference of the embedded content in the attachment id and re-fetch
it from the xref on demand instead of caching the dictionary, so the content
stays reachable without anything having to survive cleanup.

It fixes a regression introduced by #21351.
2026-06-18 16:03:32 +02:00
calixteman
187c22126a
Merge pull request #21310 from calixteman/dont_save
Add a 'supportsDownloading' browser option to gate saving/downloading
2026-06-18 15:36:41 +02:00
Calixte Denizet
ece1e2ed0c Add a 'supportsDownloading' browser option to gate saving/downloading
Introduces a 'supportsDownloading' browser option (defaulting to false)
that lets embedders disable the save/download paths entirely. When
disabled:
  - the toolbar and secondary-toolbar download buttons are hidden;
  - PDFViewerApplication.{download,save,downloadOrSave} and the
    "beforeunload" save prompt bail out early;
  - the BaseDownloadManager helpers (download, downloadData,
    openOrDownloadData) and the Firefox/generic _triggerDownload
    implementations no-op.
2026-06-18 14:51:32 +02:00
Jonas Jenwald
2ed018ec2d
Merge pull request #21460 from Snuffleupagus/autolinking-check-every-LinkAnnotation
Check every LinkAnnotation when testing if inferred links overlap (issue 21458)
2026-06-16 22:32:07 +02:00
calixteman
eae42379f2
Merge pull request #21462 from calixteman/bluescale-small-zones
Don't clamp BlueScale up when a font genuinely has small zones
2026-06-16 21:52:25 +02:00
calixteman
d28030f838
Merge pull request #21463 from calixteman/fix_unit_test
Adjust the 'BaseException' unit-test for the 'Error.stack' changes in Firefox
2026-06-16 21:43:49 +02:00
Jonas Jenwald
cbefb334fd Check every LinkAnnotation when testing if inferred links overlap (issue 21458)
Currently we only check LinkAnnotations with URLs, but completely ignore e.g. internal destinations, named actions, attachments, SetOCGState actions, JS actions, and ResetForm actions when testing if inferred links overlap any existing annotation.
This seems conceptually wrong, since it may easily break intended functionality by overlaying the *correct* DOM element with an inferred link (as was the case in issue 21458).
2026-06-16 21:35:44 +02:00
Calixte Denizet
5432642250 Adjust the 'BaseException' unit-test for the 'Error.stack' changes in Firefox
Firefox 154 no longer walks the prototype chain in the `Error.stack`
getter, so `BaseException`-derived instances return an empty string
rather than the prototype `Error`'s stack (see bug 1946559).
2026-06-16 21:30:41 +02:00
Tim van der Meij
f0dc2166ab
Merge pull request #21464 from mozilla/dependabot/npm_and_yarn/markdown-it-14.2.0
Bump markdown-it from 14.1.1 to 14.2.0
2026-06-16 21:16:19 +02:00
dependabot[bot]
9ed97a859f
Bump markdown-it from 14.1.1 to 14.2.0
Bumps [markdown-it](https://github.com/markdown-it/markdown-it) from 14.1.1 to 14.2.0.
- [Changelog](https://github.com/markdown-it/markdown-it/blob/master/CHANGELOG.md)
- [Commits](https://github.com/markdown-it/markdown-it/compare/14.1.1...14.2.0)

---
updated-dependencies:
- dependency-name: markdown-it
  dependency-version: 14.2.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-16 19:01:51 +00:00
Tim van der Meij
8bc13d502b
Merge pull request #21459 from Snuffleupagus/PDFEditor-ternary-Dict-set
Use ternary expressions to shorten code in `src/core/editor/pdf_editor.js`
2026-06-16 20:50:05 +02:00
Tim van der Meij
36eae2c978
Merge pull request #21461 from mozilla/dependabot/github_actions/github/codeql-action-4.36.2
Bump github/codeql-action from 4.36.1 to 4.36.2
2026-06-16 20:48:22 +02:00
calixteman
bc99fc0678
Don't clamp BlueScale up when a font genuinely has small zones
The lower BlueScale clamp from #21343 guarded foundry fonts via
`blueScale < DEFAULT_BLUE_SCALE`, but that lets a near-default value
(e.g. 0.037) with small zones get raised to `0.5 / maxZoneHeight`. On
macOS' Core Text rasterizer this collapses the overshooting glyphs, so
most text disappears (not reproducible on Linux/Windows).
2026-06-16 19:34:48 +02:00
calixteman
fdeed2af5e
Merge pull request #21455 from calixteman/bug1873345
Draw non-isolated blend-mode groups against their backdrop (bug 1873345)
2026-06-16 15:26:00 +02:00
Calixte Denizet
082ad21387 Draw non-isolated blend-mode groups against their backdrop (bug 1873345)
A non-isolated transparency group must blend with its backdrop, but a group
containing a blend mode was forced onto a transparent intermediate canvas;
e.g. a /Multiply highlight then painted opaquely over the text behind it,
 making that text invisible.
2026-06-16 15:09:39 +02:00
dependabot[bot]
6cdd3c19fd
Bump github/codeql-action from 4.36.1 to 4.36.2
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.36.1 to 4.36.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](87557b9c84...8aad20d150)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.36.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-16 12:14:06 +00:00
Jonas Jenwald
6c0ad865c6 Use ternary expressions to shorten code in src/core/editor/pdf_editor.js
This makes setting a few Dictionary entries a little bit shorter, which shouldn't hurt.
(Part of this code isn't fully covered by tests, so it improves overall code coverage as well.)
2026-06-16 11:50:53 +02:00
Tim van der Meij
7f7b38b424
Merge pull request #21457 from Snuffleupagus/GetAnnotationsByType-rm-page-check
Remove unneeded check in the "GetAnnotationsByType" worker-thread handler
2026-06-15 21:41:10 +02:00
Tim van der Meij
7d3ec9da1e
Merge pull request #21456 from Snuffleupagus/rm-classNamesForOutlining
Remove the unused `HighlightOutline.prototype.classNamesForOutlining` getter
2026-06-15 20:46:32 +02:00
calixteman
67e6ff0090
Merge pull request #21428 from calixteman/checkubtton_opt
Resolve checkbox/radio export values from the 'Opt' entry
2026-06-15 19:43:28 +02:00
Calixte Denizet
2550b91be9 Resolve checkbox/radio export values from the 'Opt' entry
For checkbox and radio button fields, the export value can differ from the
appearance-state name: the field's inheritable `Opt` array holds the real
export values (used for non-Latin text, or values shared between buttons).
We previously exposed the appearance-state name as the export value.
2026-06-15 18:23:26 +02:00
Jonas Jenwald
d9e4cc5f65 Remove unneeded check in the "GetAnnotationsByType" worker-thread handler
Given that the Promise returned by the `PDFDocument.prototype.getPage` method *always* resolves with a `Page` instance, checking that the page is defined isn't necessary; note 3a09329113/src/core/document.js (L1702-L1723)

Furthermore the `Page.prototype.collectAnnotationsByType` method is asynchronous, and thus it always returns a Promise, hence it's "pointless" to fallback to return an empty Array.
2026-06-15 13:12:47 +02:00
Jonas Jenwald
f781ac33da Remove the unused HighlightOutline.prototype.classNamesForOutlining getter
This was added in PR 18972 and it became unused in PR 19085, however it was accidentally left behind.
2026-06-15 12:02:46 +02:00
Tim van der Meij
3a09329113
Merge pull request #21454 from timvandermeij/eslint-plugin-unicorn
Upgrade `eslint-plugin-unicorn` to version 66.0.0
2026-06-14 21:51:42 +02:00
Tim van der Meij
0ea67ed96f
Upgrade eslint-plugin-unicorn to version 66.0.0
This is a major version bump, but the changelog at
https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v66.0.0
doesn't indicate any breaking changes that should impact us.

However, improved rules do require a small number of changes here:

- The `prefer-array-some` rule no longer reports a false positive after
  https://github.com/sindresorhus/eslint-plugin-unicorn/issues/3198 got
  fixed, so the ignore line that was added in commit 68a5ec1 is removed.

- The `prefer-ternary` rule triggers on more cases now, in particular
  `let` declarations with `if` reassignments, so a number of changes are
  made to make it pass again.

- The `prefer-at` rule triggers on more cases now, in particular
  `substring` calls that just extract a single character, so one change
  is made to make it pass again.
2026-06-14 20:20:34 +02:00
calixteman
92bd2dbb38
Merge pull request #21453 from timvandermeij/puppeteer-skip-download
Don't download Puppeteer browsers on `npm install`
2026-06-14 19:25:32 +02:00
Tim van der Meij
26b4206d87
Configure Puppeteeer to not download Chrome/Firefox by default
We currently download Chrome/Firefox immediately on `npm install`
invocations because Puppeteer's postinstall script does that by default.
However, this is wasteful if the user/workflow doesn't actually need to
run Puppeteer or its browsers, for example in GitHub Actions workflows
that do linting, static analysis or other tasks like updating locales or
publishing artifacts.

This commit therefore makes sure no browser binaries get pulled in by
default anymore, and defers doing that until it's actually necessary,
which is when we want to start the browsers in the `startBrowsers`
function of `test.mjs`.

Locally this brings the `npm install` runtime down from 8.998 to 1.800
seconds, and as a bonus it results in better log output too because it
now shows which browser versions were used in the run (whereas
previously with `npm install` this information was not sent to stdout).
2026-06-14 17:15:47 +02:00
Tim van der Meij
6bfefa53da
Configure Puppeteer to use the stable version of Chrome
We currently use the pinned version of Chrome as hardcoded in the
Puppeteer release, which is based on the version of Chrome that was
deemed stable at the time of the Puppeteer release.

However, this is not ideal because it means that Chrome updates are
strongly tied to Puppeteer releases, so if Puppeteer releases are slow
we could be missing out on e.g. (security) patches being applied on the
stable channel. It's also not consistent with Firefox where we don't
use a hardcoded pinned version either.

This commit therefore configures Puppeteer to use (resolve) the most
recent stable version of Chrome at the time of the installation so that
determining the browser version to use is fully decoupled from the
Puppeteer release we're running.

The effect of this change can be seen in the output of running
`npx puppeteer browsers list`:

Before:

`chrome@149.0.7827.22 (linux) <path>`

After (note the slightly newer version):

`chrome@149.0.7827.115 (linux)` <path>`
2026-06-14 17:12:43 +02:00
Tim van der Meij
66c22b1fc5
Configure Puppeteer to not download Chrome headless shell
Nowadays Chrome has a built-in (new) headless mode in the regular
binary, but before that time there was an old headless mode that was
essentially a separate binary [1]. We don't use the latter, but it turns
out that Puppeteer downloads it automatically if it's not explicitly
skipped, which is wasteful because it costs extra time and resources for
each `npm install` invocation.

This commit therefore skips downloading Chrome headless shell explictly,
which results in the local runtime of `npm install` going from 10.125
seconds to 8.998 seconds (which can't hurt in e.g. GitHub Actions).

[1] https://developer.chrome.com/blog/chrome-headless-shell.
2026-06-14 16:59:13 +02:00
Tim van der Meij
8560125056
Merge pull request #21448 from timvandermeij/comment-intermittent
Fix intermittent failure in the `must check that the comment sidebar is resizable` comment integration test
2026-06-14 16:35:20 +02:00
Tim van der Meij
ed1b2f91be
Merge pull request #21440 from Snuffleupagus/putBinaryImageData-convertRGBToRGBA
Use the `convertRGBToRGBA` helper with RGB images in `putBinaryImageData`
2026-06-14 14:20:11 +02:00
Tim van der Meij
bfcafbc004
Merge pull request #21444 from Snuffleupagus/merge-test-password
Add an integration-test for merging a password-protected PDF
2026-06-14 14:16:35 +02:00
Jonas Jenwald
2dc73ad2a7 Collect coverage data from all workers when closing integration-tests
The "Merge PDF" integration-tests will (indirectly) invoke `PDFViewerApplication.open` as part of loading the new PDF document, which will end up creating a new `PDFWorker` instance.
Currently worker coverage is only collected at the end of each integration-test, which means that in these cases we miss the coverage data from any "previous" workers.
2026-06-14 13:27:06 +02:00
Jonas Jenwald
feec28583d Add an integration-test for merging a password-protected PDF
Looking at the coverage data the password-handling part of the merge functionality wasn't being tested; see e75a7cfd62/blob/src/core/worker.js (L652)
2026-06-14 13:17:33 +02:00
Jonas Jenwald
1373aa4a48
Merge pull request #21452 from Snuffleupagus/merge-test-corrupt
Add an integration-test for merging a corrupt PDF
2026-06-14 13:13:47 +02:00
Jonas Jenwald
e1c930adfe Add an integration-test for merging a corrupt PDF
Currently when opening a PDF document the following code is used, where `checkFirstPage`/`checkLastPage` helps detect XRef corruption; note 86a18bd5fe/src/core/worker.js (L167-L176)

However when merging a PDF into an existing document the parsing is only "partial"; note 86a18bd5fe/src/core/worker.js (L632-L634)

It seems a little strange to not support corrupt PDFs in a consistent manner in the code-base, hence this patch adds a new `BasePdfManager` helper that handles all the relevant parsing/checking and re-uses that when merging PDFs.
2026-06-14 09:49:23 +02:00
Tim van der Meij
d305b542df
Fix intermittent failure in the must check that the comment sidebar is resizable comment integration test
We use the generic `page.mouse.move(x, y, { steps }` API, but that purely
performs the mouse move steps without having knowledge about if/how the
application handles any events caused by it, so it doesn't wait for the
sidebar to render before moving on. This causes intermittent failures if
the sidebar didn't get enough time to render before the next mouse move
is initiated (which can happen in slower environments).

This commit fixes the issue by doing the mouse move steps ourselves and
by waiting for a browser trip between each of them to make sure that the
sidebar got a chance to render.

Fixes #21447.
Relates to #21044 / #21045 / 24e5377.
2026-06-13 21:32:00 +02:00
Tim van der Meij
86a18bd5fe
Merge pull request #21446 from timvandermeij/updates
Update dependencies to the most recent versions
2026-06-13 21:15:55 +02:00
Tim van der Meij
68a5ec1403
Upgrade eslint-plugin-unicorn to version 65.0.1
This is a major version bump, but the changelog at
https://github.com/sindresorhus/eslint-plugin-unicorn/releases/tag/v65.0.0
doesn't indicate any breaking changes that should impact us.

However, there is one false positive, possibly introduced by patch
https://github.com/sindresorhus/eslint-plugin-unicorn/pull/3028:

```
src/core/xfa/factory.js
  104:54  error  Prefer `.some(…)` over `.find(…)`  unicorn/prefer-array-some
```

This is incorrect because on this line we're not dealing with an array
but with a `FontFinder` instance instead (and that doesn't have a
`.some()` method), so we ignore the rule for this line.
2026-06-13 19:33:50 +02:00
Tim van der Meij
827ddf6e09
Update dependencies to the most recent versions 2026-06-13 19:12:35 +02:00
Tim van der Meij
01948aff23
Merge pull request #21443 from Snuffleupagus/finishWorkerTask-finally
Reduce duplication when invoking `finishWorkerTask`
2026-06-13 19:01:04 +02:00
Jonas Jenwald
c88f0bba04 Reduce duplication when invoking finishWorkerTask
By utilizing `Promise.prototype.finally()` more it's possible to avoid a bit of duplication when invoking `finishWorkerTask`.
2026-06-13 16:52:47 +02:00
Jonas Jenwald
55c8516944 Use the convertRGBToRGBA helper with RGB images in putBinaryImageData
This removes a little bit of code duplication, which only exist since the `src/display/canvas.js` code pre-dates the helper function by many years.

Note: Given that `OffscreenCanvas` is enabled by default there's currently not a lot of test coverage for this code-path, hence the added browser-test.
2026-06-13 13:14:50 +02:00
Tim van der Meij
e75a7cfd62
Merge pull request #21441 from Snuffleupagus/JpegImage-isSourcePDF-conditional
Re-factor the `isSourcePDF` handling in the `JpegImage` class
2026-06-13 12:48:00 +02:00
Tim van der Meij
5f8f6b1e40
Merge pull request #21439 from Snuffleupagus/more-getOrInsertComputed
Use `Map.prototype.getOrInsertComputed()` more in the code-base
2026-06-13 12:44:51 +02:00
Jonas Jenwald
ec1e94423b Re-factor the isSourcePDF handling in the JpegImage class
This functionality was added specifically for the standalone image-decoders, and by utilizing the pre-processor we can reduce the amount of "unnecessary" code in the regular builds.

Also, shorten a few loop variables a little bit since less code is always good.
2026-06-13 10:59:02 +02:00
Jonas Jenwald
5873e1cbc0
Merge pull request #21431 from Snuffleupagus/more-isDict
Use the `isDict` helper function in a few more places
2026-06-12 23:32:22 +02:00
Jonas Jenwald
ffa7ac7a91 Use Map.prototype.getOrInsertComputed() more in the code-base 2026-06-12 23:21:16 +02:00
Tim van der Meij
ca34359e1f
Merge pull request #21426 from Snuffleupagus/rm-convertToViewportRectangle
[api-minor] Remove the unused `convertToViewportRectangle` method in the `PageViewport` class
2026-06-12 22:06:19 +02:00
calixteman
35d275d3b1
Merge pull request #18907 from calixteman/bug1802506
Use the checkboxes and radio button appearances as defined in the pdf to render them in the annotation layer (bug 1802506)
2026-06-12 22:04:29 +02:00
Tim van der Meij
4781194b37
Merge pull request #21437 from Snuffleupagus/issue-21436
Handle corrupt PDFs that lack /Kids array and just inline the /Page dictionary (issue 21436)
2026-06-12 20:49:27 +02:00
Calixte Denizet
069b757998 Use the checkboxes and radio button appearances as defined in the pdf to render them in the annotation layer (bug 1802506)
The idea is to generate two operator lists for the Yes/Off states and render them on a separate canvas.
These canvases are then attached the annotation and we modify their display depending on the input state.

It fixes #18021.
2026-06-12 20:10:56 +02:00
Jonas Jenwald
131d6b7d38 Handle corrupt PDFs that lack /Kids array and just inline the /Page dictionary (issue 21436)
This basically extends PR 9549 to the fallback `getAllPageDicts` method, which didn't exist at the time, in order to support more cases of corrupt PDF documents.
2026-06-12 12:04:58 +02:00
calixteman
63db4bb777
Merge pull request #21433 from mozilla/update-locales
l10n: Update locale files
2026-06-12 08:45:22 +02:00
github-actions[bot]
53d0856ee9 l10n: Update locale files 2026-06-12 01:00:11 +00:00
Jonas Jenwald
3b628d59fb Use the isDict helper function in a few more places 2026-06-11 17:24:03 +02:00
Jonas Jenwald
2466a76ba4
Merge pull request #21429 from Snuffleupagus/getAttachmentContent-fix-unit-test
Fix the unit-tests for on-demand password handling of encrypted attachments (issue 21425)
2026-06-11 15:13:46 +02:00
Jonas Jenwald
587abf0ef4 Re-use the getPassword helper function more in the src/core/worker.js file
Currently the same code, for requesting the password from the main-thread, is now duplicated three times.
Let's avoid that by moving the new `getPassword` helper function, added in the previous commit, and re-use that everywhere instead.
2026-06-11 10:07:39 +02:00
Jonas Jenwald
f3f5acc418 Fix the unit-tests for on-demand password handling of encrypted attachments (issue 21425)
These unit-tests used a PDF that prompted for password on document load, which meant that the on-demand password handling wasn't actually being tested as intended.

Updating the unit-tests also caused the "re-prompts for encrypted attachments after incorrect passwords" test to fail, since the `INCORRECT_PASSWORD` password reason was being accidentally "swallowed" in the worker-thread.
2026-06-10 23:08:34 +02:00
Jonas Jenwald
ac64bcfa2b
Merge pull request #21427 from Snuffleupagus/putBinaryImageData-convertBlackAndWhiteToRGBA
Use the `convertBlackAndWhiteToRGBA` helper with grayscale images in `putBinaryImageData`
2026-06-10 21:23:03 +02:00
Jonas Jenwald
d1926fb179 Use the convertBlackAndWhiteToRGBA helper with grayscale images in putBinaryImageData
This removes a little bit of code duplication, which only exist since the `src/display/canvas.js` code pre-dates the helper function by many years.

*Note:* Given that `OffscreenCanvas` is enabled by default there's currently not a lot of test coverage for this code-path, hence the added browser-test.
2026-06-10 18:31:07 +02:00
Jonas Jenwald
a543d0a2e0 [api-minor] Remove the unused convertToViewportRectangle method in the PageViewport class
This method has been completely unused for many years, possibly as far back as PR 8030, hence we can avoid shipping a little bit of dead code.

*Note:* If there's any third-party code depending on it, updating it ought to be as simple as changing
```javascript
const r = viewport.convertToViewportRectangle(rect);
```
into
```javascript
const r = [
  ...viewport.convertToViewportPoint(rect[0], rect[1]),
  ...viewport.convertToViewportPoint(rect[2], rect[3])
];
```
2026-06-10 14:19:20 +02:00
calixteman
ce08a803c4
Merge pull request #21416 from calixteman/drop-css-unsafe-inline
Drop 'unsafe-inline' from the CSP style-src directives
2026-06-09 23:16:38 +02:00
calixteman
a13f2aa793
Merge pull request #21413 from calixteman/improve_comb
Improve rendering of comb text fields
2026-06-09 23:10:49 +02:00
Calixte Denizet
fe5eb0f779
Improve rendering of comb text fields
Center each glyph within its comb cell instead of left-aligning it,
both in the HTML annotation layer and in the printed/saved appearance,
to match Acrobat. Cell width is now the single source of truth via the
--comb-width CSS variable, and field text-alignment (center/right) is
applied as a whole-cell --comb-offset that stays in sync on input,
blur, resetform and updatefromsandbox. The field no longer grows on
focus; trailing letter-spacing is clipped and cell dividers are drawn
on focus.
2026-06-09 22:15:40 +02:00
Calixte Denizet
5ca6026d80
Drop 'unsafe-inline' from the CSP style-src directives
The print service injected the per-PDF `@page { size }` rule as an inline
<style> element, which required 'unsafe-inline' on style-src-elem.

Inject it through a constructable CSSStyleSheet attached to
document.adoptedStyleSheets instead. Constructable stylesheets aren't
subject to style-src's inline restrictions in browsers.
2026-06-09 22:08:08 +02:00
calixteman
cb53dbecb9
Merge pull request #21419 from calixteman/chrome_ext_csp
[CRX] List all viewer-accessible schemes in the connect-src CSP
2026-06-09 21:32:08 +02:00
Tim van der Meij
c541d24ac3
Merge pull request #21407 from calixteman/fix_hidden_updated_field
Fix form fields with their own canvas updated on non-rendered pages
2026-06-09 20:03:20 +02:00
Tim van der Meij
29ad297626
Merge pull request #21409 from Snuffleupagus/PDFViewer-#setPrintingAllowed
Add a `PDFViewer` helper method for setting `#printingAllowed` and dispatching the event
2026-06-09 19:43:26 +02:00
Tim van der Meij
8a80f1b8b7
Merge pull request #21418 from Snuffleupagus/getAttachments-Map
[api-minor] Convert `getAttachments` to return data in a `Map`
2026-06-09 19:42:23 +02:00
Tim van der Meij
7f5b42140d
Merge pull request #21414 from calixteman/issue21406
Handle TR2 with /Default entry
2026-06-09 19:26:57 +02:00
Tim van der Meij
9e5cbcef50
Merge pull request #21421 from mozilla/dependabot/github_actions/github/codeql-action-4.36.1
Bump github/codeql-action from 4.36.0 to 4.36.1
2026-06-09 19:24:13 +02:00
Tim van der Meij
cf8677154b
Merge pull request #21420 from mozilla/dependabot/github_actions/actions/checkout-6.0.3
Bump actions/checkout from 6.0.2 to 6.0.3
2026-06-09 19:23:29 +02:00
calixteman
3602db7456
[CRX] List all viewer-accessible schemes in the connect-src CSP 2026-06-09 16:55:19 +02:00
dependabot[bot]
5140371ebe
Bump github/codeql-action from 4.36.0 to 4.36.1
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.36.0 to 4.36.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](7211b7c807...87557b9c84)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.36.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 12:14:30 +00:00
dependabot[bot]
380c4c8139
Bump actions/checkout from 6.0.2 to 6.0.3
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.2 to 6.0.3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](de0fac2e45...df4cb1c069)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 12:13:07 +00:00
Jonas Jenwald
ea139e7df1 [api-minor] Convert getAttachments to return data in a Map
Compared to regular `Object`s there's a number of advantages to using `Map`s:
 - They support "proper" iteration.
 - They have a simple way to check for the existence of data.
 - They have a simple/efficient way to check the number of elements.

If this functionality was added today, I cannot imagine that we'd choose an `Object` for this sort of data.
Furthermore, in PR 21351 the data returned by `getAttachments` changed slightly and third-party users will need to update their code anyway (hence why `[api-minor]` should be fine here).
2026-06-09 10:17:23 +02:00
Calixte Denizet
473b53fe3c Handle TR2 with /Default entry
It fixes #21406.
2026-06-08 19:09:45 +02:00
calixteman
ea4fe68c01
Merge pull request #21405 from Snuffleupagus/scripting-rm-getOrInsertComputed-polyfill
Remove the `Map.prototype.getOrInsertComputed` polyfill from the scripting implementation (PR 21399 follow-up)
2026-06-08 17:25:47 +02:00
Calixte Denizet
ecd43bc8e1 Fix form fields with their own canvas updated on non-rendered pages
When a read-only field (which has its own canvas) is updated by the
sandbox while its page isn't rendered, showElementAndHideCanvas
isn't called, so once the page is finally rendered the field still
shows its outdated canvas instead of the new value.

Replace the imperative canvas/element toggling with a `sandboxModified`
class, set from the annotation storage both at render time and on
sandbox updates, and let the CSS show the element and hide the canvas.
2026-06-08 17:22:11 +02:00
calixteman
879437247b
Merge pull request #21408 from wooorm/wooorm/selection-color-transparent
Fix transparent color of `::selection` in Firefox
2026-06-08 16:57:34 +02:00
Jonas Jenwald
f93faae01c Add a PDFViewer helper method for setting #printingAllowed and dispatching the event
This reduces a little bit of code duplication, which shouldn't hurt.
2026-06-08 15:30:05 +02:00
Titus Wormer
7b54ec0a8d
Fix transparent color of ::selection in Firefox
This forces `color: transparent` on selections.
In latest Firefox Nightly, this is no longer inherited on
`::selection` from the normal element.

References: <753827d749>
2026-06-08 15:14:21 +02:00
calixteman
fadd201c09
Merge pull request #21404 from matasaru/master
fixed typo in README.md
2026-06-08 11:56:28 +02:00
Jonas Jenwald
5f83408099 Remove the Map.prototype.getOrInsertComputed polyfill from the scripting implementation (PR 21399 follow-up)
All unit- and integration-tests pass with this patch, and according to the QuickJS changelog this is supported now; note 3d5e064e9d/Changelog (L10) and https://github.com/tc39/proposal-upsert.
2026-06-08 11:48:42 +02:00
calixteman
52a44a68be
Merge pull request #21399 from calixteman/update_quickjs_3d5e064
Update quickjs to rev 3d5e064e9dd67c70f7962836505a7fa067bf0a4e
2026-06-08 10:38:44 +02:00
calixteman
7a7e4fd382 Update quickjs to rev 3d5e064e9dd67c70f7962836505a7fa067bf0a4e 2026-06-08 09:26:36 +02:00
radu
82098f175b fixed typo in README.md 2026-06-07 18:52:07 -04:00
Tim van der Meij
ff88446d01
Merge pull request #21402 from timvandermeij/updates
Update dependencies to the most recent versions
2026-06-07 17:08:06 +02:00
Jonas Jenwald
4a01dd669a
Merge pull request #21400 from Snuffleupagus/workflows-test-external-folder
Run various test-suite when the `external/` folder is modified
2026-06-07 16:52:39 +02:00
Tim van der Meij
4112c2953b
Upgrade @eslint/json to version 2.0.0
This is a major version bump, but the changelog at
https://github.com/eslint/json/releases/json-v2.0.0
doesn't indicate any breaking changes that should impact us.
2026-06-07 16:14:37 +02:00
Tim van der Meij
984fcd4bae
Update dependencies to the most recent versions 2026-06-07 16:13:36 +02:00
Jonas Jenwald
9c0b56ac07 Run various test-suite when the external/ folder is modified
Given that the `external/` folder contains various imported code/resources, all of which could affect functionality and/or rendering, it seems safest to simply run browser/font/integration/unit tests whenever any part of that folder is touched.
2026-06-07 16:03:40 +02:00
Tim van der Meij
f86b5abb05
Merge pull request #21398 from timvandermeij/codecov-ci-fix
Upgrade `codecov/codecov-action` to version 7.0.0
2026-06-07 15:39:39 +02:00
Tim van der Meij
b8ad7c8d0f
Upgrade codecov/codecov-action to version 7.0.0
Codecov had to migrate to a new Keybase account after losing access to
their old Keybase account, and because of that the old account got
bricked to prevent misuse [1] which resulted in GPG verification
failures in our builds [2]. This new version of the action fixes the
issue by using the new account.

Fixes #21394.

[1] https://github.com/codecov/codecov-action/issues/1956
[2] https://github.com/codecov/codecov-action/issues/1955
2026-06-07 14:52:24 +02:00
Tim van der Meij
d9eea18876
Merge pull request #21396 from Snuffleupagus/injectLinkAnnotations-move-call
Prevent intermittent issues when invoking the `PDFPageView.prototype.#injectLinkAnnotations` method
2026-06-07 14:42:14 +02:00
Tim van der Meij
bfc33678da
Merge pull request #21395 from Snuffleupagus/DrawLayerBuilder-cancel-optional-chaining
Shorten the `DrawLayerBuilder.prototype.cancel` method a tiny bit
2026-06-07 14:35:40 +02:00
Jonas Jenwald
43dd2781a0 Prevent intermittent issues when invoking the PDFPageView.prototype.#injectLinkAnnotations method
Looking at the coverage data there are cases where we attempt to insert inferred link-annotations *before* the annotationLayer has rendered, see [here](2348365874/blob/web/annotation_layer_builder.js (L246)), which shouldn't happen and why that's treated as an Error.

This is most likely caused by the asynchronicity of all the relevant code, since the `Autolinker` functionality can only be invoked after both the annotationLayer *and* the textLayer have finished rendering.
Given that those operations are asynchronous, by the time that they complete it's possible that the annotationLayer (and also the textLayer) has been replaced by a new instance. In that case we might thus attempt to inject inferred link-annotations before the "new" annotationLayer has rendered.

To avoid this intermittent issue, we now ensure that the annotationLayer and textLayer haven't changed between those layers rendering and the `Autolinker` functionality being invoked. (If they did change, then a future `render` call will trigger the inferred link-annotations handling).
2026-06-07 11:28:57 +02:00
Jonas Jenwald
0eca809589 Shorten the DrawLayerBuilder.prototype.cancel method a tiny bit
By replacing the early return with optional chaining, a pattern that we already use in lots of places, the code becomes a tiny bit shorter and more importantly the code coverage for this file becomes 100 percent.
2026-06-06 23:41:31 +02:00
Tim van der Meij
f12c463452
Merge pull request #21393 from Snuffleupagus/PDFCursorTools-tests
Add basic integration-tests for the `PDFCursorTools` functionality
2026-06-06 19:51:52 +02:00
Tim van der Meij
81f15c3437
Merge pull request #21390 from Snuffleupagus/getDocument-binary-string-unit-test
Add a unit-test for passing a binary string to `getDocument`
2026-06-06 19:46:45 +02:00
Tim van der Meij
f4d6b4ef85
Merge pull request #21391 from Snuffleupagus/getDocument-Node-fs-unit-test
Add a unit-test for passing a filesystem URL-string (in Node.js) to `getDocument`
2026-06-06 19:45:26 +02:00
Jonas Jenwald
0b3b101dbc Remove the unused GrabToPan.prototype.toggle method
Given that the cursor tools are managed via the `PDFCursorTools` class, of which the `GrabToPan` instance is essentially a (semi) private implementation detail, the `GrabToPan.prototype.toggle` method is completely unused and can thus be removed.
2026-06-06 17:27:19 +02:00
Jonas Jenwald
a5333f2a92 Add a unit-test for passing a binary string to getDocument
This format is obviously not very efficient however it's been supported since "forever" and there's even examples using, hence it seems like a good idea to actually test this.
2026-06-06 14:37:25 +02:00
Jonas Jenwald
ae30748956 Add basic integration-tests for the PDFCursorTools functionality 2026-06-06 14:32:15 +02:00
calixteman
2348365874
Merge pull request #21392 from Snuffleupagus/Autolinker-invalid-email-domain-test
Add one more unit-test case for invalid email domains in the `Autolinker` class
2026-06-06 13:17:11 +02:00
Jonas Jenwald
08b704d4b1 Add one more unit-test case for invalid email domains in the Autolinker class
This improves coverage for a branch of the `Autolinker` class that wasn't previously tested.
2026-06-06 11:57:22 +02:00
Jonas Jenwald
a7d32f4518 Add a unit-test for passing a filesystem URL-string (in Node.js) to getDocument
This improves coverage for a part of the API that previously wasn't tested.
2026-06-05 23:17:11 +02:00
Tim van der Meij
9c437e6ab4
Merge pull request #21388 from calixteman/strip_jbig2_header
Strip the JBIG2 file header from JBIG2Decode streams
2026-06-05 20:06:02 +02:00
Tim van der Meij
4ed78beb38
Merge pull request #21387 from Snuffleupagus/ChunkedStream-abort-reject
Reject the stream-capability when aborting the `ChunkedStreamManager`
2026-06-05 20:02:02 +02:00
Tim van der Meij
e34e11cf78
Merge pull request #21386 from KonstantinRight/print-params-flag-fix
fix typo in bit flag value for suppressCropClip
2026-06-05 19:58:58 +02:00
Tim van der Meij
c8fb1be7b6
Merge pull request #21389 from calixteman/readme_ccov
Update the README in order to add some info about code coverage
2026-06-05 19:57:18 +02:00
Calixte Denizet
9ab6b743ea Update the README in order to add some info about code coverage 2026-06-05 17:45:20 +02:00
calixteman
173e083c71
Merge pull request #21350 from calixteman/kb_shortcuts_l10n
Match editor keyboard shortcuts by event.code as a fallback
2026-06-05 17:19:17 +02:00
Calixte Denizet
88c52a1523 Strip the JBIG2 file header from JBIG2Decode streams
It's rendering correctly in Acrobat and PdfBox.
2026-06-05 16:31:44 +02:00
Jonas Jenwald
959ce38f5b Reject the stream-capability when aborting the ChunkedStreamManager
Given that any incoming data is already being ignored after loading has been aborted, it seems reasonable to reject the stream-capability to avoid it remaining in a pending state indefinitely.

*Note:* This is something that I noticed while looking at the coverage data, since the `ChunkedStreamManager.prototype.onError` method is not used and from a brief look at the history of the code it never appears to have been used either.
2026-06-05 12:25:53 +02:00
Konstantin
a66782615e fix typo in bit flag value for suppressCropClip 2026-06-05 11:30:20 +03:00
calixteman
091f459d2e
Merge pull request #21358 from sfoster/bug-203525-viewer-favicon
Bug 2035251 - Use toolkit's pdf icon as favicon
2026-06-04 21:35:28 +02:00
Tim van der Meij
23ea0810d9
Merge pull request #21379 from calixteman/dedup_stream_merging
Deduplicate shared font/image streams when merging PDFs
2026-06-04 20:58:22 +02:00
Sam Foster
b9e3a6b5d0 Bug 2035251 - Use toolkit's pdf icon as favicon 2026-06-04 11:58:12 -07:00
Tim van der Meij
7f15bd6591
Merge pull request #21383 from calixteman/ko_inner_bd
Add knockout_inner_backdrop ref test
2026-06-04 20:41:50 +02:00
Tim van der Meij
dc3696f23c
Merge pull request #21384 from Snuffleupagus/Stream-getBytes-shorten
Shorten the `getBytes` method in the `Stream`/`ChunkedStream` classes
2026-06-04 20:41:07 +02:00
Tim van der Meij
0cc139fdfc
Merge pull request #21385 from Snuffleupagus/AppOptions-unittest-EVENT_DISPATCH
Extend the `AppOptions` unit-tests to also cover the `EVENT_DISPATCH` option-kind
2026-06-04 20:36:17 +02:00
Tim van der Meij
d619ff3207
Merge pull request #21380 from Snuffleupagus/AnnotationLayerBuilder-rm-#externalHide
Remove the `#externalHide` field from the `AnnotationLayerBuilder` class
2026-06-04 20:35:14 +02:00
Tim van der Meij
f45a1b4df5
Merge pull request #21382 from mozilla/dependabot/github_actions/github/codeql-action-4.36.0
Bump github/codeql-action from 4.35.5 to 4.36.0
2026-06-04 20:32:41 +02:00
Jonas Jenwald
dc602ae543 Extend the AppOptions unit-tests to also cover the EVENT_DISPATCH option-kind 2026-06-04 17:51:41 +02:00
Jonas Jenwald
d36d3ab893 Shorten the getBytes method in the Stream/ChunkedStream classes
This is very old code and there's currently a bit of unneeded duplication in these methods, especially in the `ChunkedStream` class.
2026-06-04 13:10:24 +02:00
Calixte Denizet
e4a3e91444 Add knockout_inner_backdrop ref test
Non-isolated subgroup needing isolation (Multiply BM) nested in a KO
group, exercising the inner-backdrop blend path.
2026-06-04 09:13:43 +02:00
dependabot[bot]
936a472f05
Bump github/codeql-action from 4.35.5 to 4.36.0
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.35.5 to 4.36.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](9e0d7b8d25...7211b7c807)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.36.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-04 00:19:24 +00:00
calixteman
9071f451a5
Merge pull request #21359 from Snuffleupagus/coverage-browser-tests
Run browser tests to collect code coverage data
2026-06-03 19:01:52 +02:00
Jonas Jenwald
890edc9265 Run browser tests to collect code coverage data
Obviously it's not yet possible to just migrate `gulp browsertest` to GitHub Actions, however it's already possible to at least run the browser tests there which allows collection of more code coverage data.
This should thus give us more realistic coverage numbers, since currently there's many `src/` files that have very low code coverage.

By taking advantage of the fact that the GitHub Actions runners provide multiple cores, these tests are also fairly fast:
 - The ubuntu-latest/firefox job complete in ~9 minutes.
2026-06-03 18:15:18 +02:00
Jonas Jenwald
b168293c17
Merge pull request #21351 from wooorm/wooorm/auth-event-and-encrypted-attachments
[api-minor] Add support for `/AuthEvent`, on-demand decryption
2026-06-03 18:13:44 +02:00
Titus Wormer
4db9e45b8c
Add support for /AuthEvent, on-demand decryption
Normally entire PDFs are encrypted (or not).
But it is also possible to only encrypt attachments.
It is then also possible to *only* prompt for a password when the user opens
them.

In the existing flow, prompting for passwords happens because things are decrypted.
A specific error is thrown, caught, and the user is prompted.
To keep this flow working, this PR changes to decrypting attachments on demand,
instead of eagerly.
This sounds logical: to not read attachments on startup.

I’ve extensively tested this, not only with regular attachments, but also with outline items
and attachments in annotations.

This PR builds on GH-21234.
It’s an alternative to the naïve GH-20732.

Closes GH-20049.
2026-06-03 16:44:57 +02:00
Jonas Jenwald
5907d87774 Remove the #externalHide field from the AnnotationLayerBuilder class
Prior to PR 20321 the annotationLayer was hidden when there was no regular annotations on the page, which meant that if there were any inferred links (from the textLayer) the annotationLayer needed to be made visible but in such a way that it wouldn't override an explicit `hide`-call from the `PDFPageView` class.

With the changes in the aforementioned PR the annotationLayer is now always "visible", and this code can thus be simplified a little bit.
2026-06-03 13:56:43 +02:00
Calixte Denizet
836a08084e Match editor keyboard shortcuts by event.code as a fallback
So that Ctrl+A, Ctrl+Z, etc. still fire on non-US keyboard layouts where
the physical "A" key produces a non-Latin character (Cyrillic, Greek,
some AZERTY combinations, ...). KeyboardManager now tries event.key first
and falls back to a US-layout translation of event.code (KeyA => a,
Digit1 => 1, Numpad1 => 1) when no shortcut is bound on event.key.

Also refactors KeyboardManager to store modifiers as a bitmask instead
of a serialized string, and treats a shortcut array without any
"mac+"-prefixed entry as applying on all platforms, letting us drop the
redundant "mac+X" duplicates of bare "X" entries across the editor code.
2026-06-03 10:13:41 +02:00
Calixte Denizet
1a7821ab13 Deduplicate shared font/image streams when merging PDFs
Identical embedded fonts and images across the merged documents are now
written once and shared, instead of being copied per source file.
And avoid to compress already compressed stream with Brotli.
2026-06-02 22:08:21 +02:00
Jonas Jenwald
19046a6949
Merge pull request #21349 from Snuffleupagus/OptionalContentConfig-serializable
Implement proper serialization of `OptionalContentConfig`
2026-06-02 21:57:16 +02:00
Tim van der Meij
e9a946ec0b
Merge pull request #21378 from wooorm/wooorm/fix-selection-rendering-off
Fix broken `enableSelectionRendering: false`
2026-06-02 21:02:18 +02:00
Tim van der Meij
744c1e6d7a
Merge pull request #21372 from calixteman/issue7998
Render gray transparency groups in grayscale
2026-06-02 20:10:18 +02:00
Tim van der Meij
e9ee61f67c
Merge pull request #21347 from calixteman/issue21240
Restore editor layer state for unchanged pages after page mutations
2026-06-02 20:08:14 +02:00
Tim van der Meij
27b345a61e
Merge pull request #21361 from timvandermeij/is-canvas-monochrome
Fix intermittent failure in the "must check that a freetext is still here after having updated it and scroll the doc" freetext editor integration test
2026-06-02 20:01:24 +02:00
Titus Wormer
a8cf37f6bc
Fix broken enableSelectionRendering: false
Closes GH-21374.
Related-to GH-20981.
2026-06-02 12:57:04 +02:00
Jonas Jenwald
b43ef1c746
Merge pull request #21373 from Snuffleupagus/presentation-mode-test-links
Add an integration-test for clicking on internal links in presentation mode
2026-06-02 10:56:14 +02:00
Jonas Jenwald
065ea625dd
Merge pull request #21371 from Snuffleupagus/BaseStream-clone-fix
Improve the `BaseStream.prototype.clone` implementations
2026-06-02 10:54:36 +02:00
Jonas Jenwald
4e6b7be4d7 Add an integration-test for clicking on internal links in presentation mode 2026-06-01 14:25:55 +02:00
calixteman
69e8d6900f Render gray transparency groups in grayscale
It fixes #7998.
2026-05-31 21:16:29 +02:00
Jonas Jenwald
a6321e7201 Improve the BaseStream.prototype.clone implementations
- The `dict` field is optional, hence avoid an Error if trying to clone a non-existent dictionary.

 - Use the `length` getter in the `Stream` class, to avoid duplication.

 - Fix the `DecodeStream` implementation, since it has a couple of bugs:
    - The `clone` method currently uses `start`/`end` fields, despite these only existing on `Stream` instances.
    - Given the previous point, we ended up creating the cloned `Stream` instance using the *entire* underlying `buffer`. This is problematic since the length of a `DecodeStream` cannot be accurately estimated before decoding, and the `buffer`-length is simply a multiple of two.
       Unless the size of the decoded-data just happens to also be a multiple of two, this causes the cloned `Stream` instance to be "padded" with zeros at the end.
2026-05-31 20:24:39 +02:00
Tim van der Meij
5fbab91f71
Merge pull request #21368 from Snuffleupagus/more-internal-events
Mark a couple of viewer, and editor, EventBus listeners as "internal"
2026-05-31 14:35:18 +02:00
Jonas Jenwald
94fdea15f4
Merge pull request #21366 from Snuffleupagus/StringStream-dict
Update the `StringStream` constructor to accept an optional dictionary argument
2026-05-31 13:01:43 +02:00
Jonas Jenwald
04237100a5 Mark a couple of viewer, and editor, EventBus listeners as "internal"
There's currently a few EventBus listeners that aren't marked as "internal", however I'm assuming that they probably should be (e.g. to reduce the risk of intermittent failures in the integration-tests).
2026-05-31 12:12:41 +02:00
Jonas Jenwald
345089de1f
Merge pull request #21367 from Snuffleupagus/canvas-MathClamp
Use the `MathClamp` helper function in the `src/display/canvas.js` file
2026-05-31 11:55:48 +02:00
Tim van der Meij
add30f3ca0
Fix intermittent failure in the "must check that a freetext is still there after having updated it and scroll the doc" freetext editor integration test
The problem is that we screenshot the page itself rather than the
canvas, even though we specifically care about the latter according to
the comment, which means that we manually have to take care of hiding and
showing the annotation editor. This is problematic because even though
we signal that the annotation editor should be hidden, we don't wait
until that is actually done, which leads to a situation where we can
take the screenshot before the annotation editor is actually invisible
in the view.

This commit fixes the issue by screenshotting the canvas instead, which
avoids the need for manually hiding/showing the annotation editor. This
makes the test less fragile, and matches other tests better.
2026-05-31 11:36:44 +02:00
Jonas Jenwald
06439a95c3 Update the StringStream constructor to accept an optional dictionary argument
There's currently some amount of `StringStream` usage where the `dict`-parameter is manually assigned, and by updating the signature of the constructor this can be avoided.
2026-05-31 11:36:32 +02:00
Tim van der Meij
327822c21f
Merge pull request #21365 from calixteman/cmap_overflow
Skip the format 4 cmap sub-table when it doesn't fit its 16-bits fields
2026-05-31 11:32:58 +02:00
Tim van der Meij
af2380060a
Merge pull request #21364 from timvandermeij/webgpu-logs
Disable WebGPU for Firefox tests
2026-05-31 11:19:22 +02:00
Jonas Jenwald
0e1660700a Use the MathClamp helper function in the src/display/canvas.js file 2026-05-31 11:13:42 +02:00
calixteman
5d28cf5e88 Skip the format 4 cmap sub-table when it doesn't fit its 16-bits fields
It's a follow-up of bug 199861 (see https://bugzilla.mozilla.org/show_bug.cgi?id=1998618#c2).
2026-05-30 21:53:29 +02:00
Tim van der Meij
eef4ea620e
Disable WebGPU for Firefox tests
The GitHub Actions workflow for the integration tests on Windows logs
the following line for every test:

`JavaScript warning: http://127.0.0.1:62313/build/generic/build/pdf.mjs,
line 134934: WebGPU is disabled by blocklist.`

On Linux WebGPU is disabled by default because of missing support, but on
Windows it's enabled by default since bug 1972486, so we try to obtain a
GPU adapter which fails (and logs) if there is no actual GPU like on
GitHub Actions. Coverage data confirms that our own WebGPU code is
already uncovered because of the lack of a GPU, so having WebGPU enabled
or disabled doesn't change that, but if it causes log spam it seems
better to disable it, which this commit does.

Note that Chrome doesn't seem to have a matching flag, but Chrome already
doesn't log anything about this (which is the primary driver for this
change), so that's not a problem.
2026-05-30 19:30:24 +02:00
Tim van der Meij
145feeaa3f
Merge pull request #21360 from timvandermeij/bump
Bump the stable version in `pdfjs.config`
2026-05-30 15:19:21 +02:00
Tim van der Meij
6701ccd86b
Bump the stable version in pdfjs.config 2026-05-30 15:14:47 +02:00
Jonas Jenwald
ce45d5a443 Implement proper serialization of OptionalContentConfig
I happened to notice that the way the `OptionalContentConfig`-data handled in the PR that implements worker-rendering leaves a lot to be desired:
 - The way that the optional content state is handled is not correct, since that PR collects the "effective visibility" of the optional content groups rather than their *actual* internal state.

 - The necessary `OptionalContentConfig`-data is collected piecemeal in the API, which leads to quite frankly very messy code that's hard to read and will be even harder to maintain.

The solution to all of these issues seem really simple though, just add a couple of `OptionalContentConfig` methods that serialize/de-serialize the necessary data.
In the API calling `optionalContentConfig.serializable` will get *all* of the needed data for transferring to the worker-renderer, and once received there calling `OptionalContentConfig.fromSerializable(/* transferred data here */)` will create an `OptionalContentConfig` instance with the correct internal state.

As part of this patch, to avoid increasing bundle-size unnecessarily, a couple of existing methods are stubbed out when the `OptionalContentConfig` class ends up in a worker-file (since they're unused there).
This part assumes that the new worker-renderer is built correctly, note how the existing `pdf.worker.mjs` is handled in 03eda70d7e/gulpfile.mjs (L539-L545)

(*Note:* Submitting a PR was a lot faster than trying to provide review comments, since writing this commit message took longer than writing the patch.)
2026-05-27 11:06:57 +02:00
Calixte Denizet
8e6e35473f Restore editor layer state for unchanged pages after page mutations
It fixes #21240.
2026-05-26 22:27:35 +02:00
371 changed files with 26061 additions and 6711 deletions

31
.gitattributes vendored
View File

@ -1,23 +1,24 @@
# Force Unix line endings for most file formats (except binary files)
*.js text eol=lf
*.jsm text eol=lf
*.css text eol=lf
*.html text eol=lf
*.md text eol=lf
*.ftl text eol=lf
*.yml text eol=lf
*.json text eol=lf
*.config text eol=lf
*.inc text eol=lf
*.manifest text eol=lf
*.rdf text eol=lf
*.jade text eol=lf
*.coffee text eol=lf
*.css text eol=lf
*.example text eol=lf
*.ftl text eol=lf
*.html text eol=lf
*.js text eol=lf
*.json text eol=lf
*.link text eol=lf
*.md text eol=lf
*.mjs text eol=lf
*.mts text eol=lf
*.njk text eol=lf
*.py text eol=lf
*.svg text eol=lf
*.ts text eol=lf
*.txt text eol=lf
*.yml text eol=lf
# PDF files shall not modify CRLF line endings
*.pdf -crlf
# Linguist language overrides
*.js linguist-language=JavaScript
*.jsm linguist-language=JavaScript
*.inc linguist-language=XML

View File

@ -1 +1,7 @@
moz-fluent-linter==0.4.*
# The requirements below can be regenerated with the following one-liner:
# `python3 -m venv venv; source venv/bin/activate; pip install -q moz-fluent-linter; pip freeze; deactivate; rm -rf venv`
fluent.syntax==0.19.0
moz-fluent-linter==0.4.10
PyYAML==6.0.3
six==1.17.0
typing_extensions==4.16.0

View File

@ -1 +1,3 @@
fonttools==4.*
# The requirements below can be regenerated with the following one-liner:
# `python3 -m venv venv; source venv/bin/activate; pip install -q fonttools; pip freeze; deactivate; rm -rf venv`
fonttools==4.63.0

View File

@ -16,13 +16,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
@ -31,7 +31,7 @@ jobs:
run: npm ci
- name: Restore cached PDF files
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: test/pdfs/*.pdf
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
@ -46,14 +46,14 @@ jobs:
run: npx gulp unittestcli --coverage --coverage-output build/coverage/unitcli
- name: Save cached PDF files
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: test/pdfs/*.pdf
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
enableCrossOsArchive: true
- name: Upload results to Codecov
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true

View File

@ -18,19 +18,19 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
uses: github/codeql-action/init@e0647621c2984b5ed2f768cb892365bf2a616ad1 # v4.37.2
with:
languages: ${{ matrix.language }}
queries: security-and-quality
- name: Autobuild CodeQL
uses: github/codeql-action/autobuild@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
uses: github/codeql-action/autobuild@e0647621c2984b5ed2f768cb892365bf2a616ad1 # v4.37.2
- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
uses: github/codeql-action/analyze@e0647621c2984b5ed2f768cb892365bf2a616ad1 # v4.37.2

View File

@ -0,0 +1,101 @@
name: Coverage (Browser tests)
on:
push:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/images/**'
- 'test/pdfs/**'
- 'test/resources/**'
- 'test/*.css'
- 'test/driver.js'
- 'test/test.mjs'
- 'test/test_manifest.json'
- 'test/test_slave.html'
- 'web/**'
- '.github/workflows/coverage_browser_tests.yml'
branches:
- master
pull_request:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/images/**'
- 'test/pdfs/**'
- 'test/resources/**'
- 'test/*.css'
- 'test/driver.js'
- 'test/test.mjs'
- 'test/test_manifest.json'
- 'test/test_slave.html'
- 'web/**'
- '.github/workflows/coverage_browser_tests.yml'
branches:
- master
workflow_dispatch:
permissions:
contents: read
jobs:
test:
name: ${{ matrix.os }} / firefox
strategy:
fail-fast: false
matrix:
node-version: [lts/*]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
environment: code-coverage
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Restore cached PDF files
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: test/pdfs/*.pdf
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
restore-keys: |
cached-pdf-files-
enableCrossOsArchive: true
- name: Run browser tests with code coverage
run: npx gulp botbrowsertest --headless -j$(nproc) --coverage --coverage-output build/coverage/browser --noChrome
- name: Save cached PDF files
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: test/pdfs/*.pdf
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
enableCrossOsArchive: true
- name: Upload results to Codecov
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
files: ./build/coverage/browser/lcov.info
flags: browsertest
name: codecov-umbrella
disable_search: true
disable_telem: true
verbose: true

View File

@ -4,6 +4,7 @@ on:
paths:
- 'l10n/en-US/**.ftl'
- '.github/fluent_linter_config.yml'
- '.github/fluent_linter_requirements.txt'
- '.github/workflows/fluent_linter.yml'
branches:
- master
@ -11,6 +12,7 @@ on:
paths:
- 'l10n/en-US/**.ftl'
- '.github/fluent_linter_config.yml'
- '.github/fluent_linter_requirements.txt'
- '.github/workflows/fluent_linter.yml'
branches:
- master
@ -25,12 +27,12 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Use Python 3.14
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.14'
cache: 'pip'

View File

@ -3,18 +3,24 @@ on:
push:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/test.mjs'
- 'test/font/**'
- '.github/font_tests_requirements.txt'
- '.github/workflows/font_tests.yml'
branches:
- master
pull_request:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/test.mjs'
- 'test/font/**'
- '.github/font_tests_requirements.txt'
- '.github/workflows/font_tests.yml'
branches:
- master
@ -43,13 +49,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
@ -58,7 +64,7 @@ jobs:
run: npm ci
- name: Use Python 3.14
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.0.2
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.14'
cache: 'pip'
@ -71,7 +77,7 @@ jobs:
run: npx gulp fonttest --headless --coverage --coverage-output build/coverage/font ${{ matrix.skip }}
- name: Upload results to Codecov
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true

View File

@ -3,7 +3,8 @@ on:
push:
paths:
- 'gulpfile.mjs'
- 'external/builder/**'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/test.mjs'
- 'test/integration/**'
@ -14,7 +15,8 @@ on:
pull_request:
paths:
- 'gulpfile.mjs'
- 'external/builder/**'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/test.mjs'
- 'test/integration/**'
@ -47,13 +49,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
@ -62,7 +64,7 @@ jobs:
run: npm ci
- name: Restore cached PDF files
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: test/pdfs/*.pdf
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
@ -87,14 +89,14 @@ jobs:
run: xvfb-run -a --server-args="-screen 0, 1920x1080x24" npx gulp integrationtest --coverage --coverage-output build/coverage/integration ${{ matrix.skip }}
- name: Save cached PDF files
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: test/pdfs/*.pdf
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
enableCrossOsArchive: true
- name: Upload results to Codecov
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true

View File

@ -15,13 +15,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

View File

@ -16,7 +16,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1
persist-credentials: false

View File

@ -15,13 +15,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

View File

@ -0,0 +1,185 @@
name: Publish per-test coverage index
# Builds the per-test coverage index (which ref test exercises which source
# line/function) and publishes it to the gh-pages branch of mozilla/pdf.js.refs,
# where it's served at:
# https://mozilla.github.io/pdf.js.refs/per-test-index.json
# The index can then be queried with `npx gulp coverage_search`.
#
# This only runs when something is merged into master (push event); the build is
# heavy (a full browser test run), so it's deliberately kept off pull requests.
on:
push:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/images/**'
- 'test/pdfs/**'
- 'test/resources/**'
- 'test/*.css'
- 'test/driver.js'
- 'test/test.mjs'
- 'test/test_manifest.json'
- 'test/test_slave.html'
- 'web/**'
- '.github/workflows/publish_coverage_index.yml'
branches:
- master
workflow_dispatch:
concurrency:
group: publish-coverage-index-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
publish:
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
environment: sync_pdfs
strategy:
matrix:
node-version: [lts/*]
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Restore cached PDF files
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: test/pdfs/*.pdf
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
restore-keys: |
cached-pdf-files-
enableCrossOsArchive: true
- name: Build the per-test coverage index
run: npx gulp botbrowsertest --headless -j$(nproc) --coverage-per-test --coverage-output build/coverage/browser --noChrome
- name: Save cached PDF files
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: test/pdfs/*.pdf
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
enableCrossOsArchive: true
- name: Check current master
id: current-master
run: |
set -euo pipefail
git fetch --no-tags --depth=1 origin master:refs/remotes/origin/master
current_master="$(git rev-parse refs/remotes/origin/master)"
if [ "$GITHUB_SHA" = "$current_master" ]; then
echo "current=true" >> "$GITHUB_OUTPUT"
else
echo "::notice::Skipping publish because ${GITHUB_SHA} is no longer origin/master (${current_master})"
echo "current=false" >> "$GITHUB_OUTPUT"
fi
- name: Generate app token for pdf.js.refs
if: steps.current-master.outputs.current == 'true'
id: refs-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ secrets.CLIENT_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: mozilla
repositories: pdf.js.refs
# Least privilege: the token only needs to push to gh-pages.
permission-contents: write
- name: Publish per-test coverage index
if: steps.current-master.outputs.current == 'true'
env:
GH_TOKEN: ${{ steps.refs-token.outputs.token }}
INDEX_FILE: build/coverage/browser/per-test-index.json
run: |
set -euo pipefail
if [ ! -f "$INDEX_FILE" ]; then
# A successful per-test run always writes the index; test.mjs only
# skips it when no per-test coverage was collected at all, so a
# missing file here means a broken build, not "nothing to publish".
echo "::error::Per-test coverage index not found at $INDEX_FILE"
exit 1
fi
repo_url="https://github.com/mozilla/pdf.js.refs.git"
# Authenticate with a short-lived header rather than embedding the
# token in the remote URL, so it never persists in .git/config.
auth_header="Authorization: basic $(printf 'x-access-token:%s' "$GH_TOKEN" | base64 | tr -d '\n')"
git_refs() { git -c http.extraheader="$auth_header" "$@"; }
stage_index() {
cp "$GITHUB_WORKSPACE/$INDEX_FILE" per-test-index.json
git add per-test-index.json
}
commit_index() {
git \
-c user.name="github-actions[bot]" \
-c user.email="41898282+github-actions[bot]@users.noreply.github.com" \
commit -q -m "Update per-test coverage index for ${GITHUB_SHA}"
}
work="$(mktemp -d)"
# Does gh-pages already exist? Probe explicitly so a transient network
# error isn't mistaken for "first run" (the orphan path below discards
# whatever else the branch holds).
ls_status=0
git_refs ls-remote --exit-code --heads "$repo_url" gh-pages >/dev/null 2>&1 || ls_status=$?
case "$ls_status" in
0)
# Reuse gh-pages, keeping any other files it holds.
git_refs clone --depth=1 --branch gh-pages "$repo_url" "$work"
cd "$work"
;;
2)
# First run: start a fresh orphan branch without cloning history.
git init -q "$work"
cd "$work"
git remote add origin "$repo_url"
git checkout -q --orphan gh-pages
;;
*)
echo "::error::Could not query gh-pages on pdf.js.refs (git ls-remote exit ${ls_status})"
exit 1
;;
esac
stage_index
if git diff --cached --quiet; then
echo "No changes to publish"
exit 0
fi
commit_index
# Retry against a concurrent update to gh-pages: re-sync onto the new
# tip, re-apply our index (latest build wins), and push again.
for attempt in 1 2 3; do
if git_refs push origin gh-pages; then
exit 0
fi
if [ "$attempt" -eq 3 ]; then
echo "::error::Failed to push the per-test coverage index after ${attempt} attempts"
exit 1
fi
echo "gh-pages advanced during the run; re-syncing and retrying (attempt ${attempt})"
git_refs fetch --depth=1 origin gh-pages
git reset --hard FETCH_HEAD
stage_index
if git diff --cached --quiet; then
echo "No changes after re-sync"
exit 0
fi
commit_index
done

View File

@ -17,13 +17,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

View File

@ -6,6 +6,12 @@ on:
permissions:
contents: read
# Allow only one concurrent deployment, without cancelling in-progress runs, so
# that an in-flight Pages deployment is allowed to finish before the next starts.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
name: Build
@ -17,13 +23,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

View File

@ -15,13 +15,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

View File

@ -3,7 +3,8 @@ on:
push:
paths:
- 'gulpfile.mjs'
- 'external/builder/**'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/test.mjs'
- 'test/unit/**'
@ -14,7 +15,8 @@ on:
pull_request:
paths:
- 'gulpfile.mjs'
- 'external/builder/**'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/test.mjs'
- 'test/unit/**'
@ -47,13 +49,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
@ -62,7 +64,7 @@ jobs:
run: npm ci
- name: Restore cached PDF files
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: test/pdfs/*.pdf
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
@ -74,14 +76,14 @@ jobs:
run: npx gulp unittest --headless --coverage --coverage-output build/coverage/unit ${{ matrix.skip }}
- name: Save cached PDF files
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: test/pdfs/*.pdf
key: cached-pdf-files-${{ hashFiles('test/pdfs/*.pdf') }}
enableCrossOsArchive: true
- name: Upload results to Codecov
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true

View File

@ -23,13 +23,13 @@ jobs:
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
token: ${{ steps.app-token.outputs.token }}
persist-credentials: false
- name: Use Node.js LTS
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: lts/*
cache: 'npm'

View File

@ -1,9 +1,13 @@
{
"chrome": {
"skipDownload": false
"skipDownload": true,
"version": "stable"
},
"chrome-headless-shell": {
"skipDownload": true
},
"firefox": {
"skipDownload": false,
"skipDownload": true,
"version": "nightly"
}
}

View File

@ -46,7 +46,7 @@ directory `build/chromium`.
### PDF debugger
Browser the internal structure of a PDF document with https://mozilla.github.io/pdf.js/internal-viewer/web/debugger.html
Browse the internal structure of a PDF document with https://mozilla.github.io/pdf.js/internal-viewer/web/debugger.html
## Getting the Code
@ -91,6 +91,88 @@ This will generate `pdf.js` and `pdf.worker.js` in the `build/generic/build/` di
Both scripts are needed but only `pdf.js` needs to be included since `pdf.worker.js` will
be loaded by `pdf.js`. The PDF.js files are large and should be minified for production.
## Code coverage
We track how much of the code is exercised by the test suite on
[Codecov](https://codecov.io/gh/mozilla/pdf.js) (see the badge at the top of this
file).
### How it is collected
When coverage is enabled, the build instruments the bundled code with
[`babel-plugin-istanbul`](https://github.com/istanbuljs/babel-plugin-istanbul),
which adds counters that record every line, branch and function that runs:
+ For browser-based tests (unit, integration and reference tests) the
instrumented code runs in the browser, fills a global `window.__coverage__`
object, and the test runner collects it from each browser session, merges the
results, and writes the report.
+ For the Node-based unit tests (`unittestcli`) the raw data is written to
`build/tmp/unittestcli-coverage.json` and turned into a report afterwards.
### Collecting coverage locally
Add the `--coverage` flag to any of the test tasks, for example:
$ npx gulp unittest --coverage # browser unit tests
$ npx gulp unittestcli --coverage # Node unit tests
$ npx gulp integrationtest --coverage # Puppeteer integration tests
$ npx gulp botbrowsertest --coverage # reference tests
The following options control the output:
| Option | Description | Default |
| --- | --- | --- |
| `--coverage` | Enable coverage collection. | off |
| `--coverage-output <dir>` | Directory where the report is written. | `build/coverage` |
| `--coverage-formats <list>` | Comma-separated list of formats: `info`, `html`, `json`, `text`, `cobertura`, `clover`. | `info` |
| `--coverage-per-test` | Also build a per-test index (see below). | off |
By default the report is written to `build/coverage` in the `info` format, i.e.
an [LCOV](https://github.com/linux-test-project/lcov) `lcov.info` file (the same
format that is uploaded to Codecov). Use `--coverage-formats html` to get a
browsable HTML report instead, or pass several formats at once, e.g.
`--coverage-formats info,html`.
### Finding which tests cover a given line
`coverage_search` lists the ref tests that exercised a specific source line or
function. It uses the per-test index (`per-test-index.json`) that is rebuilt on
every push to `master` and published to the
[`pdf.js.refs`](https://github.com/mozilla/pdf.js.refs/tree/gh-pages)
repository. The index is downloaded on demand, cached locally, and only
re-downloaded when it has changed, so no local coverage build is required:
$ npx gulp coverage_search --code="canvas.js::205"
$ npx gulp coverage_search --code="canvas.js::drawImageAtIntegerCoords"
To run — or regenerate the reference images for — only the ref tests that touch
a given line or function, pass the same `--code` option to a browser test or
`makeref` task:
$ npx gulp browsertest --code="canvas.js::205"
$ npx gulp makeref --code="canvas.js::205"
Pass `--no-download` to reuse the locally cached index without contacting the
network. The index can also be built and queried locally (the CI job that
publishes it builds it the same way):
$ npx gulp botbrowsertest --coverage-per-test
$ npx gulp coverage_search --code="canvas.js::205" \
--index=build/coverage/per-test-index.json --no-download
### Continuous integration
On every push and pull request three GitHub Actions workflows collect coverage
and upload it to Codecov, each tagged with its own Codecov *flag* so the test
types can be told apart:
| Workflow | Task | Codecov flag |
| --- | --- | --- |
| `unit_tests.yml` | `unittest` | `unittest` |
| `integration_tests.yml` | `integrationtest` | `integrationtest` |
| `coverage_browser_tests.yml` | `botbrowsertest` | `browsertest` |
## Using PDF.js in a web application
To use PDF.js in a web application you can choose to use a pre-built version of the library

View File

@ -178,6 +178,11 @@ export default [
"unicorn/prefer-dom-node-remove": "error",
"unicorn/prefer-import-meta-properties": "error",
"unicorn/prefer-includes": "error",
"unicorn/logical-assignment-operators": [
"error",
"always",
{ enforceForIfStatements: true },
],
"unicorn/prefer-logical-operator-over-ternary": "error",
"unicorn/prefer-modern-dom-apis": "error",
"unicorn/prefer-modern-math-apis": "error",

View File

@ -48,7 +48,7 @@ const jpegData = jpegImage.getData({
//
const imageData = jpegCtx.createImageData(width, height);
const imageBytes = imageData.data;
for (let j = 0, k = 0, jj = width * height * 4; j < jj; ) {
for (let j = 0, k = 0, jj = width * height * 4; j < jj;) {
imageBytes[j++] = jpegData[k++];
imageBytes[j++] = jpegData[k++];
imageBytes[j++] = jpegData[k++];

View File

@ -192,7 +192,7 @@ function renderDefaultZoomValue(shortDescription) {
document.getElementById("settings-boxes").append(wrapper);
function renderPreference(value) {
value = value || "auto";
value ||= "auto";
select.value = value;
var customOption = select.querySelector("option.custom-zoom");
if (select.selectedIndex === -1 && value) {

View File

@ -150,7 +150,7 @@ limitations under the License.
*/
function didUpdateSinceLastCheck() {
var chromeVersion = /Chrome\/(\d+)\./.exec(navigator.userAgent);
chromeVersion = chromeVersion && chromeVersion[1];
chromeVersion &&= chromeVersion[1];
if (!chromeVersion || localStorage.telemetryLastVersion === chromeVersion) {
return false;
}

View File

@ -319,6 +319,16 @@ function babelPluginStripSrcPath() {
};
}
function babelPluginAddHeaderComment(babel, { header }) {
return {
visitor: {
Program(path) {
path.addComment("leading", header);
},
},
};
}
function preprocessPDFJSCode(ctx, content) {
return transformSync(content, {
configFile: false,
@ -327,6 +337,7 @@ function preprocessPDFJSCode(ctx, content) {
}
export {
babelPluginAddHeaderComment,
babelPluginPDFJSPreprocessor,
babelPluginStripSrcPath,
preprocessPDFJSCode,

View File

@ -73,10 +73,7 @@ function preprocess(inFilename, outFilename, defines) {
const out = [];
let i = 0;
function readLine() {
if (i < totalLines) {
return lines[i++];
}
return null;
return i < totalLines ? lines[i++] : null;
}
const writeLine =
typeof outFilename === "function"
@ -113,16 +110,9 @@ function preprocess(inFilename, outFilename, defines) {
const realPath = fs.realpathSync(inFilename);
const dir = path.dirname(realPath);
try {
let fullpath;
if (file.indexOf("$ROOT/") === 0) {
fullpath = path.join(
__dirname,
"../..",
file.substring("$ROOT/".length)
);
} else {
fullpath = path.join(dir, file);
}
const fullpath = file.startsWith("$ROOT/")
? path.join(__dirname, "../..", file.substring("$ROOT/".length))
: path.join(dir, file);
preprocess(fullpath, writeLine, defines);
} catch (e) {
if (e.code === "ENOENT") {
@ -134,10 +124,7 @@ function preprocess(inFilename, outFilename, defines) {
function expand(line) {
line = line.replaceAll(/__\w+__/g, function (variable) {
variable = variable.substring(2, variable.length - 2);
if (variable in defines) {
return defines[variable];
}
return "";
return variable in defines ? defines[variable] : "";
});
writeLine(line);
}

View File

@ -20,26 +20,46 @@ import path from "path";
const __dirname = import.meta.dirname;
const PROJECT_ROOT = path.join(__dirname, "../..");
const { values } = parseArgs({
// The per-test coverage index (which ref test exercises which source
// line/function) is rebuilt on every push to master and published to the
// gh-pages branch of the pdf.js.refs repository.
const PER_TEST_INDEX_URL =
"https://raw.githubusercontent.com/mozilla/pdf.js.refs/gh-pages/per-test-index.json";
let values;
try {
({ values } = parseArgs({
args: process.argv.slice(2),
options: {
code: { type: "string" },
"coverage-dir": { type: "string", default: "build/coverage" },
index: { type: "string", default: "build/per-test-index.json" },
"no-download": { type: "boolean", default: false },
help: { type: "boolean", short: "h", default: false },
},
});
}));
} catch (error) {
// parseArgs is strict, so an unknown/renamed option (e.g. the removed
// --coverage-dir) would otherwise abort with an uncaught stack trace.
console.error(`Error: ${error.message}`);
console.error("Run with --help to see the available options.");
process.exit(1);
}
if (values.help || !values.code) {
console.log(
"Usage: coverage_search.mjs --code=<file>::<line|function> [--coverage-dir=<path>]\n\n" +
"Usage: coverage_search.mjs --code=<file>::<line|function> [--index=<path>] [--no-download]\n\n" +
" --code Source file and line number or function name to search for.\n" +
" Examples:\n" +
" --code=canvas.js::205\n" +
" --code=canvas.js::drawImageAtIntegerCoords\n" +
" --coverage-dir Coverage directory containing per-test-index.json [build/coverage]\n\n" +
" --index Where to cache or read the per-test index.\n" +
" [build/per-test-index.json]\n" +
" --no-download Don't contact the network; use the cached index as-is.\n\n" +
"Prints to stdout the IDs of tests whose coverage includes the given line or\n" +
"function (one ID per line).\n" +
"Run browsertest with --coverage-per-test first to generate the index."
"function (one ID per line).\n\n" +
"The index is downloaded from the pdf.js.refs repository and cached locally;\n" +
"it is only re-downloaded when the published file has changed.\n" +
`Source: ${PER_TEST_INDEX_URL}`
);
process.exit(values.help ? 0 : 1);
}
@ -58,18 +78,129 @@ const isLine = /^\d+$/.test(location);
const lineNum = isLine ? parseInt(location, 10) : null;
const funcName = isLine ? null : location;
const coverageDir = path.isAbsolute(values["coverage-dir"])
? values["coverage-dir"]
: path.join(PROJECT_ROOT, values["coverage-dir"]);
const indexPath = path.isAbsolute(values.index)
? values.index
: path.join(PROJECT_ROOT, values.index);
// The ETag of the cached copy is stored alongside it, so the next run can ask
// the server (via If-None-Match) to only re-send the file when it has changed.
const etagPath = `${indexPath}.etag`;
// Refreshes the locally cached index from the published copy, downloading it
// only when it has changed since the last run. When the network is unavailable
// a previously cached copy is reused if present.
async function refreshIndex() {
if (values["no-download"]) {
return; // Freshness check disabled; the read below validates existence.
}
const hasCached = fs.existsSync(indexPath);
// On any download failure, fall back to a previously cached copy when one
// exists; otherwise there's nothing to search, so fail.
const fallbackOrFail = reason => {
if (hasCached) {
console.error(
`Warning: couldn't refresh per-test index (${reason}); using the cached copy.`
);
return;
}
console.error(`Error: couldn't download per-test index (${reason}).`);
process.exit(1);
};
const headers = new Headers();
if (hasCached && fs.existsSync(etagPath)) {
const etag = fs.readFileSync(etagPath, "utf8").trim();
// Only forward a syntactically valid HTTP ETag (RFC 7232), so the cached
// file's contents can't be used to inject arbitrary data into the request.
if (/^(?:W\/)?"[\x21\x23-\x7e]*"$/.test(etag)) {
headers.set("If-None-Match", etag);
}
}
let response;
try {
console.log(`Fetching per-test index from ${PER_TEST_INDEX_URL} ...`);
response = await fetch(PER_TEST_INDEX_URL, { headers });
} catch (error) {
fallbackOrFail(error.message);
return;
}
if (response.status === 304) {
console.log("Per-test index is up to date.");
return;
}
if (!response.ok) {
fallbackOrFail(`HTTP ${response.status}`);
return;
}
let text;
try {
text = await response.text();
} catch (error) {
fallbackOrFail(error.message);
return;
}
// Parse the payload before caching it, and cache the re-serialized result
// rather than the raw response body: only well-formed JSON produced by our
// own JSON.stringify is ever written to disk.
let serialized;
try {
serialized = JSON.stringify(JSON.parse(text));
} catch {
fallbackOrFail("the downloaded index is not valid JSON");
return;
}
// Write to a temporary file and rename it into place.
try {
fs.mkdirSync(path.dirname(indexPath), { recursive: true });
const tmpPath = `${indexPath}.${process.pid}.tmp`;
fs.writeFileSync(tmpPath, serialized);
fs.renameSync(tmpPath, indexPath);
const etag = response.headers.get("etag");
if (etag) {
fs.writeFileSync(etagPath, etag);
} else {
fs.rmSync(etagPath, { force: true });
}
} catch (error) {
// A write failure (disk full, read-only dir, ...) shouldn't be fatal when
// a usable cached copy already exists.
fallbackOrFail(error.message);
return;
}
console.log(`Per-test index updated (${serialized.length} bytes).`);
}
await refreshIndex();
const indexPath = path.join(coverageDir, "per-test-index.json");
if (!fs.existsSync(indexPath)) {
console.error(`Error: index file not found: ${indexPath}`);
console.error("Run browsertest with --coverage-per-test first.");
console.error(`Error: per-test index not found: ${indexPath}`);
console.error(
"Build it locally (gulp botbrowsertest --coverage-per-test) or omit " +
"--no-download to fetch it from the pdf.js.refs repository."
);
process.exit(1);
}
const { ids, files } = JSON.parse(fs.readFileSync(indexPath, "utf8"));
let ids, files;
try {
({ ids, files } = JSON.parse(fs.readFileSync(indexPath, "utf8")));
} catch (error) {
console.error(
`Error: couldn't read per-test index at ${indexPath}: ${error.message}`
);
console.error(
"The cached index may be corrupt; delete it and re-run without " +
"--no-download to refetch it."
);
process.exit(1);
}
// Find the file entry whose path matches fileName.
let fileEntry = null;

View File

@ -386,7 +386,7 @@ function writeNumber(n) {
if (buffer > 0) {
s = writeByte((buffer & 0x7f) | (s.length > 0 ? 0x80 : 0)) + s;
}
while (s.indexOf("80") === 0) {
while (s.startsWith("80")) {
s = s.substring(2);
}
return s;

45
external/qcms/qcms.js vendored
View File

@ -1,5 +1,5 @@
/* THIS FILE IS GENERATED - DO NOT EDIT */
import { copy_result, copy_rgb, make_cssRGB } from './qcms_utils.js';
import { copy_result } from './qcms_utils.js';
/**
@ -25,16 +25,20 @@ export const Intent = Object.freeze({
});
/**
* Converts `src` and hands the result to `copy_result`, laid out as RGB, or as
* RGBA with an opaque alpha when `add_alpha` is set.
*
* # Safety
*
* This function is called directly from JavaScript.
* @param {number} transformer
* @param {Uint8Array} src
* @param {boolean} add_alpha
*/
export function qcms_convert_array(transformer, src) {
export function qcms_convert_array(transformer, src, add_alpha) {
const ptr0 = passArray8ToWasm0(src, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
wasm.qcms_convert_array(transformer, ptr0, len0);
wasm.qcms_convert_array(transformer, ptr0, len0, add_alpha);
}
/**
@ -46,10 +50,11 @@ export function qcms_convert_array(transformer, src) {
* @param {number} src2
* @param {number} src3
* @param {number} src4
* @param {boolean} css
* @returns {number}
*/
export function qcms_convert_four(transformer, src1, src2, src3, src4, css) {
wasm.qcms_convert_four(transformer, src1, src2, src3, src4, css);
export function qcms_convert_four(transformer, src1, src2, src3, src4) {
const ret = wasm.qcms_convert_four(transformer, src1, src2, src3, src4);
return ret >>> 0;
}
/**
@ -58,10 +63,11 @@ export function qcms_convert_four(transformer, src1, src2, src3, src4, css) {
* This function is called directly from JavaScript.
* @param {number} transformer
* @param {number} src
* @param {boolean} css
* @returns {number}
*/
export function qcms_convert_one(transformer, src, css) {
wasm.qcms_convert_one(transformer, src, css);
export function qcms_convert_one(transformer, src) {
const ret = wasm.qcms_convert_one(transformer, src);
return ret >>> 0;
}
/**
@ -72,10 +78,11 @@ export function qcms_convert_one(transformer, src, css) {
* @param {number} src1
* @param {number} src2
* @param {number} src3
* @param {boolean} css
* @returns {number}
*/
export function qcms_convert_three(transformer, src1, src2, src3, css) {
wasm.qcms_convert_three(transformer, src1, src2, src3, css);
export function qcms_convert_three(transformer, src1, src2, src3) {
const ret = wasm.qcms_convert_three(transformer, src1, src2, src3);
return ret >>> 0;
}
/**
@ -106,18 +113,12 @@ export function qcms_transformer_from_memory(mem, in_type, intent) {
function __wbg_get_imports() {
const import0 = {
__proto__: null,
__wbg___wbindgen_throw_6b64449b9b9ed33c: function(arg0, arg1) {
__wbg___wbindgen_throw_344f42d3211c4765: function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
},
__wbg_copy_result_0d15f3bf9d9012ae: function(arg0, arg1) {
copy_result(arg0 >>> 0, arg1 >>> 0);
},
__wbg_copy_rgb_0106d9d9464fce43: function(arg0) {
copy_rgb(arg0 >>> 0);
},
__wbg_make_cssRGB_8e24b34f71f5363e: function(arg0) {
make_cssRGB(arg0 >>> 0);
},
__wbindgen_init_externref_table: function() {
const table = wasm.__wbindgen_externrefs;
const offset = table.grow(4);
@ -135,8 +136,7 @@ function __wbg_get_imports() {
}
function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return decodeText(ptr, len);
return decodeText(ptr >>> 0, len);
}
let cachedUint8ArrayMemory0 = null;
@ -170,8 +170,9 @@ function decodeText(ptr, len) {
let WASM_VECTOR_LEN = 0;
let wasmModule, wasm;
let wasmModule, wasmInstance, wasm;
function __wbg_finalize_init(instance, module) {
wasmInstance = instance;
wasm = instance.exports;
wasmModule = module;
cachedUint8ArrayMemory0 = null;

Binary file not shown.

View File

@ -13,22 +13,28 @@
* limitations under the License.
*/
// Alpha lives in the high byte of a pixel on a little-endian host and in the
// low byte on a big-endian one.
const ALPHA_MASK =
new Uint8Array(new Uint32Array([1]).buffer)[0] === 1 ? 0xff000000 : 0x000000ff;
const RGB_MASK = ~ALPHA_MASK;
class QCMS {
static #memoryArray = null;
static _memory = null;
static _mustAddAlpha = false;
// Where the next `qcms_convert_array` result should land.
static _destBuffer = null;
static _destOffset = 0;
static _destLength = 0;
static _cssColor = "";
static _makeHexColor = null;
// Set when the destination is RGBA and its alpha channel already holds
// something worth keeping, which is the case whenever the image has an
// /SMask: `fillOpacity` has run by then. The Wasm side does not know about
// that, so it always fills alpha in, and the bytes are merged here instead of
// copied wholesale.
static _keepAlpha = false;
static get _memoryArray() {
const array = this.#memoryArray;
@ -42,43 +48,31 @@ class QCMS {
function copy_result(ptr, len) {
// This function is called from the wasm module (it's an external
// "C" function). Its goal is to copy the result from the wasm memory
// to the destination buffer without any intermediate copies.
const { _mustAddAlpha, _destBuffer, _destOffset, _destLength, _memoryArray } =
QCMS;
if (len === _destLength) {
// to the destination buffer without any intermediate copies. The wasm side
// has already laid the result out the way the caller asked for it, so this is
// one bulk copy unless the destination's alpha has to survive.
const { _destBuffer, _destOffset, _keepAlpha, _memoryArray } = QCMS;
if (!_keepAlpha) {
_destBuffer.set(_memoryArray.subarray(ptr, ptr + len), _destOffset);
return;
}
if (_mustAddAlpha) {
for (let i = ptr, ii = ptr + len, j = _destOffset; i < ii; i += 3, j += 4) {
_destBuffer[j] = _memoryArray[i];
_destBuffer[j + 1] = _memoryArray[i + 1];
_destBuffer[j + 2] = _memoryArray[i + 2];
_destBuffer[j + 3] = 255;
const count = len >> 2;
const destStart = _destBuffer.byteOffset + _destOffset;
if (((destStart | ptr) & 3) === 0) {
// Both sides are pixel-aligned, so RGB can be merged a whole pixel at a
// time. `len` is a multiple of 4 here: the wasm side wrote RGBA.
const dest32 = new Uint32Array(_destBuffer.buffer, destStart, count);
const src32 = new Uint32Array(QCMS._memory.buffer, ptr, count);
for (let i = 0; i < count; i++) {
dest32[i] = (dest32[i] & ALPHA_MASK) | (src32[i] & RGB_MASK);
}
} else {
for (let i = ptr, ii = ptr + len, j = _destOffset; i < ii; i += 3, j += 4) {
return;
}
for (let i = ptr, ii = ptr + len, j = _destOffset; i < ii; i += 4, j += 4) {
_destBuffer[j] = _memoryArray[i];
_destBuffer[j + 1] = _memoryArray[i + 1];
_destBuffer[j + 2] = _memoryArray[i + 2];
}
}
}
function copy_rgb(ptr) {
const { _destBuffer, _destOffset, _memoryArray } = QCMS;
_destBuffer[_destOffset] = _memoryArray[ptr];
_destBuffer[_destOffset + 1] = _memoryArray[ptr + 1];
_destBuffer[_destOffset + 2] = _memoryArray[ptr + 2];
}
function make_cssRGB(ptr) {
const { _memoryArray } = QCMS;
QCMS._cssColor = QCMS._makeHexColor(
_memoryArray[ptr],
_memoryArray[ptr + 1],
_memoryArray[ptr + 2]
);
}
export { copy_result, copy_rgb, make_cssRGB, QCMS };
export { copy_result, QCMS };

View File

@ -2,15 +2,15 @@
async function QuickJS(moduleArg={}){var moduleRtn;var e=moduleArg,aa=import.meta.url,h="",m;try{h=(new URL(".",aa)).href}catch{}m=async a=>{a=await fetch(a,{credentials:"same-origin"});if(a.ok)return a.arrayBuffer();throw Error(a.status+" : "+a.url);};var q=console.error.bind(console),r,t=!1,u,v,w,x=!1;function y(){var a=z.buffer;A=new Int8Array(a);new Int16Array(a);B=new Uint8Array(a);new Uint16Array(a);C=new Int32Array(a);D=new Uint32Array(a);new Float32Array(a);new Float64Array(a);new BigInt64Array(a);new BigUint64Array(a)}
function E(a){e.onAbort?.(a);a=`Aborted(${a})`;q(a);t=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");w?.(a);throw a;}var F;async function ba(a){if(!r)try{var b=await m(a);return new Uint8Array(b)}catch{}if(a==F&&r)a=new Uint8Array(r);else throw"both async and sync fetching of the wasm failed";return a}async function ca(a,b){try{var c=await ba(a);return await WebAssembly.instantiate(c,b)}catch(d){q(`failed to asynchronously prepare wasm: ${d}`),E(d)}}
async function da(a){var b=F;if(!r)try{var c=fetch(b,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(c,a)}catch(d){q(`wasm streaming compile failed: ${d}`),q("falling back to ArrayBuffer instantiation")}return ca(b,a)}class G{name="ExitStatus";constructor(a){this.message=`Program terminated with exit(${a})`;this.status=a}}
var C,A,D,B,H=a=>{for(;0<a.length;)a.shift()(e)},I=[],J=[],ea=()=>{var a=e.preRun.shift();J.push(a)},K=!0,L=0,fa=[0,31,60,91,121,152,182,213,244,274,305,335],ha=[0,31,59,90,120,151,181,212,243,273,304,334],M={},N=a=>{if(!(a instanceof G||"unwind"==a))throw a;},O=a=>{u=a;K||0<L||(e.onExit?.(a),t=!0);throw new G(a);},ia=a=>{if(!t)try{a()}catch(b){N(b)}finally{if(!(K||0<L))try{u=a=u,O(a)}catch(b){N(b)}}},P=(a,b,c)=>{var d=B;if(0<c){c=b+c-1;for(var g=0;g<a.length;++g){var f=a.codePointAt(g);if(127>=f){if(b>=
c)break;d[b++]=f}else if(2047>=f){if(b+1>=c)break;d[b++]=192|f>>6;d[b++]=128|f&63}else if(65535>=f){if(b+2>=c)break;d[b++]=224|f>>12;d[b++]=128|f>>6&63;d[b++]=128|f&63}else{if(b+3>=c)break;d[b++]=240|f>>18;d[b++]=128|f>>12&63;d[b++]=128|f>>6&63;d[b++]=128|f&63;g++}}d[b]=0}},ja=new TextDecoder,Q=a=>{if(a){for(var b=a,c=B,d=b+void 0;c[b]&&!(b>=d);)++b;a=ja.decode(B.subarray(a,b))}else a="";return a},R=a=>{for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);127>=d?b++:2047>=d?b+=2:55296<=d&&57343>=
d?(b+=4,++c):b+=3}return b},T=a=>{var b=R(a)+1,c=S(b);c&&P(a,c,b);return c};function U(){}var la=(a,b,c,d)=>{var g={string:k=>{var n=0;if(null!==k&&void 0!==k&&0!==k){n=R(k)+1;var X=V(n);P(k,X,n);n=X}return n},array:k=>{var n=V(k.length);A.set(k,n);return n}};a=e["_"+a];var f=[],p=0;if(d)for(var l=0;l<d.length;l++){var Y=g[c[l]];Y?(0===p&&(p=W()),f[l]=Y(d[l])):f[l]=d[l]}c=a(...f);return c=function(k){0!==p&&ka(p);return"string"===b?Q(k):"boolean"===b?!!k:k}(c)};
U=(a,b,c)=>{a=Q(a);b=null!==b?JSON.parse(Q(b)):[];try{const d=e.externalCall(a,b);return d?T(d):null}catch(d){return e.HEAPU8[c]=1,T(d.message)}};e.noExitRuntime&&(K=e.noExitRuntime);e.printErr&&(q=e.printErr);e.wasmBinary&&(r=e.wasmBinary);if(e.preInit)for("function"==typeof e.preInit&&(e.preInit=[e.preInit]);0<e.preInit.length;)e.preInit.shift()();e.ccall=la;e.cwrap=(a,b,c,d)=>{var g=!c||c.every(f=>"number"===f||"boolean"===f);return"string"!==b&&g&&!d?e["_"+a]:(...f)=>la(a,b,c,f,d)};
var C,A,D,B,H=a=>{for(;a.length>0;)a.shift()(e)},I=[],J=[],ea=()=>{var a=e.preRun.shift();J.push(a)},K=!0,L=0,fa=[0,31,60,91,121,152,182,213,244,274,305,335],ha=[0,31,59,90,120,151,181,212,243,273,304,334],M={},N=a=>{if(!(a instanceof G||a=="unwind"))throw a;},O=a=>{u=a;K||L>0||(e.onExit?.(a),t=!0);throw new G(a);},ia=a=>{if(!t)try{a()}catch(b){N(b)}finally{if(!(K||L>0))try{u=a=u,O(a)}catch(b){N(b)}}},P=(a,b,c)=>{var d=B;if(c>0){c=b+c-1;for(var g=0;g<a.length;++g){var f=a.codePointAt(g);if(f<=127){if(b>=
c)break;d[b++]=f}else if(f<=2047){if(b+1>=c)break;d[b++]=192|f>>6;d[b++]=128|f&63}else if(f<=65535){if(b+2>=c)break;d[b++]=224|f>>12;d[b++]=128|f>>6&63;d[b++]=128|f&63}else{if(b+3>=c)break;d[b++]=240|f>>18;d[b++]=128|f>>12&63;d[b++]=128|f>>6&63;d[b++]=128|f&63;g++}}d[b]=0}},ja=new TextDecoder,Q=a=>{if(a){for(var b=a,c=B,d=b+void 0;c[b]&&!(b>=d);)++b;a=ja.decode(B.subarray(a,b))}else a="";return a},R=a=>{for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);d<=127?b++:d<=2047?b+=2:d>=55296&&d<=57343?
(b+=4,++c):b+=3}return b},T=a=>{var b=R(a)+1,c=S(b);c&&P(a,c,b);return c};function U(){}var la=(a,b,c,d)=>{var g={string:k=>{var n=0;if(k!==null&&k!==void 0&&k!==0){n=R(k)+1;var X=V(n);P(k,X,n);n=X}return n},array:k=>{var n=V(k.length);A.set(k,n);return n}};a=e["_"+a];var f=[],p=0;if(d)for(var l=0;l<d.length;l++){var Y=g[c[l]];Y?(p===0&&(p=W()),f[l]=Y(d[l])):f[l]=d[l]}c=a(...f);return c=function(k){p!==0&&ka(p);return b==="string"?Q(k):b==="boolean"?!!k:k}(c)};
U=(a,b,c)=>{a=Q(a);b=b!==null?JSON.parse(Q(b)):[];try{let d=e.externalCall(a,b);return d?T(d):null}catch(d){return e.HEAPU8[c]=1,T(d.message)}};e.noExitRuntime&&(K=e.noExitRuntime);e.printErr&&(q=e.printErr);e.wasmBinary&&(r=e.wasmBinary);if(e.preInit)for(typeof e.preInit=="function"&&(e.preInit=[e.preInit]);e.preInit.length>0;)e.preInit.shift()();e.ccall=la;e.cwrap=(a,b,c,d)=>{var g=!c||c.every(f=>f==="number"||f==="boolean");return b!=="string"&&g&&!d?e["_"+a]:(...f)=>la(a,b,c,f,d)};
e.stringToNewUTF8=T;
var S,ma,ka,V,W,z,na={e:()=>E(""),a:()=>{K=!1;L=0},b:function(a,b){a=-9007199254740992>a||9007199254740992<a?NaN:Number(a);a=new Date(1E3*a);C[b>>2]=a.getSeconds();C[b+4>>2]=a.getMinutes();C[b+8>>2]=a.getHours();C[b+12>>2]=a.getDate();C[b+16>>2]=a.getMonth();C[b+20>>2]=a.getFullYear()-1900;C[b+24>>2]=a.getDay();var c=a.getFullYear();C[b+28>>2]=(0!==c%4||0===c%100&&0!==c%400?ha:fa)[a.getMonth()]+a.getDate()-1|0;C[b+36>>2]=-(60*a.getTimezoneOffset());c=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();
var d=(new Date(a.getFullYear(),0,1)).getTimezoneOffset();C[b+32>>2]=(c!=d&&a.getTimezoneOffset()==Math.min(d,c))|0},i:(a,b)=>{M[a]&&(clearTimeout(M[a].id),delete M[a]);if(!b)return 0;var c=setTimeout(()=>{delete M[a];ia(()=>ma(a,performance.now()))},b);M[a]={id:c,A:b};return 0},c:(a,b,c,d)=>{var g=(new Date).getFullYear(),f=(new Date(g,0,1)).getTimezoneOffset();g=(new Date(g,6,1)).getTimezoneOffset();D[a>>2]=60*Math.max(f,g);C[b>>2]=Number(f!=g);b=p=>{var l=Math.abs(p);return`UTC${0<=p?"-":"+"}${String(Math.floor(l/
60)).padStart(2,"0")}${String(l%60).padStart(2,"0")}`};a=b(f);b=b(g);g<f?(P(a,c,17),P(b,d,17)):(P(a,d,17),P(b,c,17))},g:U,f:function(a,b){a=Q(a);let c;try{c=window.JSON.parse(a)}catch(d){c=a}0!==b?window.alert(a):window.console.log("DUMP",c)},d:()=>Date.now(),j:a=>{var b=B.length;a>>>=0;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);a:{d=(Math.min(2147483648,65536*Math.ceil(Math.max(a,d)/65536))-z.buffer.byteLength+65535)/65536|0;try{z.grow(d);y();var g=
1;break a}catch(f){}g=void 0}if(g)return!0}return!1},m:function(a){a=Q(a);window.console.log(a)},h:function(a){a=Q(a);return Date.parse(a)},l:function(a,b,c,d){a=Q(a);b=Q(b);c=Q(c);c=`Quickjs -- ${a}: ${b}\n${c}`;0!==d?window.alert(c):window.console.error(c)},k:O},Z;
Z=await (async function(){function a(c){c=Z=c.exports;e._evalInSandbox=c.p;e._nukeSandbox=c.q;e._init=c.r;e._commFun=c.s;e._dumpMemoryUse=c.t;S=c.u;e._free=c.v;ma=c.w;ka=c.x;V=c.y;W=c.z;z=c.n;y();return Z}var b={a:na};if(e.instantiateWasm)return new Promise(c=>{e.instantiateWasm(b,(d,g)=>{c(a(d,g))})});F??=e.locateFile?e.locateFile?e.locateFile("quickjs-eval.wasm",h):h+"quickjs-eval.wasm":(new URL("quickjs-eval.wasm",import.meta.url)).href;return a((await da(b)).instance)}());
(function(){function a(){e.calledRun=!0;if(!t){x=!0;Z.o();v?.(e);e.onRuntimeInitialized?.();if(e.postRun)for("function"==typeof e.postRun&&(e.postRun=[e.postRun]);e.postRun.length;){var b=e.postRun.shift();I.push(b)}H(I)}}if(e.preRun)for("function"==typeof e.preRun&&(e.preRun=[e.preRun]);e.preRun.length;)ea();H(J);e.setStatus?(e.setStatus("Running..."),setTimeout(()=>{setTimeout(()=>e.setStatus(""),1);a()},1)):a()})();x?moduleRtn=e:moduleRtn=new Promise((a,b)=>{v=a;w=b});
var S,ma,ka,V,W,z,na={e:()=>E(""),a:()=>{K=!1;L=0},b:function(a,b){a=a<-9007199254740992||a>9007199254740992?NaN:Number(a);a=new Date(a*1E3);C[b>>2]=a.getSeconds();C[b+4>>2]=a.getMinutes();C[b+8>>2]=a.getHours();C[b+12>>2]=a.getDate();C[b+16>>2]=a.getMonth();C[b+20>>2]=a.getFullYear()-1900;C[b+24>>2]=a.getDay();var c=a.getFullYear();C[b+28>>2]=(c%4!==0||c%100===0&&c%400!==0?ha:fa)[a.getMonth()]+a.getDate()-1|0;C[b+36>>2]=-(a.getTimezoneOffset()*60);c=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();
var d=(new Date(a.getFullYear(),0,1)).getTimezoneOffset();C[b+32>>2]=(c!=d&&a.getTimezoneOffset()==Math.min(d,c))|0},i:(a,b)=>{M[a]&&(clearTimeout(M[a].id),delete M[a]);if(!b)return 0;var c=setTimeout(()=>{delete M[a];ia(()=>ma(a,performance.now()))},b);M[a]={id:c,A:b};return 0},c:(a,b,c,d)=>{var g=(new Date).getFullYear(),f=(new Date(g,0,1)).getTimezoneOffset();g=(new Date(g,6,1)).getTimezoneOffset();D[a>>2]=Math.max(f,g)*60;C[b>>2]=Number(f!=g);b=p=>{var l=Math.abs(p);return`UTC${p>=0?"-":"+"}${String(Math.floor(l/
60)).padStart(2,"0")}${String(l%60).padStart(2,"0")}`};a=b(f);b=b(g);g<f?(P(a,c,17),P(b,d,17)):(P(a,d,17),P(b,c,17))},g:U,f:function(a,b){a=Q(a);try{var c=window.JSON.parse(a)}catch(d){c=a}b!==0?window.alert(a):window.console.log("DUMP",c)},d:()=>Date.now(),j:a=>{var b=B.length;a>>>=0;if(a>2147483648)return!1;for(var c=1;c<=4;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);a:{d=(Math.min(2147483648,Math.ceil(Math.max(a,d)/65536)*65536)-z.buffer.byteLength+65535)/65536|0;try{z.grow(d);y();var g=1;
break a}catch(f){}g=void 0}if(g)return!0}return!1},m:function(a){a=Q(a);window.console.log(a)},h:function(a){a=Q(a);return Date.parse(a)},l:function(a,b,c,d){a=Q(a);b=Q(b);c=Q(c);c=`Quickjs -- ${a}: ${b}\n${c}`;d!==0?window.alert(c):window.console.error(c)},k:O},Z;
Z=await (async function(){function a(c){c=Z=c.exports;e._evalInSandbox=c.p;e._nukeSandbox=c.q;e._init=c.r;e._commFun=c.s;e._dumpMemoryUse=c.t;S=c.u;e._free=c.v;ma=c.w;ka=c.x;V=c.y;W=c.z;z=c.n;y();return Z}var b={a:na};if(e.instantiateWasm)return new Promise(c=>{e.instantiateWasm(b,(d,g)=>{c(a(d,g))})});F??=e.locateFile?e.locateFile?e.locateFile("quickjs-eval.wasm",h):h+"quickjs-eval.wasm":(new URL("quickjs-eval.wasm",import.meta.url)).href;return function(c){return a(c.instance)}(await da(b))}());
(function(){function a(){e.calledRun=!0;if(!t){x=!0;Z.o();v?.(e);e.onRuntimeInitialized?.();if(e.postRun)for(typeof e.postRun=="function"&&(e.postRun=[e.postRun]);e.postRun.length;){var b=e.postRun.shift();I.push(b)}H(I)}}if(e.preRun)for(typeof e.preRun=="function"&&(e.preRun=[e.preRun]);e.preRun.length;)ea();H(J);e.setStatus?(e.setStatus("Running..."),setTimeout(()=>{setTimeout(()=>e.setStatus(""),1);a()},1)):a()})();x?moduleRtn=e:moduleRtn=new Promise((a,b)=>{v=a;w=b});
;return moduleRtn}export default QuickJS;

Binary file not shown.

View File

@ -13,7 +13,9 @@
* limitations under the License.
*/
import * as babel from "@babel/core";
import {
babelPluginAddHeaderComment,
babelPluginPDFJSPreprocessor,
babelPluginStripSrcPath,
preprocessPDFJSCode,
@ -24,7 +26,6 @@ import {
} from "./external/ccov/coverage_format.mjs";
import { exec, execSync, spawn, spawnSync } from "child_process";
import autoprefixer from "autoprefixer";
import babel from "@babel/core";
import { buildPrefsSchema } from "./external/chromium/prefs.mjs";
import crypto from "crypto";
import { finished } from "stream/promises";
@ -104,11 +105,11 @@ const AUTOPREFIXER_CONFIG = {
// Default Babel targets used for generic, components, minified-pre
const BABEL_TARGETS = ENV_TARGETS.join(", ");
const BABEL_PRESET_ENV_OPTS = Object.freeze({
corejs: "3.49.0",
const BABEL_COREJS_OPTS = Object.freeze({
method: "usage-global",
version: "3.49.0",
exclude: ["web.structured-clone"],
shippedProposals: true,
useBuiltIns: "usage",
});
const DEFINES = Object.freeze({
@ -225,6 +226,8 @@ function createWebpackAlias(defines) {
"web-print_service": "",
"web-secondary_toolbar": "web/secondary_toolbar.js",
"web-signature_manager": "web/signature_manager.js",
"web-digital_signature_properties_manager":
"web/digital_signature_properties_manager.js",
"web-toolbar": "web/toolbar.js",
"web-views_manager": "web/views_manager.js",
};
@ -325,9 +328,7 @@ function createWebpackConfig(
/node_modules[\\/]core-js/,
];
const babelPresets = skipBabel
? undefined
: [["@babel/preset-env", BABEL_PRESET_ENV_OPTS]];
const babelPresets = skipBabel ? undefined : ["@babel/preset-env"];
const babelPlugins = [
[
babelPluginPDFJSPreprocessor,
@ -337,6 +338,9 @@ function createWebpackConfig(
},
],
];
if (!skipBabel) {
babelPlugins.push(["babel-plugin-polyfill-corejs3", BABEL_COREJS_OPTS]);
}
if (bundleDefines.COVERAGE) {
babelPlugins.push("babel-plugin-istanbul");
}
@ -789,36 +793,18 @@ function runTests(testsName, { bot = false } = {}) {
args.push("--coveragePerTest");
}
const codeArg = testsName === "browser" ? getArgValue("--code") : null;
if (codeArg) {
const coverageDir =
getArgValue("--coverage-output") || BUILD_DIR + "coverage";
const result = spawnSync(
"node",
[
path.join(__dirname, "external/ccov/coverage_search.mjs"),
`--code=${codeArg}`,
`--coverage-dir=${coverageDir}`,
],
{ encoding: "utf8" }
);
if (result.status !== 0) {
reject(new Error(result.stderr?.trim() || "coverage_search failed"));
if (testsName === "browser") {
let shouldRun;
try {
shouldRun = applyCodeTestFilter(args);
} catch (error) {
reject(error);
return;
}
const testIds = result.stdout.trim().split("\n").filter(Boolean);
if (testIds.length === 0) {
console.log(`\n### No tests found covering "${codeArg}"`);
if (!shouldRun) {
resolve();
return;
}
console.log(
`\n### Found ${testIds.length} test(s) covering "${codeArg}":\n` +
testIds.map(id => ` ${id}`).join("\n")
);
for (const id of testIds) {
args.push(`-t=${id}`);
}
}
const testProcess = startNode(args, { cwd: TEST_DIR, stdio: "inherit" });
@ -884,6 +870,136 @@ function collectArgs(options, args) {
}
}
// Builds the coverage_search command line. By default the published index is
// downloaded; an explicit --index=<path> selects a local index instead, used
// read-only so it's never overwritten by the published copy.
function getCoverageSearchArgs(codeArg) {
const searchArgs = [
path.join(__dirname, "external/ccov/coverage_search.mjs"),
`--code=${codeArg}`,
];
const indexArg = getArgValue("--index");
if (indexArg === "") {
// An explicit but empty value (e.g. an unset shell variable expanding to
// `--index=`) almost certainly isn't intended; fail loudly rather than
// silently falling back to the downloaded index.
throw new Error("--index was given without a value");
}
if (indexArg) {
searchArgs.push(`--index=${indexArg}`, "--no-download");
} else if (process.argv.includes("--no-download")) {
searchArgs.push("--no-download");
}
return searchArgs;
}
// Returns the set of test IDs defined in the local ref-test manifest, or null
// when it can't be read. Used to drop coverage-derived IDs that don't exist on
// this branch (e.g. a test renamed since the published index was built), which
// would otherwise make test.mjs reject the entire run.
function readManifestTestIds() {
try {
const manifestFile = process.env.PDF_TEST || "test_manifest.json";
const manifest = JSON.parse(
fs.readFileSync(path.join(__dirname, TEST_DIR, manifestFile), "utf8")
);
return new Set(manifest.map(entry => entry.id));
} catch {
return null;
}
}
// For a --code=<file>::<line|function> argument, runs coverage_search to find
// the ref tests that exercise that location and returns their IDs (an empty
// array when none match locally). Returns null when --code wasn't given; throws
// when the search itself fails.
function resolveCodeTestIds() {
const codeArg = getArgValue("--code");
if (!codeArg) {
return null;
}
// Inherit stderr so the index download progress is visible; stdout is
// captured because it carries the matching test IDs.
const result = spawnSync("node", getCoverageSearchArgs(codeArg), {
encoding: "utf8",
stdio: ["ignore", "pipe", "inherit"],
});
if (result.status !== 0) {
// status is null when the child couldn't be spawned or was killed by a
// signal; surface the real cause instead of a generic message.
throw new Error(
result.error
? `coverage_search failed: ${result.error.message}`
: `coverage_search failed (exit code ${result.status})`
);
}
let testIds = result.stdout.trim().split("\n").filter(Boolean);
// The published index is built from master, so some covering tests may not
// exist on this branch. Drop them (with a note) rather than letting test.mjs
// reject the whole run — and silently exit 0 — on the first unknown ID.
const knownIds = readManifestTestIds();
if (knownIds) {
const missing = testIds.filter(id => !knownIds.has(id));
if (missing.length) {
console.log(
`\n### Ignoring ${missing.length} covered test(s) not in the manifest:\n` +
missing.map(id => ` ${id}`).join("\n")
);
testIds = testIds.filter(id => knownIds.has(id));
}
}
if (testIds.length === 0) {
console.log(`\n### No tests found covering "${codeArg}"`);
} else {
console.log(
`\n### Found ${testIds.length} test(s) covering "${codeArg}":\n` +
testIds.map(id => ` ${id}`).join("\n")
);
}
return testIds;
}
function appendTestFilters(args, testIds) {
const existingIds = new Set();
// collectArgs always normalizes filters to the space-separated
// `-t <id>` / `--testfilter <id>` form, so that's the only shape to read.
for (let i = 0; i < args.length; i++) {
if (args[i] === "-t" || args[i] === "--testfilter") {
if (i + 1 < args.length) {
existingIds.add(args[++i]);
}
}
}
for (const id of testIds) {
if (!existingIds.has(id)) {
// Pass the id as a separate argument: node's parseArgs parses the short
// form `-t=<id>` as the literal value "=<id>", which matches no test and
// aborts the run with "Unrecognized test IDs".
args.push("-t", id);
existingIds.add(id);
}
}
}
// Applies the --code coverage filter to `args`. Returns false when the run
// should be skipped (--code was given but resolved to no runnable tests), and
// true otherwise (no --code, or matching tests were appended). Throws when the
// coverage search itself fails.
function applyCodeTestFilter(args) {
const codeTestIds = resolveCodeTestIds();
if (codeTestIds === null) {
return true; // No --code argument; run normally.
}
if (codeTestIds.length === 0) {
return false; // Nothing (runnable) covers the requested location.
}
appendTestFilters(args, codeTestIds);
return true;
}
function makeRef(done, bot) {
console.log("\n### Creating reference images");
@ -932,6 +1048,18 @@ function makeRef(done, bot) {
args
);
let shouldRun;
try {
shouldRun = applyCodeTestFilter(args);
} catch (error) {
done(error);
return;
}
if (!shouldRun) {
done();
return;
}
const testProcess = startNode(args, { cwd: TEST_DIR, stdio: "inherit" });
testProcess.on("close", function (code) {
if (code !== 0) {
@ -942,34 +1070,33 @@ function makeRef(done, bot) {
});
}
// Queries the per-test coverage index built by --coverage-per-test and prints
// the IDs of tests that exercised a given source file location. Run with
// --code=<file>::<line|function>, e.g. --code=canvas.js::205
// Prints the IDs of tests that exercised a given source file location, using
// the per-test coverage index published to the pdf.js.refs repository. The
// index is downloaded on demand, cached locally, and only re-downloaded when
// it has changed. Run with --code=<file>::<line|function>, e.g.
// --code=canvas.js::205 (add --no-download to reuse the cached index offline).
gulp.task("coverage_search", function (done) {
const codeArg = getArgValue("--code");
if (!codeArg) {
done(new Error('Missing --code argument, e.g. --code="canvas.js::205"'));
return;
}
const coverageDir =
getArgValue("--coverage-output") || BUILD_DIR + "coverage";
const result = spawnSync(
"node",
[
path.join(__dirname, "external/ccov/coverage_search.mjs"),
`--code=${codeArg}`,
`--coverage-dir=${coverageDir}`,
],
{ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
);
if (result.stderr) {
process.stderr.write(result.stderr);
}
if (result.stdout) {
process.stdout.write(result.stdout);
let searchArgs;
try {
searchArgs = getCoverageSearchArgs(codeArg);
} catch (error) {
done(error);
return;
}
const result = spawnSync("node", searchArgs, { stdio: "inherit" });
if (result.status !== 0) {
done(new Error("coverage_search failed"));
done(
new Error(
result.error
? `coverage_search failed: ${result.error.message}`
: `coverage_search failed (exit code ${result.status})`
)
);
return;
}
done();
@ -1030,10 +1157,7 @@ function createBuildNumber(done) {
const version = config.versionPrefix + buildNumber;
exec('git log --format="%h" -n 1', function (err2, stdout2, stderr2) {
let buildCommit = "";
if (!err2) {
buildCommit = stdout2.replace("\n", "");
}
const buildCommit = !err2 ? stdout2.replace("\n", "") : "";
createStringSource(
"version.json",
@ -1686,9 +1810,9 @@ function buildLibHelper(bundleDefines, inputStream, outputDir) {
const licenseHeader = fs
.readFileSync("./src/license_header.js")
.toString()
.split("\n")
.slice(1, -2)
.map(line => line.replace(/^\s*\*\s?/, ""));
.trim()
.replace(/^\/\*/, "")
.replace(/\*\/$/, "");
const ctx = {
rootPath: __dirname,
@ -1728,6 +1852,9 @@ function buildLibHelper(bundleDefines, inputStream, outputDir) {
[babelPluginPDFJSPreprocessor, ctx],
[babelPluginStripSrcPath],
];
if (!skipBabel) {
plugins.push(["babel-plugin-polyfill-corejs3", BABEL_COREJS_OPTS]);
}
if (enableCoverage) {
plugins.push([
"babel-plugin-istanbul",
@ -1737,28 +1864,16 @@ function buildLibHelper(bundleDefines, inputStream, outputDir) {
},
]);
}
plugins.push([
"add-header-comment",
{
header: licenseHeader,
},
]);
plugins.push([babelPluginAddHeaderComment, { header: licenseHeader }]);
const result = babel.transform(file.contents.toString(), {
const result = babel.transformSync(file.contents.toString(), {
...(enableCoverage && {
filename: file.path,
babelrc: false,
configFile: false,
}),
sourceType: "module",
presets: skipBabel
? undefined
: [
[
"@babel/preset-env",
{ ...BABEL_PRESET_ENV_OPTS, loose: false, modules: false },
],
],
presets: skipBabel ? undefined : ["@babel/preset-env"],
plugins,
targets: BABEL_TARGETS,
sourceMaps: enableSourceMaps,
@ -2399,6 +2514,71 @@ gulp.task("lint-chmod", function (done) {
done();
});
gulp.task("lint-bom", async function () {
console.log("\n### Checking for UTF-8 byte order marks");
// Cover untracked-but-not-ignored files too, so a BOM in a freshly created
// file is caught before `git add`.
const files = execSync("git ls-files -coz --exclude-standard", {
encoding: "utf8",
maxBuffer: 1 << 28,
})
.split("\0")
.filter(Boolean);
// Only the first three bytes matter: a leading EF BB BF is a UTF-8 BOM.
async function hasBOM(file) {
let handle;
try {
handle = await fs.promises.open(file, "r");
} catch {
return false; // Directory, broken symlink, removed file, etc.
}
try {
const { bytesRead, buffer } = await handle.read(Buffer.alloc(3), 0, 3, 0);
return (
bytesRead === 3 &&
buffer[0] === 0xef &&
buffer[1] === 0xbb &&
buffer[2] === 0xbf
);
} finally {
await handle.close();
}
}
// Don't exhaust file descriptors.
const offenders = [];
for (let i = 0; i < files.length; i += 256) {
const chunk = files.slice(i, i + 256);
const flags = await Promise.all(chunk.map(hasBOM));
chunk.forEach((file, j) => flags[j] && offenders.push(file));
}
offenders.sort();
if (offenders.length === 0) {
console.log("files checked, no errors found");
return;
}
if (!process.argv.includes("--fix")) {
for (const file of offenders) {
console.log(` Unexpected byte order mark: ${file}`);
}
throw new Error("BOM check failed (run `gulp lint-bom --fix` to clear).");
}
// Strip the BOM on disk and let the user stage the change.
await Promise.all(
offenders.map(async file => {
const content = await fs.promises.readFile(file);
await fs.promises.writeFile(file, content.subarray(3));
console.log(` removed byte order mark: ${file}`);
})
);
console.log(`done: ${offenders.length} file(s) updated`);
});
gulp.task("lint", function (done) {
console.log("\n### Linting JS/CSS/JSON/SVG/HTML files");
@ -2463,7 +2643,7 @@ gulp.task("lint", function (done) {
return;
}
gulp.series("lint-licenses", "lint-chmod")(done);
gulp.series("lint-licenses", "lint-chmod", "lint-bom")(done);
});
});

View File

@ -153,6 +153,19 @@ pdfjs-document-properties-linearized = العرض السريع عبر الوِب
pdfjs-document-properties-linearized-yes = نعم
pdfjs-document-properties-linearized-no = لا
pdfjs-document-properties-close-button = أغلق
pdfjs-digital-signature-properties-view-certificate = اعرض الشهادة
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = السبب: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = الطابع الزمني: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
## Print
@ -764,6 +777,49 @@ pdfjs-views-manager-waiting-for-file = يرفع ملف…
pdfjs-toggle-views-manager-button1 =
.title = أدِر الصفحات
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = خصائص التوقيع الرقمي
.aria-label = خصائص التوقيع الرقمي
pdfjs-digital-signature-properties-button-label = خصائص التوقيع الرقمي
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = وقِّع المستند بتوقيع رقمي صالح
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = الحالة: تحققَ من التوقيع
pdfjs-digital-signature-properties-status-invalid = الحالة: التوقيع غير صالح
pdfjs-digital-signature-properties-status-unknown = الحالة: تعذّر التحقق (غير مدعوم)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = الشهادة: موثوقة ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = الشهادة: غير متوفرة
pdfjs-digital-signature-properties-certificate-untrusted = الشهادة: غير موثوقة
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = الشهادة: جهة إصدار مجهولة ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = الشهادة: موقعّة ذاتيًا ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = الشهادة: جهة إصدار مجهولة ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = الشهادة: منتهية الصلاحية
pdfjs-digital-signature-properties-certificate-expired-with-date = الشهادة: منتهية الصلاحية ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = الشهادة: مُلغاة
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,28 @@ pdfjs-document-properties-linearized = Хуткі прагляд у Інтэрн
pdfjs-document-properties-linearized-yes = Так
pdfjs-document-properties-linearized-no = Не
pdfjs-document-properties-close-button = Закрыць
pdfjs-digital-signature-properties-view-certificate = Паказаць сертыфікат
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Прычына: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Адзнака часу: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Дадатковы подпіс ({ $count })
[few] Дадатковыя подпісы ({ $count })
*[many] Дадатковыя подпісы ({ $count })
}
## Print
@ -740,6 +762,79 @@ pdfjs-views-manager-waiting-for-file = Зацягваецца файл…
pdfjs-toggle-views-manager-button1 =
.title = Кіраванне старонкамі
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Уласцівасці лічбавага подпісу
.aria-label = Уласцівасці лічбавага подпісу
pdfjs-digital-signature-properties-button-label = Уласцівасці лічбавага подпісу
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Дакумент быў падпісаны сапраўдным лічбавым подпісам
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Дакумент падпісаны, але { $count } лічбавы подпіс не ўдалося праверыць
[few] Дакумент падпісаны, але { $count } лічбавыя подпісы не ўдалося праверыць
*[many] Дакумент падпісаны, але { $count } лічбавых подпісаў не ўдалося праверыць
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Дакумент падпісаны { $count } недавераным сертыфікатам
[few] Дакумент падпісаны { $count } недаверанымі сертыфікатамі
*[many] Дакумент падпісаны { $count } недаверанымі сертыфікатамі
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Дакумент падпісаны { $count } пратэрмінаваным сертыфікатам
[few] Дакумент падпісаны { $count } пратэрмінаванымі сертыфікатамі
*[many] Дакумент падпісаны { $count } пратэрмінаванымі сертыфікатамі
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Дакумент мае { $count } нядзейсны лічбавы подпіс
[few] Дакумент мае { $count } нядзейсныя лічбавыя подпісы
*[many] Дакумент мае { $count } нядзейсных лічбавых подпісаў
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Дакумент падпісаны { $count } адкліканым сертыфікатам
[few] Дакумент падпісаны { $count } адкліканымі сертыфікатамі
*[many] Дакумент падпісаны { $count } адкліканымі сертыфікатамі
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Статус: Подпіс правераны
pdfjs-digital-signature-properties-status-invalid = Статус: Подпіс нядзейсны
pdfjs-digital-signature-properties-status-unknown = Статус: Немагчыма праверыць (не падтрымліваецца)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Сертыфікат: Давераны ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Сертыфікат: Недаступны
pdfjs-digital-signature-properties-certificate-untrusted = Сертыфікат: Недавераны
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Сертыфікат: Невядомы выдавец ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Сертыфікат: Самападпісаны ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Сертыфікат: Недавераны выдавец ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Сертыфікат: Пратэрмінаваны
pdfjs-digital-signature-properties-certificate-expired-with-date = Сертыфікат: Пратэрмінаваны ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Сертыфікат: Адкліканы
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -386,3 +386,16 @@ pdfjs-editor-new-alt-text-not-now-button = Не сега
## Image alt-text settings
pdfjs-editor-alt-text-settings-delete-model-button = Изтриване
## Controls
pdfjs-editor-add-signature-image-upload-error-description = Проверете мрежовата си връзка или опитайте с друго изображение.
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-expired = Сертификат: с изтекъл срок на валидност

View File

@ -5,18 +5,194 @@
## Main toolbar buttons (tooltips and alt text for images)
pdfjs-previous-button =
.title = بلگه دیندایی
pdfjs-previous-button-label = دیندایی
pdfjs-next-button =
.title = بلگه نیایی
pdfjs-next-button-label = بئڌی
# .title: Tooltip for the pageNumber input.
pdfjs-page-input =
.title = بلگه
# Variables:
# $pagesCount (Number) - the total number of pages in the document
# This string follows an input field with the number of the page currently displayed.
pdfjs-of-pages = ز { $pagesCount }
# Variables:
# $pageNumber (Number) - the currently visible page
# $pagesCount (Number) - the total number of pages in the document
pdfjs-page-of-pages = ({ $pageNumber } ز { $pagesCount })
pdfjs-zoom-out-button =
.title = کۊچیر نمایی
pdfjs-zoom-out-button-label = کۊچیر نمایی
pdfjs-zoom-in-button =
.title = گپ نمایی
pdfjs-zoom-in-button-label = گپ نمایی
pdfjs-zoom-select =
.title = زۊم کردن
pdfjs-open-file-button =
.title = گۊشیڌن فایل
pdfjs-open-file-button-label = گۊشیڌن
pdfjs-print-button =
.title = چاپ
pdfjs-print-button-label = چاپ
pdfjs-save-button =
.title = زفت
pdfjs-save-button-label = زفت
# Used in Firefox for Android as a tooltip for the download button (“download” is a verb).
pdfjs-download-button =
.title = دانلود
# Used in Firefox for Android as a label for the download button (“download” is a verb).
# Length of the translation matters since we are in a mobile context, with limited screen estate.
pdfjs-download-button-label = دانلود
pdfjs-bookmark-button-label = بلگه هیم سکویی
## Secondary toolbar and context menu
pdfjs-tools-button =
.title = ٱوزارا
pdfjs-tools-button-label = ٱوزارا
pdfjs-first-page-button =
.title = رئڌن و بلگه نیایی
pdfjs-first-page-button-label = رئڌن و بلگه نیایی
pdfjs-last-page-button =
.title = رئڌن و بلگه دیندایی
pdfjs-last-page-button-label = رئڌن و بلگه دیندایی
pdfjs-page-rotate-cw-button =
.title = لر خردن ساعتگرد
pdfjs-page-rotate-cw-button-label = لر خردن ساعتگرد
pdfjs-page-rotate-ccw-button =
.title = لر خردن پاد ساعتگرد
pdfjs-page-rotate-ccw-button-label = لر خردن پاد ساعتگرد
pdfjs-cursor-text-select-tool-button =
.title = فعال کردن ٱوزار پسند هؽل
pdfjs-cursor-text-select-tool-button-label = ٱوزار پسند هؽل
pdfjs-cursor-hand-tool-button =
.title = فعال کردن ٱوزار دست
pdfjs-cursor-hand-tool-button-label = ٱوزار دست
pdfjs-scroll-page-button =
.title = و کار گرؽڌن اسکرۊل بلگه
pdfjs-scroll-page-button-label = اسکرۊل بلگه
pdfjs-scroll-vertical-button =
.title = و کار گرؽڌن اسکرۊل عمۊدی
pdfjs-scroll-vertical-button-label = اسکرۊل عمۊدی
pdfjs-scroll-horizontal-button =
.title = و کار گرؽڌن اسکرۊل اوفوقی
pdfjs-scroll-horizontal-button-label = اسکرۊل اوفوقی
pdfjs-scroll-wrapped-button =
.title = و کار گرؽڌن اسکرۊل پؽچسته
pdfjs-scroll-wrapped-button-label = اسکرۊل پؽچسته
## Document properties dialog
pdfjs-document-properties-button =
.title = خۊسۊسیات سند…
pdfjs-document-properties-button-label = خۊسۊسیات سند…
pdfjs-document-properties-file-name = نوم فایل:
pdfjs-document-properties-file-size = هندا فایل:
pdfjs-document-properties-title = عونوان:
pdfjs-document-properties-author = هؽل کوݩ:
pdfjs-document-properties-subject = سرتال:
pdfjs-document-properties-creation-date = تاریخ وورکل وابیڌن:
pdfjs-document-properties-modification-date = تاریخ آلشتکاری:
# Variables:
# $dateObj (Date) - the creation/modification date and time of the PDF file
pdfjs-document-properties-date-time-string = { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
pdfjs-document-properties-creator = وورکل کون:
pdfjs-document-properties-producer = وورکل کون PDF:
pdfjs-document-properties-version = نوسخه PDF:
pdfjs-document-properties-page-count = تئداد بلگه یل:
pdfjs-document-properties-page-size = هندا بلگه:
pdfjs-document-properties-page-size-unit-inches = اینچ
pdfjs-document-properties-page-size-unit-millimeters = میلی متر
pdfjs-document-properties-page-size-orientation-portrait = portrait
pdfjs-document-properties-page-size-orientation-landscape = landscape
pdfjs-document-properties-page-size-name-a-three = A3
pdfjs-document-properties-page-size-name-a-four = A4
pdfjs-document-properties-page-size-name-letter = نامه
pdfjs-document-properties-page-size-name-legal = هۊقۊقی
## Variables:
## $width (Number) - the width of the (current) page
## $height (Number) - the height of the (current) page
## $unit (String) - the unit of measurement of the (current) page
## $name (String) - the name of the (current) page
## $orientation (String) - the orientation of the (current) page
pdfjs-document-properties-page-size-dimension-string = { $width } × { $height } { $unit } ({ $orientation })
pdfjs-document-properties-page-size-dimension-name-string = { $width } × { $height } { $unit } ({ $name }, { $orientation })
##
# The linearization status of the document; usually called "Fast Web View" in
# English locales of Adobe software.
pdfjs-document-properties-linearized = نیشتن زل وب:
pdfjs-document-properties-linearized-yes = هری
pdfjs-document-properties-linearized-no = ن
pdfjs-document-properties-close-button = بستن
## Print
pdfjs-print-progress-message = ٱماڌه کردن سند سی چاپ کردن…
# Variables:
# $progress (Number) - percent value
pdfjs-print-progress-percent = { $progress }%
pdfjs-print-progress-close-button = لقو
## Tooltips and alt text for side panel toolbar buttons
pdfjs-toggle-sidebar-button =
.title = آلشت هالت نوار کلی
pdfjs-toggle-sidebar-button-label = آلشت هالت نوار کلی
pdfjs-document-outline-button-label = تئر سند
pdfjs-attachments-button =
.title = نشووݩ داڌن پیوستا
pdfjs-attachments-button-label = پیوستا
pdfjs-layers-button-label = لایه یل
pdfjs-thumbs-button =
.title = نشووݩ داڌن شؽواتا کۊچیر
pdfjs-thumbs-button-label = شؽواتا کۊچیر
pdfjs-findbar-button =
.title = جوستن من سند
pdfjs-findbar-button-label = جوستن
pdfjs-additional-layers = لایه یل ازافه
## Thumbnails panel item (tooltip and alt text for images)
# Variables:
# $page (Number) - the page number
pdfjs-thumb-page-title =
.title = بلگه { $page }
## Find panel button title and messages
pdfjs-find-previous-button-label = دیندایی
pdfjs-find-next-button-label = بئڌی
pdfjs-find-highlight-checkbox = هایلایت کردن پوی
## Predefined zoom values
pdfjs-page-scale-width = پئنا بلگه
pdfjs-page-scale-fit = هندا کردن بلگه
pdfjs-page-scale-auto = زۊم کردن خوتکار
pdfjs-page-scale-actual = هندا واقعی‌
# Variables:
# $scale (Number) - percent value for page scale
pdfjs-page-scale-percent = { $scale }%
## PDF page
# Variables:
# $page (Number) - the page number
pdfjs-page-landmark =
.aria-label = بلگه { $page }
## Annotations
# Variables:
# $dateObj (Date) - the modification date and time of the annotation
pdfjs-annotation-date-time-string = { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
## Password
pdfjs-password-ok-button = خا
@ -24,6 +200,12 @@ pdfjs-password-cancel-button = لقو
## Editing
pdfjs-editor-free-text-button =
.title = هؽل
pdfjs-editor-free-text-button-label = هؽل
pdfjs-editor-ink-button =
.title = کشیڌن
pdfjs-editor-ink-button-label = کشیڌن
pdfjs-editor-stamp-button =
.title = ٱووردن یا آلشت شؽواتا
pdfjs-editor-stamp-button-label = ٱووردن یا آلشت شؽواتا
@ -35,6 +217,14 @@ pdfjs-editor-stamp-editor =
##
# Editor Parameters
pdfjs-editor-free-text-color-input = رنگ
pdfjs-editor-free-text-size-input = هندا
pdfjs-editor-ink-color-input = رنگ
pdfjs-editor-ink-thickness-input = کۊلۊفتی
pdfjs-editor-ink-opacity-input = کر بیڌن
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = کۊلۊفتی
# .default-content is used as a placeholder in an empty text editor.
pdfjs-free-text2 =
.aria-label = آلشتگر هؽل
@ -44,15 +234,55 @@ pdfjs-editor-comments-sidebar-no-comments-link = قلوه دووسته بۊین
## Alt-text dialog
pdfjs-editor-alt-text-cancel-button = لقو
pdfjs-editor-alt-text-save-button = زفت
## Color picker
pdfjs-editor-colorpicker-yellow =
.title = هیل
pdfjs-editor-colorpicker-green =
.title = ساوز
pdfjs-editor-colorpicker-blue =
.title = کوۊ
pdfjs-editor-colorpicker-pink =
.title = آل
pdfjs-editor-colorpicker-red =
.title = سوئر
## Show all highlights
## This is a toggle button to show/hide all the highlights.
pdfjs-editor-highlight-show-all-button-label = نشووݩ داڌن پوی
pdfjs-editor-highlight-show-all-button =
.title = نشووݩ داڌن پوی
## New alt-text dialog
## Group note for entire feature: Alternative text (alt text) helps when people can't see the image. This feature includes a tool to create alt text automatically using an AI model that works locally on the user's device to preserve privacy.
pdfjs-editor-new-alt-text-disclaimer-learn-more-url = قلوه دووسته بۊین
pdfjs-editor-new-alt-text-not-now-button = سکو ن
pdfjs-editor-new-alt-text-error-close-button = بستن
## "Annotations removed" bar
pdfjs-editor-undo-bar-undo-button-label = وورگندن
pdfjs-editor-undo-bar-close-button =
.title = بستن
pdfjs-editor-undo-bar-close-button-label = بستن
## Tab panels
pdfjs-editor-add-signature-draw-thickness-range-label = کۊلۊفتی
## Controls
pdfjs-editor-add-signature-error-close-button = بستن
## Dialog buttons
pdfjs-editor-add-signature-cancel-button = لقو
pdfjs-editor-add-signature-add-button = ٱووردن
pdfjs-editor-edit-signature-update-button = ورۊ رسۊوی
## Comment popup
@ -64,4 +294,32 @@ pdfjs-editor-edit-comment-popup-button =
# An existing comment is edited
pdfjs-editor-edit-comment-dialog-title-when-editing = آلشت منشڌ
pdfjs-editor-edit-comment-dialog-save-button-when-editing = ورۊ رسۊوی
pdfjs-editor-edit-comment-dialog-save-button-when-adding = ٱووردن
pdfjs-editor-edit-comment-dialog-text-input =
.placeholder = ناهاڌن پا هؽل کردن…
pdfjs-editor-edit-comment-dialog-cancel-button = لقو
## The view manager is a sidebar displaying different views:
## - thumbnails;
## - outline;
## - attachments;
## - layers.
## The thumbnails view is used to edit the pdf: remove/insert pages, ...
pdfjs-views-manager-sidebar =
.aria-label = نوار کلی
pdfjs-views-manager-layers-option-label = لایه یل
pdfjs-views-manager-pages-status-action-button-label = دؽوۉداری
pdfjs-views-manager-pages-status-copy-button-label = لف گیری
pdfjs-views-manager-pages-status-cut-button-label = بۊریڌن
pdfjs-views-manager-pages-status-delete-button-label = پاک کردن
pdfjs-views-manager-status-undo-button-label = وورگندن
pdfjs-views-manager-status-done-button-label = ٱنجوم وابی
pdfjs-views-manager-status-close-button =
.title = بستن
pdfjs-views-manager-status-close-button-label = بستن
pdfjs-views-manager-paste-button-label = جا وندن
# Badge used to promote a new feature in the UI, keep it as short as possible.
# It's spelled uppercase for English, but it can be translated as usual.
pdfjs-new-badge-content = نۊ

View File

@ -153,6 +153,29 @@ pdfjs-document-properties-linearized = Rychlé zobrazování z webu:
pdfjs-document-properties-linearized-yes = Ano
pdfjs-document-properties-linearized-no = Ne
pdfjs-document-properties-close-button = Zavřít
pdfjs-digital-signature-properties-view-certificate = Zobrazit certifikát
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Důvod: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Časové razítko: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Podpis ({ $count })
[few] Podpisy ({ $count })
[many] Podpisy ({ $count })
*[other] Podpisy ({ $count })
}
## Print
@ -748,6 +771,84 @@ pdfjs-views-manager-waiting-for-file = Nahrávání souboru…
pdfjs-toggle-views-manager-button1 =
.title = Spravovat strany
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Vlastnosti digitálního podpisu
.aria-label = Vlastnosti digitálního podpisu
pdfjs-digital-signature-properties-button-label = Vlastnosti digitálního podpisu
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokument byl podepsán platným digitálním podpisem
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokument je podepsán, ale { $count } elektronický podpis se nepodařilo ověřit
[few] Dokument je podepsán, ale { $count } elektronické podpisy se nepodařilo ověřit
[many] Dokument je podepsán, ale { $count } elektronických podpisů se nepodařilo ověřit
*[other] Dokument je podepsán, ale { $count } elektronických podpisů se nepodařilo ověřit
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokument podepsaný { $count } certifikátem, který není důvěryhodný
[few] Dokument podepsaný { $count } certifikáty, které nejsou důvěryhodné
[many] Dokument podepsaný { $count } certifikáty, které nejsou důvěryhodné
*[other] Dokument podepsaný { $count } certifikáty, které nejsou důvěryhodné
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokument je podepsaný { $count } prošlým certifikátem
[few] Dokument je podepsaný { $count } prošlými certifikáty
[many] Dokument je podepsaný { $count } prošlými certifikáty
*[other] Dokument je podepsaný { $count } prošlými certifikáty
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokument má { $count } neplatný elektronický podpis
[few] Dokument má { $count } neplatné elektronické podpisy
[many] Dokument má { $count } neplatných elektronických podpisů
*[other] Dokument má { $count } neplatných elektronických podpisů
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokument je podepsaný { $count } zneplatněným certifikátem
[few] Dokument je podepsaný { $count } zneplatněnými certifikáty
[many] Dokument je podepsaný { $count } zneplatněnými certifikáty
*[other] Dokument je podepsaný { $count } zneplatněnými certifikáty
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Stav: Podpis ověřen
pdfjs-digital-signature-properties-status-invalid = Stav: Podpis je neplatný
pdfjs-digital-signature-properties-status-unknown = Stav: Nelze ověřit (nepodporováno)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certifikát: Důvěryhodný ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certifikát: nedostupný
pdfjs-digital-signature-properties-certificate-untrusted = Certifikát: nedůvěryhodný
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certifikát: Neznámý vydavatel ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certifikát: Self-signed ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certifikát: Nedůvěryhodný vydavatel ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certifikát: vypršel
pdfjs-digital-signature-properties-certificate-expired-with-date = Certifikát: Vypršel ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certifikát: zneplatněn
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,31 @@ pdfjs-document-properties-linearized = Golwg Gwe Cyflym:
pdfjs-document-properties-linearized-yes = Iawn
pdfjs-document-properties-linearized-no = Na
pdfjs-document-properties-close-button = Cau
pdfjs-digital-signature-properties-view-certificate = Gweld tystysgrif
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Rheswm: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Stamp amser: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[zero] Is-lofnodion ( { $count } )
[one] Is-lofnodion ( { $count } )
[two] Is-lofnodion ( { $count } )
[few] Is-lofnodion ( { $count } )
[many] Is-lofnodion ( { $count } )
*[other] Is-lofnodion ( { $count } )
}
## Print
@ -764,6 +789,94 @@ pdfjs-views-manager-waiting-for-file = Yn llwytho ffeil i fyny…
pdfjs-toggle-views-manager-button1 =
.title = Rheoli tudalennau
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Priodweddau llofnod digidol
.aria-label = Priodweddau llofnod digidol
pdfjs-digital-signature-properties-button-label = Priodweddau llofnod digidol
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Llofnodwyd y ddogfen gyda llofnod digidol dilys
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[zero] Llofnodwyd y ddogfen ond doedd dim modd dilysu { $count } llofnod digidol
[one] Llofnodwyd y ddogfen ond doedd dim modd dilysu { $count } llofnod digidol
[two] Llofnodwyd y ddogfen ond doedd dim modd dilysu { $count } llofnod digidol
[few] Llofnodwyd y ddogfen ond doedd dim modd dilysu { $count } llofnod digidol
[many] Llofnodwyd y ddogfen ond doedd dim modd dilysu { $count } llofnod digidol
*[other] Llofnodwyd y ddogfen ond doedd dim modd dilysu { $count } llofnod digidol
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[zero] Dogfen wedi'i llofnodi â { $count } thystysgrif does dim modd ymddiried ynddyn nhw
[one] Dogfen wedi'i llofnodi â { $count } thystysgrif does dim modd ymddiried ynddi
[two] Dogfen wedi'i llofnodi â { $count } thystysgrifau does dim modd ymddiried ynddyn nhw
[few] Dogfen wedi'i llofnodi â { $count } thystysgrifau does dim modd ymddiried ynddyn nhw
[many] Dogfen wedi'i llofnodi â { $count } thystysgrifau does dim modd ymddiried ynddyn nhw
*[other] Dogfen wedi'i llofnodi â { $count } thystysgrifau does dim modd ymddiried ynddyn nhw
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[zero] Dogfen wedi'i llofnodi gyda { $count } tystysgrifau sydd wedi dod i ben
[one] Dogfen wedi'i llofnodi gydag { $count } dystysgrif sydd wedi dod i ben
[two] Dogfen wedi'i llofnodi gyda { $count } dystysgrif sydd wedi dod i ben
[few] Dogfen wedi'i llofnodi gyda { $count } tystysgrif sydd wedi dod i ben
[many] Dogfen wedi'i llofnodi gyda { $count } thystysgrif sydd wedi dod i ben
*[other] Dogfen wedi'i llofnodi gyda { $count } tystysgrif sydd wedi dod i ben
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[zero] Mae gan y ddogfen { $count } llofnodion digidol annilys
[one] Mae gan y ddogfen { $count } llofnod digidol annilys
[two] Mae gan y ddogfen { $count } llofnod digidol annilys
[few] Mae gan y ddogfen { $count } llofnod digidol annilys
[many] Mae gan y ddogfen { $count } llofnod digidol annilys
*[other] Mae gan y ddogfen { $count } llofnod digidol annilys
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[zero] Dogfen wedi'i llofnodi gyda { $count } tystysgrifau wedi'u dirymu
[one] Dogfen wedi'i llofnodi gyda { $count } tystysgrif wedi'u dirymu
[two] Dogfen wedi'i llofnodi gyda { $count } tystysgrif wedi'u dirymu
[few] Dogfen wedi'i llofnodi gyda { $count } tystysgrif wedi'u dirymu
[many] Dogfen wedi'i llofnodi gyda { $count } thystysgrif wedi'u dirymu
*[other] Dogfen wedi'i llofnodi gyda { $count } tystysgrif wedi'u dirymu
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Statws: Llofnod wedi'i ddilysu
pdfjs-digital-signature-properties-status-invalid = Statws: Llofnod annilys
pdfjs-digital-signature-properties-status-unknown = Statws: Methu dilysu (heb ei gefnogi)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Tystysgrif: Wedi ymddiried ( { $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Tystysgrif: Ddim ar gael
pdfjs-digital-signature-properties-certificate-untrusted = Tystysgrif: Dim ymddiriedaeth
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Tystysgrif: Cyhoeddwr anhysbys ( { $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Tystysgrif: Hunan-lofnod ( { $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Tystysgrif: Cyhoeddwr heb ymddiriedaeth ( { $issuer })
pdfjs-digital-signature-properties-certificate-expired = Tystysgrif: Wedi dod i ben
pdfjs-digital-signature-properties-certificate-expired-with-date = Tystysgrif: Wedi dod i ben ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Tystysgrif: Wedi'i ddirymu
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -660,7 +660,10 @@ pdfjs-views-manager-view-selector-button =
pdfjs-views-manager-view-selector-button-label = Visninger
pdfjs-views-manager-pages-title = Sider
pdfjs-views-manager-attachments-title = Vedhæftede filer
pdfjs-views-manager-layers-title1 = Lag
.title = Lag (dobbeltklik for at nulstille alle lag til standard-tilstanden)
pdfjs-views-manager-pages-option-label = Sider
pdfjs-views-manager-outlines-option-label = Dokument-disposition
pdfjs-views-manager-attachments-option-label = Vedhæftede filer
pdfjs-views-manager-layers-option-label = Lag
pdfjs-views-manager-add-file-button =
@ -678,6 +681,7 @@ pdfjs-views-manager-pages-status-action-button-label = Håndter
pdfjs-views-manager-pages-status-copy-button-label = Kopier
pdfjs-views-manager-pages-status-cut-button-label = Klip
pdfjs-views-manager-pages-status-delete-button-label = Slet
pdfjs-views-manager-pages-status-export-selected-button-label = Eksporter valgte…
# Variables:
# $count (Number) - the number of selected pages to be cut.
pdfjs-views-manager-status-undo-cut-label =
@ -699,6 +703,8 @@ pdfjs-views-manager-pages-status-undo-delete-label =
[one] 1 side slettet
*[other] { $count } sider slettet
}
pdfjs-views-manager-pages-status-waiting-ready-label = Gør din fil klar…
pdfjs-views-manager-pages-status-waiting-uploading-label = Uploader fil…
pdfjs-views-manager-status-undo-button-label = Fortryd
pdfjs-views-manager-status-done-button-label = Færdig
pdfjs-views-manager-status-close-button =
@ -711,6 +717,10 @@ pdfjs-views-manager-paste-button-before =
# $page (Number) - the page number after which the paste button is.
pdfjs-views-manager-paste-button-after =
.title = Indsæt efter side { $page }
# Badge used to promote a new feature in the UI, keep it as short as possible.
# It's spelled uppercase for English, but it can be translated as usual.
pdfjs-new-badge-content = NY
pdfjs-views-manager-waiting-for-file = Uploader fil…
pdfjs-toggle-views-manager-button1 =
.title = Håndter sider

View File

@ -67,8 +67,8 @@ pdfjs-page-rotate-cw-button =
.title = Im Uhrzeigersinn drehen
pdfjs-page-rotate-cw-button-label = Im Uhrzeigersinn drehen
pdfjs-page-rotate-ccw-button =
.title = Gegen Uhrzeigersinn drehen
pdfjs-page-rotate-ccw-button-label = Gegen Uhrzeigersinn drehen
.title = Gegen den Uhrzeigersinn drehen
pdfjs-page-rotate-ccw-button-label = Gegen den Uhrzeigersinn drehen
pdfjs-cursor-text-select-tool-button =
.title = Textauswahl-Werkzeug aktivieren
pdfjs-cursor-text-select-tool-button-label = Textauswahl-Werkzeug
@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Schnelle Webanzeige:
pdfjs-document-properties-linearized-yes = Ja
pdfjs-document-properties-linearized-no = Nein
pdfjs-document-properties-close-button = Schließen
pdfjs-digital-signature-properties-view-certificate = Zertifikat ansehen
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Grund: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Zeitstempel: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] ({ $count }) Untersignatur
*[other] ({ $count }) Untersignaturen
}
## Print
@ -278,7 +299,7 @@ pdfjs-rendering-error = Beim Darstellen der Seite trat ein Fehler auf.
# (32000-1:2008 Table 169 Annotation types).
# Some common types are e.g.: "Check", "Text", "Comment", "Note"
pdfjs-text-annotation-type =
.alt = [Anlage: { $type }]
.alt = [{ $type } Anmerkung]
# Variables:
# $dateObj (Date) - the modification date and time of the annotation
pdfjs-annotation-date-time-string = { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
@ -605,7 +626,7 @@ pdfjs-editor-add-signature-save-checkbox = Unterschrift speichern
pdfjs-editor-add-signature-save-warning-message = Sie haben die Grenze von 5 gespeicherten Unterschriften erreicht. Entfernen Sie eine, um weitere zu speichern.
pdfjs-editor-add-signature-image-upload-error-title = Grafik konnte nicht hochgeladen werden
pdfjs-editor-add-signature-image-upload-error-description = Überprüfen Sie Ihre Netzwerkverbindung, oder versuchen Sie es mit einer anderen Grafik.
pdfjs-editor-add-signature-image-no-data-error-title = Kann Grafik nicht in eine Signatur umwandeln
pdfjs-editor-add-signature-image-no-data-error-title = Kann Grafik nicht in eine Unterschrift umwandeln
pdfjs-editor-add-signature-image-no-data-error-description = Bitte versuchen Sie, eine andere Grafik hochzuladen.
pdfjs-editor-add-signature-error-close-button = Schließen
@ -709,9 +730,9 @@ pdfjs-views-manager-pages-status-undo-delete-label =
}
pdfjs-views-manager-pages-status-waiting-ready-label = Ihre Datei wird vorbereitet…
pdfjs-views-manager-pages-status-waiting-uploading-label = Datei wird hochgeladen…
pdfjs-views-manager-status-warning-cut-label = Ausschneiden war nicht möglich. Aktualisieren Sie die Seite und versuchen Sie es erneut.
pdfjs-views-manager-status-warning-cut-label = Ausschneiden nicht möglich. Aktualisieren Sie die Seite und versuchen Sie es erneut.
pdfjs-views-manager-status-warning-copy-label = Kopieren nicht möglich. Aktualisieren Sie die Seite und versuchen Sie es erneut.
pdfjs-views-manager-status-warning-delete-label = Löschen war nicht möglich. Aktualisieren Sie die Seite und versuchen Sie es erneut.
pdfjs-views-manager-status-warning-delete-label = Löschen nicht möglich. Aktualisieren Sie die Seite und versuchen Sie es erneut.
pdfjs-views-manager-status-warning-save-label = Speichern nicht möglich. Aktualisieren Sie die Seite und versuchen Sie es erneut.
pdfjs-views-manager-status-undo-button-label = Rückgängig
pdfjs-views-manager-status-done-button-label = Fertig
@ -732,11 +753,79 @@ pdfjs-views-manager-waiting-for-file = Datei wird hochgeladen…
pdfjs-toggle-views-manager-button1 =
.title = Seiten verwalten
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Eigenschaften digitaler Signatur
.aria-label = Eigenschaften digitaler Signatur
pdfjs-digital-signature-properties-button-label = Eigenschaften digitaler Signatur
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokument wurde mit einer gültigen digitalen Signatur signiert
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokument signiert, aber { $count } digitale Signatur konnte nicht verifiziert werden
*[other] Dokument signiert, aber { $count } digitale Signaturen konnten nicht verifiziert werden
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokument mit { $count } Zertifikat signiert, das nicht vertrauenswürdig ist
*[other] Dokument mit { $count } Zertifikaten signiert, die nicht vertrauenswürdig sind
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokument mit { $count } abgelaufenen Zertifikat signiert
*[other] Dokument mit { $count } abgelaufenen Zertifikaten signiert
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokument hat { $count } ungültige digitale Signatur
*[other] Dokument hat { $count } ungültige digitale Signaturen
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokument mit { $count } gesperrten Zertifikat signiert
*[other] Dokument mit { $count } gesperrten Zertifikaten signiert
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: Signatur überprüft
pdfjs-digital-signature-properties-status-invalid = Status: Signatur ungültig
pdfjs-digital-signature-properties-status-unknown = Status: Verifizieren nicht möglich (nicht unterstützt)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Zertifikat: Vertrauenswürdig ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Zertifikat: Nicht verfügbar
pdfjs-digital-signature-properties-certificate-untrusted = Zertifikat: Nicht vertrauenswürdig
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Zertifikat: Unbekannter Aussteller ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Zertifikat: Selbstsigniert ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Zertifikat: Nicht vertrauenswürdiger Aussteller ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Zertifikat: Abgelaufen
pdfjs-digital-signature-properties-certificate-expired-with-date = Zertifikat: Abgelaufen ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Zertifikat: Widerrufen
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =
.title = Gespeicherte Signatur entfernen
pdfjs-editor-delete-signature-button-label1 = Gespeicherte Signatur entfernen
.title = Gespeicherte Unterschrift entfernen
pdfjs-editor-delete-signature-button-label1 = Gespeicherte Unterschrift entfernen
## Editor toolbar

View File

@ -153,6 +153,29 @@ pdfjs-document-properties-linearized = Fast Web View:
pdfjs-document-properties-linearized-yes = Jo
pdfjs-document-properties-linearized-no = Ně
pdfjs-document-properties-close-button = Zacyniś
pdfjs-digital-signature-properties-view-certificate = Certifikat pokazaś
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Pśicyna: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Casowy kołk: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] { $count } pódsignatura
[two] { $count } pódsignaturje
[few] { $count } pódsignatury
*[other] { $count } pódsignaturow
}
## Print
@ -748,6 +771,84 @@ pdfjs-views-manager-waiting-for-file = Dataja se nagrawa…
pdfjs-toggle-views-manager-button1 =
.title = Boki zastojaś
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Kakosći digitalneje signatury
.aria-label = Kakosći digitalneje signatury
pdfjs-digital-signature-properties-button-label = Kakosći digitalneje signatury
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokument jo se signěrował z płaśiweju digitalneju signaturu
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokument jo se signěrował, ale { $count } digitalna signatura njedajo se wobkšuśiś
[two] Dokument jo se signěrował, ale { $count } digitalnej signaturje njedajotej se wobkšuśiś
[few] Dokument jo se signěrował, ale { $count } digitalne signatury njedaju se wobkšuśiś
*[other] Dokument jo se signěrował, ale { $count } digitalnych signaturow njedajo se wobkšuśiś
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokument jo z { $count } certifikatom signěrowany, kótaryž njejo dowěry gódny
[two] Dokument jo z { $count } certifikatoma signěrowany, kótarejž njejstej dowěry gódnej
[few] Dokument jo z { $count } certifikatami signěrowany, kótarež njejsu dowěry gódne
*[other] Dokument jo z { $count } certifikatami signěrowany, kótarež njejsu dowěry gódne
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokument jo z { $count } spadnjonym certifikatom signěrowany
[two] Dokument jo z { $count } spadnjonyma certifikatoma signěrowany
[few] Dokument jo z { $count } spadnjonymi certifikatami signěrowany
*[other] Dokument jo z { $count } spadnjonymi certifikatami signěrowany
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokument ma { $count } njepłaśiwu digitalnu signaturu
[two] Dokument ma { $count } njepłaśiwej digitalnej signaturje
[few] Dokument ma { $count } njepłaśiwe digitalne signatury
*[other] Dokument ma { $count } njepłaśiwych digitalnych signaturow
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokument jo z { $count } wótwołanym certifikatom signěrowany
[two] Dokument jo z { $count } wótwołanyma certifikatoma signěrowany
[few] Dokument jo z { $count } wótwołanymi certifikatami signěrowany
*[other] Dokument jo z { $count } wótwołanymi certifikatami signěrowany
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: Signatura jo wobkšuśona
pdfjs-digital-signature-properties-status-invalid = Status: Signatura jo njepłaśiwa
pdfjs-digital-signature-properties-status-unknown = Status: Njedajo se wobkšuśiś (njepódpěra se)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certifikat: Dowěry gódny ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certifikat: Nic k dispoziciji
pdfjs-digital-signature-properties-certificate-untrusted = Certifikat: Dowěry njegódny
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certifikat: Njeznaty wudawaŕ ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certifikat: Samsigněrowany ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certifikat: Dowěry njegódny wudawaŕ ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certifikat: Spadnjony
pdfjs-digital-signature-properties-certificate-expired-with-date = Certifikat: Spadnjony ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certifikat: Wótwołany
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Ταχεία προβολή ιστού:
pdfjs-document-properties-linearized-yes = Ναι
pdfjs-document-properties-linearized-no = Όχι
pdfjs-document-properties-close-button = Κλείσιμο
pdfjs-digital-signature-properties-view-certificate = Προβολή πιστοποιητικού
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Αιτία: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Χρονοσήμανση: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Δευτερεύουσα υπογραφή ({ $count })
*[other] Δευτερεύουσες υπογραφές ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Μεταφόρτωση αρχείου…
pdfjs-toggle-views-manager-button1 =
.title = Διαχείριση σελίδων
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Ιδιότητες ψηφιακής υπογραφής
.aria-label = Ιδιότητες ψηφιακής υπογραφής
pdfjs-digital-signature-properties-button-label = Ιδιότητες ψηφιακής υπογραφής
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Το έγγραφο έχει υπογραφεί με έγκυρη ψηφιακή υπογραφή
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Το έγγραφο έχει υπογραφεί, αλλά δεν ήταν δυνατή η επαλήθευση { $count } ψηφιακής υπογραφής
*[other] Το έγγραφο έχει υπογραφεί, αλλά δεν ήταν δυνατή η επαλήθευση { $count } ψηφιακών υπογραφών
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Το έγγραφο έχει υπογραφεί με { $count } πιστοποιητικό που δεν είναι αξιόπιστο
*[other] Το έγγραφο έχει υπογραφεί με { $count } πιστοποιητικά που δεν είναι αξιόπιστα
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Το έγγραφο έχει υπογραφεί με { $count } ληγμένο πιστοποιητικό
*[other] Το έγγραφο έχει υπογραφεί με { $count } ληγμένα πιστοποιητικά
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Το έγγραφο διαθέτει { $count } μη έγκυρη ψηφιακή υπογραφή
*[other] Το έγγραφο διαθέτει { $count } μη έγκυρες ψηφιακές υπογραφές
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Το έγγραφο έχει υπογραφεί με { $count } ανακληθέν πιστοποιητικό
*[other] Το έγγραφο έχει υπογραφεί με { $count } ανακληθέντα πιστοποιητικά
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Κατάσταση: Επαληθευμένη υπογραφή
pdfjs-digital-signature-properties-status-invalid = Κατάσταση: Μη έγκυρη υπογραφή
pdfjs-digital-signature-properties-status-unknown = Κατάσταση: Αδυναμία επαλήθευσης (δεν υποστηρίζεται)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Πιστοποιητικό: Έμπιστο ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Πιστοποιητικό: Μη διαθέσιμο
pdfjs-digital-signature-properties-certificate-untrusted = Πιστοποιητικό: Μη αξιόπιστο
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Πιστοποιητικό: Άγνωστος εκδότης ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Πιστοποιητικό: Αυτοϋπογεγραμμένο ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Πιστοποιητικό: Μη αξιόπιστος εκδότης ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Πιστοποιητικό: Έχει λήξει
pdfjs-digital-signature-properties-certificate-expired-with-date = Πιστοποιητικό: Έχει λήξει ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Πιστοποιητικό: Έχει ανακληθεί
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Fast Web View:
pdfjs-document-properties-linearized-yes = Yes
pdfjs-document-properties-linearized-no = No
pdfjs-document-properties-close-button = Close
pdfjs-digital-signature-properties-view-certificate = View certificate
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Reason: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Timestamp: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Sub-signature ({ $count })
*[other] Sub-signatures ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Uploading file…
pdfjs-toggle-views-manager-button1 =
.title = Manage pages
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Digital signature properties
.aria-label = Digital signature properties
pdfjs-digital-signature-properties-button-label = Digital signature properties
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Document was signed with a valid digital signature
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Document signed but { $count } digital signature could not be verified
*[other] Document signed but { $count } digital signatures could not be verified
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Document signed with { $count } certificate that is not trusted
*[other] Document signed with { $count } certificates that are not trusted
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Document signed with { $count } expired certificate
*[other] Document signed with { $count } expired certificates
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Document has { $count } invalid digital signature
*[other] Document has { $count } invalid digital signatures
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Document signed with { $count } revoked certificate
*[other] Document signed with { $count } revoked certificates
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: Signature verified
pdfjs-digital-signature-properties-status-invalid = Status: Signature invalid
pdfjs-digital-signature-properties-status-unknown = Status: Unable to verify (unsupported)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certificate: Trusted ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certificate: Unavailable
pdfjs-digital-signature-properties-certificate-untrusted = Certificate: Untrusted
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certificate: Unknown issuer ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certificate: Self-signed ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certificate: Untrusted issuer ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certificate: Expired
pdfjs-digital-signature-properties-certificate-expired-with-date = Certificate: Expired ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certificate: Revoked
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -785,3 +785,96 @@ pdfjs-views-manager-paste-button-after =
pdfjs-new-badge-content = NEW
pdfjs-views-manager-waiting-for-file = Uploading file…
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Digital signature properties
.aria-label = Digital signature properties
pdfjs-digital-signature-properties-button-label = Digital signature properties
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Document was signed with a valid digital signature
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Document signed but { $count } digital signature could not be verified
*[other] Document signed but { $count } digital signatures could not be verified
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Document signed with { $count } certificate that is not trusted
*[other] Document signed with { $count } certificates that are not trusted
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Document signed with { $count } expired certificate
*[other] Document signed with { $count } expired certificates
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Document has { $count } invalid digital signature
*[other] Document has { $count } invalid digital signatures
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Document signed with { $count } revoked certificate
*[other] Document signed with { $count } revoked certificates
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: Signature verified
pdfjs-digital-signature-properties-status-invalid = Status: Signature invalid
pdfjs-digital-signature-properties-status-unknown = Status: Unable to verify (unsupported)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certificate: Trusted ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certificate: Unavailable
pdfjs-digital-signature-properties-certificate-untrusted = Certificate: Untrusted
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certificate: Unknown issuer ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certificate: Self-signed ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certificate: Untrusted issuer ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certificate: Expired
pdfjs-digital-signature-properties-certificate-expired-with-date = Certificate: Expired ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certificate: Revoked
##
pdfjs-digital-signature-properties-view-certificate = View certificate
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Reason: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Timestamp: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Sub-signature ({ $count })
*[other] Sub-signatures ({ $count })
}

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Rapida tekstaĵa vido:
pdfjs-document-properties-linearized-yes = Jes
pdfjs-document-properties-linearized-no = Ne
pdfjs-document-properties-close-button = Fermi
pdfjs-digital-signature-properties-view-certificate = Vidi atestilon
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Kialo: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Tempindiko: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Duaranga subskribo ({ $count })
*[other] Duarangaj subskriboj ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Dosiero alŝutata…
pdfjs-toggle-views-manager-button1 =
.title = Administri paĝojn
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Atributoj de cifereca subskribo
.aria-label = Atributoj de cifereca subskribo
pdfjs-digital-signature-properties-button-label = Atributoj de cifereca subskribo
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = La dokumento estis subskribita de valida cifereca subskribo
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokumento subskribita, tamen { $count } cifereca subskribo ne povis esti kontrolita
*[other] Dokumento subskribita, tamen { $count } ciferecaj subskriboj ne povis esti kontrolita
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokumento subskribita de { $count } nefidata atestilo
*[other] Dokumento subskribita de { $count } nefidataj atestiloj
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokumento subskribita de { $count } senvalidiĝinta atestilo
*[other] Dokumento subskribita de { $count } senvalidiĝintaj atestiloj
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] La dokumento havas { $count } nevalidan ciferecan subskribon
*[other] La dokumento havas { $count } nevalidajn ciferecajn subskribojn
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokumento subskribita de { $count } senvalidigita atestilo
*[other] Dokumento subskribita de { $count } senvalidigitaj atestiloj
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Stato: Subskribo kontrolita
pdfjs-digital-signature-properties-status-invalid = Stato: Subskribo nevalida
pdfjs-digital-signature-properties-status-unknown = Stato: Ne eblas kontroli (nesubtenata)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Atestilo: Fidata ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Atestilo: Nedisponebla
pdfjs-digital-signature-properties-certificate-untrusted = Atestilo: Ne fidata
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Atestilo: Nekonata eldoninto ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Atestilo: Memsubskribita ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Atestilo: Nefidata eldoninto ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Atestilo: Senvalidiĝinta
pdfjs-digital-signature-properties-certificate-expired-with-date = Atestilo: Senvalidiĝinta ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Atestilo: Senvalidigita
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Vista rápida de la Web:
pdfjs-document-properties-linearized-yes = Sí
pdfjs-document-properties-linearized-no = No
pdfjs-document-properties-close-button = Cerrar
pdfjs-digital-signature-properties-view-certificate = Ver certificado
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Razón: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Fecha: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Subfirma ({ $count })
*[other] Subfirmas ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Subiendo archivo…
pdfjs-toggle-views-manager-button1 =
.title = Administrar páginas
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Propiedades de firma digital
.aria-label = Propiedades de firma digital
pdfjs-digital-signature-properties-button-label = Propiedades de firma digital
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = El documento fue firmado con una firma digital válida
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Documento firmado pero { $count } firma digital no pudo ser verificada
*[other] Documento firmado pero { $count } firmas digitales no pudieron ser verificadas
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Documento firmado con { $count } certificado que no es confiable
*[other] Documento firmado con { $count } certificados que no son confiables
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Documento firmado con { $count } certificado expirado
*[other] Documento firmado con { $count } certificado expirado
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] El documento tiene { $count } firmas digital inválida
*[other] El documento tiene { $count } firmas digitales inválidas
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Documento firmado con { $count } certificado revocado
*[other] Documento firmado con { $count } certificados revocados
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Estado: Firma verificada
pdfjs-digital-signature-properties-status-invalid = Estado: Firma inválida
pdfjs-digital-signature-properties-status-unknown = Estado: No se puede verificar (no soportada)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certificado: Confiable ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certificado: No disponible
pdfjs-digital-signature-properties-certificate-untrusted = Certificado: No confiable
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certificado: Emisor desconocido ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certificado: Autofirmado ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certificado: Emisor no confiable ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certificado: Vencido
pdfjs-digital-signature-properties-certificate-expired-with-date = Certificado: Vencido ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certificado: Revocado
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Vista rápida en Web:
pdfjs-document-properties-linearized-yes = Sí
pdfjs-document-properties-linearized-no = No
pdfjs-document-properties-close-button = Cerrar
pdfjs-digital-signature-properties-view-certificate = Ver certificado
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Motivo: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Marca de tiempo: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Subfirma ({ $count })
*[other] Subfirmas ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Subiendo archivo…
pdfjs-toggle-views-manager-button1 =
.title = Gestionar páginas
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Propiedades de firma digital
.aria-label = Propiedades de firma digital
pdfjs-digital-signature-properties-button-label = Propiedades de firma digital
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = El documento fue firmado con una firma digital válida
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Documento firmado, pero no se pudo verificar la firma digital
*[other] Documento firmado, pero no se pudieron verificar las { $count } firmas digitales
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Documento firmado con { $count } certificado que no es de confianza
*[other] Documento firmado con { $count } certificados que no son de confianza
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Documento firmado con { $count } certificado expirado
*[other] Documento firmado con { $count } certificados expirados
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] El documento tiene { $count } firma digital no válida
*[other] El documento tiene { $count } firmas digitales no válidas
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Documento firmado con { $count } certificado revocado
*[other] Documento firmado con { $count } certificados revocados
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Estado: Firma verificada
pdfjs-digital-signature-properties-status-invalid = Estado: Firma inválida
pdfjs-digital-signature-properties-status-unknown = Estado: No se puede verificar (no compatible)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certificado: Confiable ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certificado: No disponible
pdfjs-digital-signature-properties-certificate-untrusted = Certificado: No confiable
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certificado: Emisor desconocido ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certificado: Autofirmado ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certificado: Emisor no confiable ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certificado: Expirado
pdfjs-digital-signature-properties-certificate-expired-with-date = Certificado: Expirado ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certificado: Revocado
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,7 @@ pdfjs-document-properties-linearized = Vista rápida de la web:
pdfjs-document-properties-linearized-yes = Sí
pdfjs-document-properties-linearized-no = No
pdfjs-document-properties-close-button = Cerrar
pdfjs-digital-signature-properties-view-certificate = Ver certificado
## Print
@ -161,8 +162,8 @@ pdfjs-print-progress-message = Preparando documento para impresión…
# $progress (Number) - percent value
pdfjs-print-progress-percent = { $progress }%
pdfjs-print-progress-close-button = Cancelar
pdfjs-printing-not-supported = Advertencia: La impresión no esta completamente soportada por este navegador.
pdfjs-printing-not-ready = Advertencia: El PDF no cargo completamente para impresión.
pdfjs-printing-not-supported = Advertencia: La impresión no está completamente soportada por este navegador.
pdfjs-printing-not-ready = Advertencia: El PDF no cargó completamente para impresión.
## Tooltips and alt text for side panel toolbar buttons
@ -265,7 +266,7 @@ pdfjs-page-landmark =
## Loading indicator messages
pdfjs-loading-error = Un error ocurrió al cargar el PDF.
pdfjs-invalid-file-error = Archivo PDF invalido o dañado.
pdfjs-invalid-file-error = Archivo PDF inválido o dañado.
pdfjs-missing-file-error = Archivo PDF no encontrado.
pdfjs-unexpected-response-error = Respuesta inesperada del servidor.
pdfjs-rendering-error = Un error ocurrió al renderizar la página.
@ -360,7 +361,7 @@ pdfjs-editor-remove-signature-button =
pdfjs-editor-free-text-color-input = Color
pdfjs-editor-free-text-size-input = Tamaño
pdfjs-editor-ink-color-input = Color
pdfjs-editor-ink-thickness-input = Grossor
pdfjs-editor-ink-thickness-input = Grosor
pdfjs-editor-ink-opacity-input = Opacidad
pdfjs-editor-stamp-add-image-button =
.title = Agregar imagen
@ -580,7 +581,7 @@ pdfjs-editor-add-signature-type-input =
.aria-label = Escribe tu firma
.placeholder = Escribe tu firma
pdfjs-editor-add-signature-draw-placeholder = Dibuja tu firma
pdfjs-editor-add-signature-draw-thickness-range-label = Grossor
pdfjs-editor-add-signature-draw-thickness-range-label = Grosor
# Variables:
# $thickness (Number) - the thickness (in pixels) of the line used to draw a signature.
pdfjs-editor-add-signature-draw-thickness-range =
@ -697,15 +698,15 @@ pdfjs-views-manager-status-undo-cut-label =
# $count (Number) - the number of selected pages to be copied.
pdfjs-views-manager-pages-status-undo-copy-label =
{ $count ->
[one] 1 pagina copiada
*[other] { $count } paginas copiadas
[one] 1 página copiada
*[other] { $count } páginas copiadas
}
# Variables:
# $count (Number) - the number of selected pages to be deleted.
pdfjs-views-manager-pages-status-undo-delete-label =
{ $count ->
[one] 1 pagina eliminada
*[other] { $count } paginas eliminadas
[one] 1 página eliminada
*[other] { $count } páginas eliminadas
}
pdfjs-views-manager-pages-status-waiting-ready-label = Preparando tu archivo…
pdfjs-views-manager-pages-status-waiting-uploading-label = Subiendo archivo…

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Webeko ikuspegi bizkorra:
pdfjs-document-properties-linearized-yes = Bai
pdfjs-document-properties-linearized-no = Ez
pdfjs-document-properties-close-button = Itxi
pdfjs-digital-signature-properties-view-certificate = Ikusi ziurtagiria
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Arrazoia: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Denbora-marka: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Azpi-sinadura ({ $count })
*[other] Azpi-sinadurak ({ $count })
}
## Print
@ -401,11 +422,11 @@ pdfjs-editor-comments-sidebar-no-comments-link = Argibide gehiago
## Alt-text dialog
pdfjs-editor-alt-text-button-label = Testu alternatiboa
pdfjs-editor-alt-text-button-label = Ordezko testua
pdfjs-editor-alt-text-edit-button =
.aria-label = Editatu testu alternatiboa
.aria-label = Editatu ordezko testua
pdfjs-editor-alt-text-dialog-label = Aukeratu aukera
pdfjs-editor-alt-text-dialog-description = Testu alternatiboak laguntzen du jendeak ezin duenean irudia ikusi edo ez denean kargatzen.
pdfjs-editor-alt-text-dialog-description = Ordezko testuak laguntzen du jendeak ezin duenean irudia ikusi edo ez denean kargatzen.
pdfjs-editor-alt-text-add-description-label = Gehitu azalpena
pdfjs-editor-alt-text-add-description-description = Saiatu idazten gaia, ezarpena edo ekintzak deskribatzen dituen esaldi 1 edo 2.
pdfjs-editor-alt-text-mark-decorative-label = Markatu apaingarri gisa
@ -418,7 +439,7 @@ pdfjs-editor-alt-text-textarea =
.placeholder = Adibidez, "gizon gaztea mahaian eserita dago bazkaltzeko"
# Alternative text (alt text) helps when people can't see the image.
pdfjs-editor-alt-text-button =
.aria-label = Testu alternatiboa
.aria-label = Ordezko testua
## Editor resizers
## This is used in an aria label to help to understand the role of the resizer.
@ -470,38 +491,38 @@ pdfjs-editor-highlight-show-all-button =
## Group note for entire feature: Alternative text (alt text) helps when people can't see the image. This feature includes a tool to create alt text automatically using an AI model that works locally on the user's device to preserve privacy.
# Modal header positioned above a text box where users can edit the alt text.
pdfjs-editor-new-alt-text-dialog-edit-label = Editatu testu alternatiboa (irudiaren azalpena)
pdfjs-editor-new-alt-text-dialog-edit-label = Editatu ordezko testua (irudiaren azalpena)
# Modal header positioned above a text box where users can add the alt text.
pdfjs-editor-new-alt-text-dialog-add-label = Gehitu testu alternatiboa (irudiaren azalpena)
pdfjs-editor-new-alt-text-dialog-add-label = Gehitu ordezko testua (irudiaren azalpena)
pdfjs-editor-new-alt-text-textarea =
.placeholder = Idatzi zure azalpena hemen…
# This text refers to the alt text box above this description. It offers a definition of alt text.
pdfjs-editor-new-alt-text-description = Azalpen laburra irudia ikusi ezin duen jendearentzat edo irudia kargatu ezin denerako.
# This is a required legal disclaimer that refers to the automatically created text inside the alt text box above this text. It disappears if the text is edited by a human.
pdfjs-editor-new-alt-text-disclaimer1 = Testu alternatibo hau automatikoki sortu da eta okerra izan liteke.
pdfjs-editor-new-alt-text-disclaimer1 = Ordezko testu hau automatikoki sortu da eta okerra izan liteke.
pdfjs-editor-new-alt-text-disclaimer-learn-more-url = Argibide gehiago
pdfjs-editor-new-alt-text-create-automatically-button-label = Sortu testu alternatiboa automatikoki
pdfjs-editor-new-alt-text-create-automatically-button-label = Sortu ordezko testua automatikoki
pdfjs-editor-new-alt-text-not-now-button = Une honetan ez
pdfjs-editor-new-alt-text-error-title = Ezin da testu alternatiboa automatikoki sortu
pdfjs-editor-new-alt-text-error-description = Idatzi zure testu alternatibo propioa edo saiatu berriro geroago.
pdfjs-editor-new-alt-text-error-title = Ezin da ordezko testua automatikoki sortu
pdfjs-editor-new-alt-text-error-description = Idatzi zure ordezko testu propioa edo saiatu berriro geroago.
pdfjs-editor-new-alt-text-error-close-button = Itxi
# Variables:
# $totalSize (Number) - the total size (in MB) of the AI model.
# $downloadedSize (Number) - the downloaded size (in MB) of the AI model.
pdfjs-editor-new-alt-text-ai-model-downloading-progress = Testu alternatiboaren AA modeloa deskargatzen ({ $downloadedSize }/{ $totalSize } MB)
.aria-valuetext = Testu alternatiboaren AA modeloa deskargatzen ({ $downloadedSize }/{ $totalSize } MB)
pdfjs-editor-new-alt-text-ai-model-downloading-progress = Ordezko testuaren AA modeloa deskargatzen ({ $downloadedSize }/{ $totalSize } MB)
.aria-valuetext = Ordezko testuaren AA modeloa deskargatzen ({ $downloadedSize }/{ $totalSize } MB)
# This is a button that users can click to edit the alt text they have already added.
pdfjs-editor-new-alt-text-added-button =
.aria-label = Testu alternatiboa gehituta
pdfjs-editor-new-alt-text-added-button-label = Testu alternatiboa gehituta
.aria-label = Ordezko testua gehituta
pdfjs-editor-new-alt-text-added-button-label = Ordezko testua gehituta
# This is a button that users can click to open the alt text editor and add alt text when it is not present.
pdfjs-editor-new-alt-text-missing-button =
.aria-label = Testu alternatiboa falta da
pdfjs-editor-new-alt-text-missing-button-label = Testu alternatiboa falta da
.aria-label = Ordezko testua falta da
pdfjs-editor-new-alt-text-missing-button-label = Ordezko testua falta da
# This is a button that opens up the alt text modal where users should review the alt text that was automatically generated.
pdfjs-editor-new-alt-text-to-review-button =
.aria-label = Berrikusi testu alternatiboa
pdfjs-editor-new-alt-text-to-review-button-label = Berrikusi testu alternatiboa
.aria-label = Berrikusi ordezko testua
pdfjs-editor-new-alt-text-to-review-button-label = Berrikusi ordezko testua
# "Created automatically" is a prefix that will be added to the beginning of any alt text that has been automatically generated. After the colon, the user will see/hear the actual alt text description. If the alt text has been edited by a human, this prefix will not appear.
# Variables:
# $generatedAltText (String) - the generated alt-text.
@ -510,22 +531,22 @@ pdfjs-editor-new-alt-text-generated-alt-text-with-disclaimer = Automatikoki sort
## Image alt-text settings
pdfjs-image-alt-text-settings-button =
.title = Irudiaren testu alternatiboaren ezarpenak
pdfjs-image-alt-text-settings-button-label = Irudiaren testu alternatiboaren ezarpenak
pdfjs-editor-alt-text-settings-dialog-label = Irudiaren testu alternatiboaren ezarpenak
pdfjs-editor-alt-text-settings-automatic-title = Testu alternatibo automatikoa
pdfjs-editor-alt-text-settings-create-model-button-label = Sortu testu alternatiboa automatikoki
.title = Irudien ordezko testuaren ezarpenak
pdfjs-image-alt-text-settings-button-label = Irudien ordezko testuaren ezarpenak
pdfjs-editor-alt-text-settings-dialog-label = Irudien ordezko testuaren ezarpenak
pdfjs-editor-alt-text-settings-automatic-title = Ordezko testu automatikoa
pdfjs-editor-alt-text-settings-create-model-button-label = Sortu ordezko testua automatikoki
pdfjs-editor-alt-text-settings-create-model-description = Azalpenak iradokitzen ditu irudia ikusi ezin duen jendearentzat edo irudia kargatu ezin denerako.
# Variables:
# $totalSize (Number) - the total size (in MB) of the AI model.
pdfjs-editor-alt-text-settings-download-model-label = Testu alternatiboaren AA modeloa ({ $totalSize } MB)
pdfjs-editor-alt-text-settings-ai-model-description = Zure gailuan modu lokalean exekutatzen da eta zure datuak pribatu mantentzen dira. Testu alternatibo automatikorako beharrezkoa.
pdfjs-editor-alt-text-settings-download-model-label = Ordezko testuaren AA modeloa ({ $totalSize } MB)
pdfjs-editor-alt-text-settings-ai-model-description = Zure gailuan modu lokalean exekutatzen da eta zure datuak pribatu mantentzen dira. Ordezko testu automatikorako beharrezkoa.
pdfjs-editor-alt-text-settings-delete-model-button = Ezabatu
pdfjs-editor-alt-text-settings-download-model-button = Deskargatu
pdfjs-editor-alt-text-settings-downloading-model-button = Deskargatzen…
pdfjs-editor-alt-text-settings-editor-title = Testu alternatiboaren editorea
pdfjs-editor-alt-text-settings-show-dialog-button-label = Erakutsi testu alternatiboa irudi bat gehitzean berehala
pdfjs-editor-alt-text-settings-show-dialog-description = Zure irudiek testu alternatiboa duela ziurtatzen laguntzen dizu.
pdfjs-editor-alt-text-settings-editor-title = Ordezko testuaren editorea
pdfjs-editor-alt-text-settings-show-dialog-button-label = Erakutsi ordezko testua irudi bat gehitzean berehala
pdfjs-editor-alt-text-settings-show-dialog-description = Zure irudi guztiek ordezko testua dutela ziurtatzen laguntzen dizu.
pdfjs-editor-alt-text-settings-close-button = Itxi
## Accessibility labels (announced by screen readers) for objects added to the editor.
@ -563,7 +584,7 @@ pdfjs-editor-undo-bar-close-button-label = Itxi
pdfjs-editor-add-signature-dialog-label =
Leiho modal honek PDF dokumentu batera gehitzeko sinadurak
sortzea ahalbidetzen dio erabiltzaileari. Erabiltzaileak izena edita
dezake (testu alternatibo modura ere erabiltzen dena) eta sinadura
dezake (ordezko testu modura ere erabiltzen dena) eta sinadura
gordetzeko aukera du gehiagotan erabili ahal izateko.
pdfjs-editor-add-signature-dialog-title = Gehitu sinadura
@ -598,9 +619,9 @@ pdfjs-editor-add-signature-image-browse-link =
## Controls
pdfjs-editor-add-signature-description-label = Azalpena (testu alternatiboa)
pdfjs-editor-add-signature-description-label = Azalpena (ordezko testua)
pdfjs-editor-add-signature-description-input =
.title = Azalpena (testu alternatiboa)
.title = Azalpena (ordezko testua)
pdfjs-editor-add-signature-description-default-when-drawing = Sinadura
pdfjs-editor-add-signature-clear-button-label = Garbitu sinadura
pdfjs-editor-add-signature-clear-button =
@ -736,6 +757,74 @@ pdfjs-views-manager-waiting-for-file = Fitxategia igotzen…
pdfjs-toggle-views-manager-button1 =
.title = Kudeatu orriak
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Sinadura digitalaren propietateak
.aria-label = Sinadura digitalaren propietateak
pdfjs-digital-signature-properties-button-label = Sinadura digitalaren propietateak
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokumentua baliozko sinadura digitalarekin sinatuta dago
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokumentua sinatuta dago baina sinadura digital bat ezin izan da egiaztatu
*[other] Dokumentua sinatuta dago baina { $count } sinadura digital ezin izan dira egiaztatu
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Document ziurtagiri fidagaitz batekin sinatuta dago
*[other] Document { $count } ziurtagiri fidagaitzekin sinatuta dago
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokumentua iraungitako ziurtagiri batekin sinatuta dago
*[other] Dokumentua iraungitako { $count } ziurtagirirekin sinatuta dago
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokumentuak sinadura digital baliogabe bat du
*[other] Dokumentuak { $count } sinadura digital baliogabe ditu
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokumentua baliogabetutako ziurtagiri batekin sinatuta dago
*[other] Dokumentua baliogabetutako { $count } ziurtagirirekin sinatuta dago
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Egoera: sinadura egiaztatuta
pdfjs-digital-signature-properties-status-invalid = Egoera: sinadura baliogabea
pdfjs-digital-signature-properties-status-unknown = Egoera: ezin da egiaztatu (euskarririk ez)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Ziurtagiria: fidagarria ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Ziurtagiria: ez dago erabilgarri
pdfjs-digital-signature-properties-certificate-untrusted = Ziurtagiria: fidagaitza
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Ziurtagiria: jaulkitzaile ezezaguna ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Ziurtagiria: bere buruak sinatutakoa ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Ziurtagiria: jaulkitzaile fidagaitza ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Ziurtagiria: iraungita
pdfjs-digital-signature-properties-certificate-expired-with-date = Ziurtagiria: iraungita ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Ziurtagiria: baliogabetuta
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Nopea web-katselu:
pdfjs-document-properties-linearized-yes = Kyllä
pdfjs-document-properties-linearized-no = Ei
pdfjs-document-properties-close-button = Sulje
pdfjs-digital-signature-properties-view-certificate = Näytä varmenne
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Syy: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Aikaleima: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Aliallekirjoitus ({ $count })
*[other] Aliallekirjoitukset ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Lähetetään tiedostoa…
pdfjs-toggle-views-manager-button1 =
.title = Hallitse sivuja
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Digitaalisen allekirjoituksen ominaisuudet
.aria-label = Digitaalisen allekirjoituksen ominaisuudet
pdfjs-digital-signature-properties-button-label = Digitaalisen allekirjoituksen ominaisuudet
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Asiakirja allekirjoitettiin kelvollisella digitaalisella allekirjoituksella
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Asiakirja allekirjoitettu, mutta { $count } digitaalista allekirjoitusta ei voitu vahvistaa
*[other] Asiakirja allekirjoitettu, mutta { $count } digitaalista allekirjoitusta ei voitu vahvistaa
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Asiakirja on allekirjoitettu { $count } varmenteella, johon ei luoteta
*[other] Asiakirja on allekirjoitettu { $count } varmenteella, joihin ei luoteta
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Asiakirja allekirjoitettu { $count } vanhentuneella varmenteella
*[other] Asiakirja allekirjoitettu { $count } vanhentuneella varmenteella
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Asiakirjassa on { $count } virheellinen digitaalinen allekirjoitus
*[other] Asiakirjassa on { $count } virheellistä digitaalista allekirjoitusta
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Asiakirja allekirjoitettu { $count } kumotulla varmenteella
*[other] Asiakirja allekirjoitettu { $count } kumotulla varmenteella
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Tila: Allekirjoitus vahvistettu
pdfjs-digital-signature-properties-status-invalid = Tila: Allekirjoitus virheellinen
pdfjs-digital-signature-properties-status-unknown = Tila: Vahvistus epäonnistui (ei tuettu)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Varmenne: Luotettu ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Varmenne: Ei saatavilla
pdfjs-digital-signature-properties-certificate-untrusted = Varmenne: Ei-luotettu
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Varmenne: Tuntematon myöntäjä ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Varmenne: Itse allekirjoitettu ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Varmenne: Ei-luotettu myöntäjä ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Varmenne: Vanhentunut
pdfjs-digital-signature-properties-certificate-expired-with-date = Varmenne: Vanhentunut ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Varmenne: Kumottu
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Affichage rapide des pages web :
pdfjs-document-properties-linearized-yes = Oui
pdfjs-document-properties-linearized-no = Non
pdfjs-document-properties-close-button = Fermer
pdfjs-digital-signature-properties-view-certificate = Afficher le certificat
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Raison : { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Horodatage : { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Sous-signature ({ $count })
*[other] Sous-signatures ({ $count })
}
## Print
@ -236,7 +257,7 @@ pdfjs-find-match-count = Occurrence { $current } sur { $total }
# $limit (Number) - the maximum number of matches
pdfjs-find-match-count-limit =
{ $limit ->
[one] Plus d{ $limit } occurrence
[1] Plus dune occurrence
*[other] Plus de { $limit } occurrences
}
pdfjs-find-not-found = Expression non trouvée
@ -728,6 +749,74 @@ pdfjs-views-manager-waiting-for-file = Envoi du fichier…
pdfjs-toggle-views-manager-button1 =
.title = Gérer les pages
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Propriétés de la signature numérique
.aria-label = Propriétés de la signature numérique
pdfjs-digital-signature-properties-button-label = Propriétés de la signature numérique
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Le document a été signé avec une signature numérique valide
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Document signé mais { $count } signature numérique na pas pu être vérifiée
*[other] Document signé mais { $count } signatures numériques nont pas pu être vérifiées
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[1] Document signé avec un certificat non digne de confiance
*[other] Document signé avec { $count } certificats non dignes de confiance
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[1] Document signé avec un certificat expiré
*[other] Document signé avec { $count } certificats expirés
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[1] Le document contient une signature numérique non valide
*[other] Le document contient { $count } signatures numériques non valides
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[1] Document signé avec un certificat révoqué
*[other] Document signé avec { $count } certificats révoqués
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = État : signature vérifiée
pdfjs-digital-signature-properties-status-invalid = État : signature invalide
pdfjs-digital-signature-properties-status-unknown = État : impossible à vérifier (non pris en charge)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certificat : fiable ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certificat : indisponible
pdfjs-digital-signature-properties-certificate-untrusted = Certificat : non fiable
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certificat : émetteur inconnu ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certificat : auto-signé ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certificat : émetteur non fiable ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certificat : expiré
pdfjs-digital-signature-properties-certificate-expired-with-date = Certificat : expiré ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certificat : révoqué
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Flugge webwerjefte:
pdfjs-document-properties-linearized-yes = Ja
pdfjs-document-properties-linearized-no = Nee
pdfjs-document-properties-close-button = Slute
pdfjs-digital-signature-properties-view-certificate = Sertifikaat besjen
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Reden: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Tiidstimpel: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Undertekening ({ $count })
*[other] Undertekeningen ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Bestân oplade…
pdfjs-toggle-views-manager-button1 =
.title = Siden beheare
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Eigenskippen fan digitale hantekening
.aria-label = Eigenskippen fan digitale hantekening
pdfjs-digital-signature-properties-button-label = Eigenskippen fan digitale hantekening
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokumint is ûndertekene mei in jildige digitale hantekening
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokumint ûndertekene, mar { $count } digitale hantekening koe net ferifiearre wurde
*[other] Dokumint ûndertekene, mar { $count } digitale hantekeningen koene net ferifiearre wurde
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokumint ûndertekene mei { $count } sertifikaat dat net fertroud wurdt
*[other] Dokumint ûndertekene mei { $count } sertifikaten dyt net fertroud wurde
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokumint ûndertekene mei { $count } ferrûne sertifikaat
*[other] Dokumint ûndertekene mei { $count } ferrûne sertifikaten
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokumint hat { $count } ûnjildige digitale hantekening
*[other] Dokumint hat { $count } ûnjildige digitale hantekeningen
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokumint ûndertekene mei { $count } ynlutsen sertifikaat
*[other] Dokumint ûndertekene mei { $count } ynlutsen sertifikaten
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: hantekening ferifiearre
pdfjs-digital-signature-properties-status-invalid = Status: hantekening ûnjildich
pdfjs-digital-signature-properties-status-unknown = Status: kin net ferifiearje wurde (net stipe)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Sertifikaat: fertroud ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Sertifikaat: net beskikber
pdfjs-digital-signature-properties-certificate-untrusted = Sertifikaat: net fertroud
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Sertifikaat: Unbekende útjouwer ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Sertifikaat: selsûndertekene ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Sertifikaat: net-fertroude útjouwer ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Sertifikaat: ferrûn
pdfjs-digital-signature-properties-certificate-expired-with-date = Sertifikaat: ferrûn ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Sertifikaat: ynlutsen
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Ñanduti jahecha pyae:
pdfjs-document-properties-linearized-yes = Añete
pdfjs-document-properties-linearized-no = Ahániri
pdfjs-document-properties-close-button = Mboty
pdfjs-digital-signature-properties-view-certificate = Mboajapyre jehecha
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Mbaére: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Ára: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Mboheraguapyi ({ $count })
*[other] Mboheraguapyieta ({ $count })
}
## Print
@ -560,6 +581,7 @@ pdfjs-editor-undo-bar-close-button-label = Mboty
## Add a signature dialog
pdfjs-editor-add-signature-dialog-label = Ko modal omoneĩ poruhárape omoheñóivo mboheraguapy ombojuaju hag̃ua PDF rehe. Upe poruhára ombosakoikuaa téra (oikóva avei moñeẽrã mokõihávarõ) ha, ejaposérõ, eñongatu mboheraguapy eiporujey hag̃ua.
pdfjs-editor-add-signature-dialog-title = Embojuaju teraguapy
## Tab names
@ -731,6 +753,49 @@ pdfjs-views-manager-waiting-for-file = Ehupihína marandurenda…
pdfjs-toggle-views-manager-button1 =
.title = Eñangareko kuotiarogue
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Firma digital oguerekóva
.aria-label = Firma digital oguerekóva
pdfjs-digital-signature-properties-button-label = Firma digital oguerekóva
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Pe kuatia oñemboheraguapy firma digital oikóvape
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Heko: Mboheraguapy hechajeypyre
pdfjs-digital-signature-properties-status-invalid = Heko: Mboheraguapy oikoỹva
pdfjs-digital-signature-properties-status-unknown = Heko: Ndojehechajeykuaái (ndojokupytýi)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Mboajapyre: Jeroviaha ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Mboajapyre: Oĩỹva
pdfjs-digital-signature-properties-certificate-untrusted = Mboajapyre: Jeroviaỹha
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Mboajapyre: Guenohẽha jekuaaỹva ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Mboajapyre: Heraguapejeheguíva { $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Mboajapyre: Guenohẽha jeroviaỹha ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Mboajapyre: Oikoveỹmava
pdfjs-digital-signature-properties-certificate-expired-with-date = Mboajapyre: Oikoveỹmava ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Mboajapyre: Mbojevypyre
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = תצוגת דף מהירה:
pdfjs-document-properties-linearized-yes = כן
pdfjs-document-properties-linearized-no = לא
pdfjs-document-properties-close-button = סגירה
pdfjs-digital-signature-properties-view-certificate = הצגת אישור
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = סיבה: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = חותמת זמן: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] חתימת משנה ({ $count })
*[other] חתימות משנה ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = בתהליך העלאת הקובץ…
pdfjs-toggle-views-manager-button1 =
.title = ניהול עמודים
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = מאפייני חתימה דיגיטלית
.aria-label = מאפייני חתימה דיגיטלית
pdfjs-digital-signature-properties-button-label = מאפייני חתימה דיגיטלית
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = המסמך נחתם בחתימה דיגיטלית תקפה
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] המסמך חתום אך לא ניתן היה לאמת חתימה דיגיטלית אחת
*[other] המסמך חתום אך לא ניתן היה לאמת { $count } חתימות דיגיטליות
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] המסמך חתום עם אישור אחד שאינו מהימן
*[other] המסמך חתום עם { $count } אישורים שאינם מהימנים
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] המסמך חתום עם אישור אחד שפג תוקפו
*[other] המסמך חתום עם { $count } אישורים שפג תוקפם
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] למסמך יש חתימה דיגיטלית אחת שאינה תקינה
*[other] למסמך יש { $count } חתימות דיגיטליות שאינן תקינות
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] המסמך חתום עם אישור אחד שנשלל
*[other] המסמך חתום עם { $count } אישורים שנשללו
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = מצב: החתימה מאומתת
pdfjs-digital-signature-properties-status-invalid = מצב: החתימה לא תקינה
pdfjs-digital-signature-properties-status-unknown = מצב: לא ניתן לאמת (לא נתמך)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = אישור אבטחה: מהימן ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = אישור אבטחה: לא זמין
pdfjs-digital-signature-properties-certificate-untrusted = אישור אבטחה: לא מהימן
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = אישור אבטחה: מנפיק לא ידוע ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = אישור אבטחה: נחתם עצמית ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = אישור אבטחה: מנפיק לא מהימן ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = אישור אבטחה: פג תוקפו
pdfjs-digital-signature-properties-certificate-expired-with-date = אישור אבטחה: פג תוקפו ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = אישור אבטחה: נשלל
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,29 @@ pdfjs-document-properties-linearized = Fast Web View:
pdfjs-document-properties-linearized-yes = Haj
pdfjs-document-properties-linearized-no = Ně
pdfjs-document-properties-close-button = Začinić
pdfjs-digital-signature-properties-view-certificate = Certifikat pokazać
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Přičina: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Časowy kołk: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] { $count } podsignatura
[two] { $count } podsignaturje
[few] { $count } podsignatury
*[other] { $count } podsignaturow
}
## Print
@ -748,6 +771,84 @@ pdfjs-views-manager-waiting-for-file = Dataja so nahrawa…
pdfjs-toggle-views-manager-button1 =
.title = Strony rjadować
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Kajkosće digitalneje signatury
.aria-label = Kajkosće digitalneje signatury
pdfjs-digital-signature-properties-button-label = Kajkosće digitalneje signatury
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokument je so z płaćiwej digitalnej signaturu signował
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokument je so signował, ale { $count } digitalna signatura njeda so wobkrućić
[two] Dokument je so signował, ale { $count } digitalnej signaturje njedatej so wobkrućić
[few] Dokument je so signował, ale { $count } digitalne signatury njedachu so wobkrućić
*[other] Dokument je so signował, ale { $count } digitalnych signaturow njeda so wobkrućić
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokument je z { $count } certifikatom signowany, kotryž dowěry hódny njeje
[two] Dokument je z { $count } certifikatomaj signowany, kotrejž dowěry hódnej njejstej
[few] Dokument je z { $count } certifikatami signowany, kotrež dowěry hódne njejsu
*[other] Dokument je z { $count } certifikatami signowany, kotrež dowěry hódne njejsu
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokument je z { $count } spadnjenym certifikatom signowany
[two] Dokument je z { $count } spadnjenymaj certifikatomaj signowany
[few] Dokument je z { $count } spadnjenymi certifikatami signowany
*[other] Dokument je z { $count } spadnjenymi certifikatami signowany
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokument ma { $count } njepłaćiwu digitalnu signaturu
[two] Dokument ma { $count } njepłaćiwej digitalnej signaturje
[few] Dokument ma { $count } njepłaćiwe digitalne signatury
*[other] Dokument ma { $count } njepłaćiwych digitalnych signaturow
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokument je z { $count } wotwołanym certifikatom signowany
[two] Dokument je z { $count } wotwołanymaj certifikatomaj signowany
[few] Dokument je z { $count } wotwołanymi certifikatami signowany
*[other] Dokument je z { $count } wotwołanymi certifikatami signowany
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: Signatura je wobkrućena
pdfjs-digital-signature-properties-status-invalid = Status: Signatura je njepłaćiwa
pdfjs-digital-signature-properties-status-unknown = Status: Njeda so wobkrućić (njepodpěruje so)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certifikat: Dowěry hódny ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certifikat: Nic k dispoziciji
pdfjs-digital-signature-properties-certificate-untrusted = Certifikat: Dowěry njehódny
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certifikat: Njeznaty wudawar ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certifikat: Samsignowany ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certifikat: Dowěry njehódny wudawar ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certifikat: Spadnjeny
pdfjs-digital-signature-properties-certificate-expired-with-date = Certifikat: Spadnjeny ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certifikat: Wotwołany
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Gyors webes nézet:
pdfjs-document-properties-linearized-yes = Igen
pdfjs-document-properties-linearized-no = Nem
pdfjs-document-properties-close-button = Bezárás
pdfjs-digital-signature-properties-view-certificate = Tanúsítvány megtekintése
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Ok: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Időbélyeg: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Részaláírás ({ $count })
*[other] Részaláírások ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Fájl feltöltése…
pdfjs-toggle-views-manager-button1 =
.title = Oldalak kezelése
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Digitális aláírás tulajdonságai
.aria-label = Digitális aláírás tulajdonságai
pdfjs-digital-signature-properties-button-label = Digitális aláírás tulajdonságai
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = A dokumentum érvényes digitális aláírással lett aláírva
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] A dokumentum alá van írva, de { $count } digitális aláírás nem ellenőrizhető
*[other] A dokumentum alá van írva, de { $count } digitális aláírás nem ellenőrizhető
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] A dokumentum { $count } nem megbízható tanúsítvánnyal van aláírva
*[other] A dokumentum { $count } nem megbízható tanúsítvánnyal van aláírva
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] A dokumentum { $count } lejárt tanúsítvánnyal van aláírva
*[other] A dokumentum { $count } lejárt tanúsítvánnyal van aláírva
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] A dokumentum { $count } érvénytelen aláírással rendelkezik
*[other] A dokumentum { $count } érvénytelen aláírással rendelkezik
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] A dokumentum { $count } visszavont tanúsítvánnyal van aláírva
*[other] A dokumentum { $count } visszavont tanúsítvánnyal van aláírva
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Állapot: az aláírás ellenőrizve
pdfjs-digital-signature-properties-status-invalid = Állapot: az aláírás érvénytelen
pdfjs-digital-signature-properties-status-unknown = Állapot: nem ellenőrizhető (nem támogatott)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Tanúsítvány: megbízható ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Tanúsítvány: nem érhető el
pdfjs-digital-signature-properties-certificate-untrusted = Tanúsítvány: nem megbízható
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Tanúsítvány: ismeretlen kibocsátó ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Tanúsítvány: önaláírt ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Tanúsítvány: nem megbízható kibocsátó ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Tanúsítvány: lejárt
pdfjs-digital-signature-properties-certificate-expired-with-date = Tanúsítvány: lejárt ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Tanúsítvány: visszavonva
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,15 @@ pdfjs-document-properties-linearized = Արագ վեբ դիտում․
pdfjs-document-properties-linearized-yes = Այո
pdfjs-document-properties-linearized-no = Ոչ
pdfjs-document-properties-close-button = Փակել
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Պատճառը՝ { $reason }
## Print

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Vista web rapide:
pdfjs-document-properties-linearized-yes = Si
pdfjs-document-properties-linearized-no = No
pdfjs-document-properties-close-button = Clauder
pdfjs-digital-signature-properties-view-certificate = Vider le certificato
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Ration: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Data e hora: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Firma secundari ({ $count })
*[other] Firmas secundari ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Cargante file…
pdfjs-toggle-views-manager-button1 =
.title = Gerer paginas
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Proprietates del firma digital
.aria-label = Proprietates del firma digital
pdfjs-digital-signature-properties-button-label = Proprietates del firma digital
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Le documento era firmate con un firma digital valide
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Documento firmate ma { $count } firma digital non poteva esser verificate
*[other] Documento firmate ma { $count } firmas digital non poteva esser verificate
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Documento firmate con { $count } certificato que non es de fiducia
*[other] Documento firmate con { $count } certificatos que non es de fiducia
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Documento firmate con { $count } certificato expirate
*[other] Documento firmate con { $count } certificatos expirate
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Le documento ha { $count } firma digital non valide
*[other] Le documento ha { $count } firmas digital non valide
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Documento firmate con { $count } certificato revocate
*[other] Documento firmate con { $count } certificatos revocate
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Stato: firma verificate
pdfjs-digital-signature-properties-status-invalid = Stato: firma non valide
pdfjs-digital-signature-properties-status-unknown = Stato: impossibile verificar (non supportate)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certificato: de fiducia ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certificato: indisponibile
pdfjs-digital-signature-properties-certificate-untrusted = Certificato: non de confidentia
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certificato: emissor incognite ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certificato: auto-firmate ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certificato: emissor non de confidentia ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certificato: expirate
pdfjs-digital-signature-properties-certificate-expired-with-date = Certificato: expirate ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certificato: revocate
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Visualizzazione web veloce:
pdfjs-document-properties-linearized-yes = Sì
pdfjs-document-properties-linearized-no = No
pdfjs-document-properties-close-button = Chiudi
pdfjs-digital-signature-properties-view-certificate = Visualizza certificato
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Motivo: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Data e ora: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Firma secondaria ({ $count })
*[other] Firme secondarie ({ $count })
}
## Print
@ -240,7 +261,7 @@ pdfjs-find-match-count =
# $limit (Number) - the maximum number of matches
pdfjs-find-match-count-limit =
{ $limit ->
[one] Più di una { $limit } corrispondenza
[one] Più di { $limit } corrispondenza
*[other] Più di { $limit } corrispondenze
}
pdfjs-find-not-found = Testo non trovato
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Caricamento file…
pdfjs-toggle-views-manager-button1 =
.title = Gestisci pagine
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Proprietà firma digitale
.aria-label = Proprietà firma digitale
pdfjs-digital-signature-properties-button-label = Proprietà firma digitale
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Il documento è stato firmato con una firma digitale valida
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Il documento è stato firmato ma non è stato possibile verificare { $count } firma digitale
*[other] Il documento è stato firmato ma non è stato possibile verificare { $count } firme digitali
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Documento firmato con { $count } certificato non attendibile
*[other] Documento firmato con { $count } certificati non attendibili
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Documento firmato con { $count } certificato scaduto
*[other] Documento firmato con { $count } certificati scaduti
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Il documento contiene { $count } firma digitale non valida
*[other] Il documento contiene { $count } firme digitali non valide
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Documento firmato con { $count } certificato revocato
*[other] Documento firmato con { $count } certificati revocati
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Stato: firma verificata
pdfjs-digital-signature-properties-status-invalid = Stato: firma non valida
pdfjs-digital-signature-properties-status-unknown = Stato: impossibile verificare (non supportato)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certificato: affidabile ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certificato: non disponibile
pdfjs-digital-signature-properties-certificate-untrusted = Certificato: non attendibile
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certificato: emittente sconosciuto ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certificato: autofirmato ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certificato: emittente non attendibile ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certificato: scaduto
pdfjs-digital-signature-properties-certificate-expired-with-date = Certificato: scaduto ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certificato: revocato
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,23 @@ pdfjs-document-properties-linearized = ウェブ表示用に最適化:
pdfjs-document-properties-linearized-yes = はい
pdfjs-document-properties-linearized-no = いいえ
pdfjs-document-properties-close-button = 閉じる
pdfjs-digital-signature-properties-view-certificate = 証明書を表示
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = 理由: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = タイムスタンプ: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures = サブ署名 ({ $count } 筆)
## Print
@ -700,6 +717,54 @@ pdfjs-views-manager-waiting-for-file = ファイルをアップロードして
pdfjs-toggle-views-manager-button1 =
.title = ページを管理
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = デジタル署名のプロパティ
.aria-label = デジタル署名のプロパティ
pdfjs-digital-signature-properties-button-label = デジタル署名のプロパティ
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = 文書は検証されたデジタル署名で署名されています
pdfjs-digital-signature-properties-banner-unknown = 文書は署名されていますが、{ $count } 筆のデジタル署名が検証できません
pdfjs-digital-signature-properties-banner-untrusted = 文書は { $count } 筆の信頼できないデジタル署名で署名されています
pdfjs-digital-signature-properties-banner-expired = 文書は { $count } 枚の有効期限が切れた証明書で署名されています
pdfjs-digital-signature-properties-banner-invalid = 文書には { $count } 筆の不正なデジタル署名があります
pdfjs-digital-signature-properties-banner-revoked = 文書は { $count } 枚の破棄された証明書で署名されています
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = 状態: 検証された証明書
pdfjs-digital-signature-properties-status-invalid = 状態: 不正な証明書
pdfjs-digital-signature-properties-status-unknown = 状態: 検証不可 (未サポート)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = 証明書: 信頼されている ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = 証明書: 利用不可
pdfjs-digital-signature-properties-certificate-untrusted = 証明書: 信頼できない
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = 証明書: 発行者不明 ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = 証明書: 自己署名 ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = 証明書: 信頼できない発行者 ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = 証明書: 有効期限切れ
pdfjs-digital-signature-properties-certificate-expired-with-date = 証明書: 有効期限切れ ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = 証明書: 破棄
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = მსუბუქი ვებჩვე
pdfjs-document-properties-linearized-yes = დიახ
pdfjs-document-properties-linearized-no = არა
pdfjs-document-properties-close-button = დახურვა
pdfjs-digital-signature-properties-view-certificate = სერტიფიკატის ნახვა
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = მიზეზი: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = დროის ნიშნული: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] ქვეხელმოწერები ({ $count })
*[other] ქვეხელმოწერები ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = ფაილი აიტვირთე
pdfjs-toggle-views-manager-button1 =
.title = გვერდების მართვა
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = ციფრული ხელმოწერის პარამეტრები
.aria-label = ციფრული ხელმოწერის პარამეტრები
pdfjs-digital-signature-properties-button-label = ციფრული ხელმოწერის პარამეტრები
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = დოკუმენტი ხელმოწერილია მართებული ციფრული ხელმოწერით
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] დოკუმენტი ხელმოწერილია, მაგრამ { $count } ციფრული ხელმოწერა ვერ დამოწმდა
*[other] დოკუმენტი ხელმოწერილია, მაგრამ { $count } ციფრული ხელმოწერა ვერ დამოწმდა
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] დოკუმენტი ხელმოწერილია { $count } არასანდო სერტიფიკატით
*[other] დოკუმენტი ხელმოწერილია { $count } არასანდო სერტიფიკატით
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] დოკუმენტი ხელმოწერილია { $count } ვადაგასული სერტიფიკატით
*[other] დოკუმენტი ხელმოწერილია { $count } ვადაგასული სერტიფიკატით
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] დოკუმენტი ხელმოწერილია { $count } უმართებულო ციფრული სერტიფიკატით
*[other] დოკუმენტი ხელმოწერილია { $count } უმართებულო ციფრული სერტიფიკატით
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] დოკუმენტი ხელმოწერილია { $count } ძალადაკარგული სერტიფიკატით
*[other] დოკუმენტი ხელმოწერილია { $count } ძალადაკარგული სერტიფიკატით
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = მდგომარეობა: ხელმოწერა დამოწმებულია
pdfjs-digital-signature-properties-status-invalid = მდგომარეობა: ხელმოწერა უმართებულოა
pdfjs-digital-signature-properties-status-unknown = მდგომარეობა: ვერ მოწმდება (მხარდაუჭერელია)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = სერტიფიკატი: სანდოა ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = სერტიფიკატი: მიუწვდომელია
pdfjs-digital-signature-properties-certificate-untrusted = სერტიფიკატი: არასანდოა
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = სერტიფიკატი: უცნობი გამცემი ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = სერტიფიკატი: თვითხელმოწერით ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = სერტიფიკატი: არასანდო გამცემი ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = სერტიფიკატი: ვადაგასული
pdfjs-digital-signature-properties-certificate-expired-with-date = სერტიფიკატი: ვადაგასული ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = სერტიფიკატი: ძალადაკარგულია
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -125,7 +125,7 @@ pdfjs-document-properties-creator = Yerna-t:
pdfjs-document-properties-producer = Afecku n uselket PDF:
pdfjs-document-properties-version = Lqem PDF:
pdfjs-document-properties-page-count = Amḍan n yisebtar:
pdfjs-document-properties-page-size = Tuγzi n usebter:
pdfjs-document-properties-page-size = Teɣzi n usebter:
pdfjs-document-properties-page-size-unit-inches = deg
pdfjs-document-properties-page-size-unit-millimeters = mm
pdfjs-document-properties-page-size-orientation-portrait = s teɣzi

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Жылдам Web көрінісі:
pdfjs-document-properties-linearized-yes = Иә
pdfjs-document-properties-linearized-no = Жоқ
pdfjs-document-properties-close-button = Жабу
pdfjs-digital-signature-properties-view-certificate = Сертификатты қарау
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Себебі: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Күн мен уақыт белгісі: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Ішкі қолтаңба ({ $count })
*[other] Ішкі қолтаңбалар ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Файл жүктеп салынуда…
pdfjs-toggle-views-manager-button1 =
.title = Беттерді басқару
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Цифрлық қолтаңба қасиеттері
.aria-label = Цифрлық қолтаңба қасиеттері
pdfjs-digital-signature-properties-button-label = Цифрлық қолтаңба қасиеттері
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Құжатқа жарамды цифрлық қолтаңбамен қол қойылған
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Құжатқа қол қойылған, бірақ { $count } цифрлық қолтаңбаны тексеру мүмкін болмады
*[other] Құжатқа қол қойылған, бірақ { $count } цифрлық қолтаңбаны тексеру мүмкін болмады
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Құжатқа сенімсіз { $count } сертификатпен қол қойылған
*[other] Құжатқа сенімсіз { $count } сертификатпен қол қойылған
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Құжатқа мерзімі өткен { $count } сертификатпен қол қойылған
*[other] Құжатқа мерзімі өткен { $count } сертификатпен қол қойылған
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Құжатта { $count } жарамсыз цифрлық қолтаңба бар
*[other] Құжатта { $count } жарамсыз цифрлық қолтаңба бар
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Құжатқа қайтарылған { $count } сертификатпен қол қойылған
*[other] Құжатқа қайтарылған { $count } сертификатпен қол қойылған
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Қалып-күй: Қолтаңба тексерілді
pdfjs-digital-signature-properties-status-invalid = Қалып-күй: Қолтаңба жарамсыз
pdfjs-digital-signature-properties-status-unknown = Қалып-күй: Тексеру мүмкін емес (қолдау көрсетілмейді)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Сертификат: Сенімді ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Сертификат: Қолжетімсіз
pdfjs-digital-signature-properties-certificate-untrusted = Сертификат: Сенімсіз
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Сертификат: Белгісіз шығарушы ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Сертификат: Өздігінен қол қойылған ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Сертификат: Сенімсіз шығарушы ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Сертификат: Мерзімі өткен
pdfjs-digital-signature-properties-certificate-expired-with-date = Сертификат: Мерзімі өткен ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Сертификат: Қайтарылған
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,23 @@ pdfjs-document-properties-linearized = 빠른 웹 보기:
pdfjs-document-properties-linearized-yes = 예
pdfjs-document-properties-linearized-no = 아니요
pdfjs-document-properties-close-button = 닫기
pdfjs-digital-signature-properties-view-certificate = 인증서 보기
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = 이유: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = 타임스탬프: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures = 하위 서명 ({ $count }개)
## Print
@ -569,7 +586,7 @@ pdfjs-editor-add-signature-draw-thickness-range-label = 두께
# $thickness (Number) - the thickness (in pixels) of the line used to draw a signature.
pdfjs-editor-add-signature-draw-thickness-range =
.title = 그리기 두께: { $thickness }
pdfjs-editor-add-signature-image-placeholder = 이미지 파일을 여기에 끌어 놓으세요
pdfjs-editor-add-signature-image-placeholder = 이미지 파일을 여기에 끌어 놓으세요
pdfjs-editor-add-signature-image-browse-link =
{ PLATFORM() ->
[macos] 또는 이미지 파일 찾아보기
@ -665,7 +682,7 @@ pdfjs-views-manager-pages-status-action-button-label = 관리
pdfjs-views-manager-pages-status-copy-button-label = 복사
pdfjs-views-manager-pages-status-cut-button-label = 잘라내기
pdfjs-views-manager-pages-status-delete-button-label = 삭제
pdfjs-views-manager-pages-status-export-selected-button-label = 선택 페이지 내보내기…
pdfjs-views-manager-pages-status-export-selected-button-label = 선택 페이지 내보내기…
# Variables:
# $count (Number) - the number of selected pages to be cut.
pdfjs-views-manager-status-undo-cut-label = { $count }개 페이지 잘림
@ -700,6 +717,54 @@ pdfjs-views-manager-waiting-for-file = 파일 업로드 중…
pdfjs-toggle-views-manager-button1 =
.title = 페이지 관리
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = 디지털 서명 속성
.aria-label = 디지털 서명 속성
pdfjs-digital-signature-properties-button-label = 디지털 서명 속성
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = 유효한 디지털 서명으로 문서에 서명되었습니다
pdfjs-digital-signature-properties-banner-unknown = 문서에 서명되었지만 { $count }개의 디지털 서명을 확인할 수 없음
pdfjs-digital-signature-properties-banner-untrusted = 신뢰할 수 없는 { $count }개의 인증서로 서명된 문서
pdfjs-digital-signature-properties-banner-expired = { $count }개의 만료된 인증서로 서명된 문서
pdfjs-digital-signature-properties-banner-invalid = 문서에 잘못된 { $count }개의 디지털 서명이 있음
pdfjs-digital-signature-properties-banner-revoked = 폐기된 인증서 { $count }개로 서명된 문서
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = 상태: 서명 확인됨
pdfjs-digital-signature-properties-status-invalid = 상태: 유효하지 않은 서명
pdfjs-digital-signature-properties-status-unknown = 상태: 확인할 수 없음 (지원되지 않음)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = 인증서: 신뢰할 수 있음 ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = 인증서: 사용할 수 없음
pdfjs-digital-signature-properties-certificate-untrusted = 인증서: 신뢰할 수 없음
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = 인증서: 알 수 없는 발급자 ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = 인증서: 자체 서명 ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = 인증서: 신뢰할 수 없는 발급자 ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = 인증서: 만료됨
pdfjs-digital-signature-properties-certificate-expired-with-date = 인증서: 만료됨 ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = 인증서: 폐기됨
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -479,6 +479,21 @@ pdfjs-editor-add-signature-cancel-button = റദ്ദാക്കുക
pdfjs-editor-add-signature-add-button = ചേൎക്കുക
pdfjs-editor-edit-signature-update-button = പുതുക്കുക
## Edit a comment dialog
pdfjs-editor-edit-comment-dialog-cancel-button = റദ്ദാക്കുക
## The view manager is a sidebar displaying different views:
## - thumbnails;
## - outline;
## - attachments;
## - layers.
## The thumbnails view is used to edit the pdf: remove/insert pages, ...
pdfjs-views-manager-status-close-button =
.title = അടയ്ക്കുക
pdfjs-views-manager-status-close-button-label = അടയ്ക്കുക
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Hurtig nettvisning:
pdfjs-document-properties-linearized-yes = Ja
pdfjs-document-properties-linearized-no = Nei
pdfjs-document-properties-close-button = Lukk
pdfjs-digital-signature-properties-view-certificate = Vis sertifikat
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Grunn: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Tidsstempel: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Undersignatur ({ $count })
*[other] Undersignaturer ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Laster opp filen …
pdfjs-toggle-views-manager-button1 =
.title = Behandle sider
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Egenskaper for digital signatur
.aria-label = Egenskaper for digital signatur
pdfjs-digital-signature-properties-button-label = Egenskaper for digital signatur
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokumentet ble signert med en gyldig digital signatur
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokumentet er signert, men { $count } digital signatur kunne ikke verifiseres
*[other] Dokumentet er signert, men { $count } digitale signaturer kunne ikke verifiseres
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokumentet er signert med { $count } sertifikat som ikke er klarert
*[other] Dokumentet er signert med { $count } sertifikater som ikke er klarert
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokumentet er signert med { $count } utløpt sertifikat
*[other] Dokumentet er signert med { $count } utløpte sertifikater
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokumentet har { $count } ugyldig digital signatur
*[other] Dokumentet har { $count } ugyldige digitale signaturer
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokumentet er signert med { $count } tilbakekalt sertifikat
*[other] Dokumentet er signert med { $count } tilbakekalte sertifikater
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: Signatur bekreftet
pdfjs-digital-signature-properties-status-invalid = Status: Signatur ugyldig
pdfjs-digital-signature-properties-status-unknown = Status: Kan ikke bekrefte (støttes ikke)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Sertifikat: Klarert ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Sertifikat: Utilgjengelig
pdfjs-digital-signature-properties-certificate-untrusted = Sertifikat: Ikke klarert
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Sertifikat: Ukjent utsteder ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Sertifikat: Selvsignert ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Sertifikat: Ikke klarert utsteder ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Sertifikat: Utløpt
pdfjs-digital-signature-properties-certificate-expired-with-date = Sertifikat: Utløpt ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Sertifikat: Tilbakekalt
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Snelle webweergave:
pdfjs-document-properties-linearized-yes = Ja
pdfjs-document-properties-linearized-no = Nee
pdfjs-document-properties-close-button = Sluiten
pdfjs-digital-signature-properties-view-certificate = Certificaat bekijken
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Reden: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Tijdstempel: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Ondertekening ({ $count })
*[other] Ondertekeningen ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Bestand uploaden…
pdfjs-toggle-views-manager-button1 =
.title = Paginas beheren
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Eigenschappen digitale handtekening
.aria-label = Eigenschappen digitale handtekening
pdfjs-digital-signature-properties-button-label = Eigenschappen digitale handtekening
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Document is ondertekend met een geldige digitale handtekening
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Document ondertekend, maar { $count } digitale handtekening kon niet worden geverifieerd
*[other] Document ondertekend, maar { $count } digitale handtekeningen konden niet worden geverifieerd
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Document ondertekend met { $count } certificaat dat niet wordt vertrouwd
*[other] Document ondertekend met { $count } certificaten die niet worden vertrouwd
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Document ondertekend met { $count } verlopen certificaat
*[other] Document ondertekend met { $count } verlopen certificaten
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Document heeft { $count } ongeldige digitale handtekening
*[other] Document heeft { $count } ongeldige digitale handtekeningen
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Document ondertekend met { $count } ingetrokken certificaat
*[other] Document ondertekend met { $count } ingetrokken certificaten
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: handtekening geverifieerd
pdfjs-digital-signature-properties-status-invalid = Status: handtekening ongeldig
pdfjs-digital-signature-properties-status-unknown = Status: kan niet worden geverifieerd (niet ondersteund)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certificaat: vertrouwd ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certificaat: niet beschikbaar
pdfjs-digital-signature-properties-certificate-untrusted = Certificaat: niet vertrouwd
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certificaat: onbekende uitgever ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certificaat: zelfondertekend ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certificaat: niet-vertrouwde uitgever ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certificaat: verlopen
pdfjs-digital-signature-properties-certificate-expired-with-date = Certificaat: verlopen ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certificaat: ingetrokken
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Rask nettvising:
pdfjs-document-properties-linearized-yes = Ja
pdfjs-document-properties-linearized-no = Nei
pdfjs-document-properties-close-button = Lat att
pdfjs-digital-signature-properties-view-certificate = Vis sertifikat
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Grunn: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Tidsstempel: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Undersignatur ({ $count })
*[other] Undersignaturar ({ $count })
}
## Print
@ -515,7 +536,7 @@ pdfjs-image-alt-text-settings-button-label = Alternative tekst-innstillingar for
pdfjs-editor-alt-text-settings-dialog-label = Alternative tekst-innstillingar for bilde
pdfjs-editor-alt-text-settings-automatic-title = Automatisk alternativ tekst
pdfjs-editor-alt-text-settings-create-model-button-label = Opprett alternativ tekt automatisk
pdfjs-editor-alt-text-settings-create-model-description = Foreslår skildringar for å hjelpe folk som ikkje kan sjå bildet eller når bildet ikkje blir lasta inn.
pdfjs-editor-alt-text-settings-create-model-description = Føreslår skildringar for å hjelpe folk som ikkje kan sjå bildet eller når bildet ikkje blir lasta inn.
# Variables:
# $totalSize (Number) - the total size (in MB) of the AI model.
pdfjs-editor-alt-text-settings-download-model-label = KI-modell for alternativ tekst ({ $totalSize } MB)
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Lastar opp fila…
pdfjs-toggle-views-manager-button1 =
.title = Handsam sider
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Eigenskapar for digital signatur
.aria-label = Eigenskapar for digital signatur
pdfjs-digital-signature-properties-button-label = Eigenskapar for digital signatur
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokumentet vart signert med ei gyldig digital signatur
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokumentet er signert, men { $count } digital signatur kunne ikkje verifiserast
*[other] Dokumentet er signert, men { $count } digitale signaturar kunne ikkje verifiserast
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokumentet er signert med { $count } sertifikat som ikkje er klarert
*[other] Dokumentet er signert med { $count } sertifikat som ikkje er klarerte
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokumentet er signert med { $count } utgåttt sertifikat
*[other] Dokumentet er signert med { $count } utgåtte sertifikat
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokumentet har { $count } ugyldig digital signatur
*[other] Dokumentet har { $count } ugyldige digitale signaturar
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokumentet er signert med { $count } tilbakekalt sertifikat
*[other] Dokumentet er signert med { $count } tilbakekalte sertifikat
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: Signatur stadfesta
pdfjs-digital-signature-properties-status-invalid = Status: Signatur ugyldig
pdfjs-digital-signature-properties-status-unknown = Status: Kan ikkje stadfeste (blir ikkje støtta)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Sertifikat: Klarert ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Sertifikat: Utilgjengeleg
pdfjs-digital-signature-properties-certificate-untrusted = Sertifikat: Ikkje klarert
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Sertifikat: Ukjent utferdar ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Sertifikat: Sjølvsignert ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Sertifikat: Ikkje klarert utferdar ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Sertifikat: Utgått
pdfjs-digital-signature-properties-certificate-expired-with-date = Sertifikat: Utgått ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Sertifikat: Tilbakekalla
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,28 @@ pdfjs-document-properties-linearized = Szybki podgląd w Internecie:
pdfjs-document-properties-linearized-yes = tak
pdfjs-document-properties-linearized-no = nie
pdfjs-document-properties-close-button = Zamknij
pdfjs-digital-signature-properties-view-certificate = Wyświetl certyfikat
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Powód: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Data: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] { $count } podpis podrzędny
[few] { $count } podpisy podrzędne
*[many] { $count } podpisów podrzędnych
}
## Print
@ -739,6 +761,79 @@ pdfjs-views-manager-waiting-for-file = Przesyłanie pliku…
pdfjs-toggle-views-manager-button1 =
.title = Zarządzaj stronami
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Właściwości podpisu cyfrowego
.aria-label = Właściwości podpisu cyfrowego
pdfjs-digital-signature-properties-button-label = Właściwości podpisu cyfrowego
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokument został podpisany ważnym podpisem cyfrowym
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokument jest popisany, ale nie można zweryfikować { $count } podpisu cyfrowego
[few] Dokument jest popisany, ale nie można zweryfikować { $count } podpisów cyfrowych
*[many] Dokument jest popisany, ale nie można zweryfikować { $count } podpisów cyfrowych
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokument jest podpisany za pomocą { $count } certyfikatu, który nie jest zaufany
[few] Dokument jest podpisany za pomocą { $count } certyfikatów, które nie są zaufane
*[many] Dokument jest podpisany za pomocą { $count } certyfikatów, które nie są zaufane
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokument jest podpisany za pomocą { $count } wygasłego certyfikatu
[few] Dokument jest podpisany za pomocą { $count } wygasłych certyfikatów
*[many] Dokument jest podpisany za pomocą { $count } wygasłych certyfikatów
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokument ma { $count } nieważny podpis cyfrowy
[few] Dokument ma { $count } nieważne podpisy cyfrowe
*[many] Dokument ma { $count } nieważnych podpisów cyfrowych
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokument jest podpisany za pomocą { $count } odwołanego certyfikatu
[few] Dokument jest podpisany za pomocą { $count } odwołanych certyfikatów
*[many] Dokument jest podpisany za pomocą { $count } odwołanych certyfikatów
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Stan: podpis jest zweryfikowany
pdfjs-digital-signature-properties-status-invalid = Stan: podpis jest nieważny
pdfjs-digital-signature-properties-status-unknown = Stan: nie można zweryfikować (nieobsługiwane)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certyfikat: zaufany ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certyfikat: niedostępny
pdfjs-digital-signature-properties-certificate-untrusted = Certyfikat: niezaufany
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certyfikat: nieznany wystawca ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certyfikat: samopodpisany ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certyfikat: niezaufany wystawca ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certyfikat: wygasły
pdfjs-digital-signature-properties-certificate-expired-with-date = Certyfikat: wygasły ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certyfikat: odwołany
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Exibição web rápida:
pdfjs-document-properties-linearized-yes = Sim
pdfjs-document-properties-linearized-no = Não
pdfjs-document-properties-close-button = Fechar
pdfjs-digital-signature-properties-view-certificate = Ver certificado
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Motivo: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Data e hora: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Assinatura secundária ({ $count })
*[other] Assinaturas secundárias ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Enviando arquivo…
pdfjs-toggle-views-manager-button1 =
.title = Gerenciar páginas
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Propriedades da assinatura digital
.aria-label = Propriedades da assinatura digital
pdfjs-digital-signature-properties-button-label = Propriedades da assinatura digital
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = O documento foi assinado com uma assinatura digital válida
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Documento assinado, mas { $count } assinatura digital não pôde ser verificada
*[other] Documento assinado, mas { $count } assinaturas digitais não puderam ser verificadas
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Documento assinado com { $count } certificado que não é confiável
*[other] Documento assinado com { $count } certificados que não são confiáveis
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Documento assinado com { $count } certificado expirado
*[other] Documento assinado com { $count } certificados expirados
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] O documento tem { $count } assinatura digital inválida
*[other] O documento tem { $count } assinaturas digitais inválidas
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Documento assinado com { $count } certificado revogado
*[other] Documento assinado com { $count } certificados revogados
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: Assinatura verificada
pdfjs-digital-signature-properties-status-invalid = Status: Assinatura inválida
pdfjs-digital-signature-properties-status-unknown = Status: Não foi possível verificar (não há suporte)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certificado: Confiável ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certificado: Não disponível
pdfjs-digital-signature-properties-certificate-untrusted = Certificado: Não confiável
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certificado: Emissor desconhecido ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certificado: Autoassinado ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certificado: Emissor não confiável ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certificado: Expirado
pdfjs-digital-signature-properties-certificate-expired-with-date = Certificado: Expirado ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certificado: Revogado
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,28 @@ pdfjs-document-properties-linearized = Vizualizare web rapidă:
pdfjs-document-properties-linearized-yes = Da
pdfjs-document-properties-linearized-no = Nu
pdfjs-document-properties-close-button = Închide
pdfjs-digital-signature-properties-view-certificate = Vezi certificatul
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Motiv: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Marcaj temporal: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] ({ $count }) sub semnătură
[few] ({ $count }) sub semnături
*[other] ({ $count }) de sub semnături
}
## Print
@ -390,8 +412,9 @@ pdfjs-free-text2 =
# $count (Number) - the number of comments.
pdfjs-editor-comments-sidebar-title =
{ $count ->
[one] Comentariu
*[other] Comentarii
[one] comentariu
[few] comentarii
*[other] de comentarii
}
pdfjs-editor-comments-sidebar-close-button =
.title = Închide bara laterală
@ -739,6 +762,79 @@ pdfjs-views-manager-waiting-for-file = Se încarcă fișierul…
pdfjs-toggle-views-manager-button1 =
.title = Gestionează paginile
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Proprietățile semnăturii digitale
.aria-label = Proprietățile semnăturii digitale
pdfjs-digital-signature-properties-button-label = Proprietățile semnăturii digitale
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Documentul a fost semnat cu o semnătură digitală validă
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Document semnat, dar { $count } semnătură digitală nu au putut fi verificată
[few] Document semnat, dar { $count } semnături digitale nu au putut fi verificate
*[other] Document semnat, dar { $count } de semnături digitale nu au putut fi verificate
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Document semnat cu { $count } certificat care nu este de încredere
[few] Document semnat cu { $count } certificate care nu sunt de încredere
*[other] Document semnat cu { $count } de certificate care nu sunt de încredere
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Document semnat cu { $count } certificat expirat
[few] Document semnat cu { $count } certificate expirate
*[other] Document semnat cu { $count } de certificate expirate
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Documentul are { $count } semnătură digitală nevalidă
[few] Documentul are { $count } semnături digitale nevalide
*[other] Documentul are { $count } de semnături digitale nevalide
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Document semnat cu { $count } certificat revocat
[few] Document semnat cu { $count } certificate revocate
*[other] Document semnat cu { $count } de certificate revocate
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Stare: Semnătură verificată
pdfjs-digital-signature-properties-status-invalid = Stare: Semnătură nevalidă
pdfjs-digital-signature-properties-status-unknown = Stare: Nu se poate verifica (neacceptat)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certificat: De încredere ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certificat: Indisponibil
pdfjs-digital-signature-properties-certificate-untrusted = Certificat: De neîncredere
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certificat: Emitent necunoscut ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certificat: Autosemnat ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certificat: Emitent de neîncredere ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certificat: Expirat
pdfjs-digital-signature-properties-certificate-expired-with-date = Certificat: Expirat ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certificat: Revocat
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,28 @@ pdfjs-document-properties-linearized = Быстрый просмотр в Web:
pdfjs-document-properties-linearized-yes = Да
pdfjs-document-properties-linearized-no = Нет
pdfjs-document-properties-close-button = Закрыть
pdfjs-digital-signature-properties-view-certificate = Просмотреть сертификат
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Причина: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Метка времени: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Дополнительная подпись ({ $count })
[few] Дополнительные подписи ({ $count })
*[many] Дополнительные подписи ({ $count })
}
## Print
@ -740,6 +762,79 @@ pdfjs-views-manager-waiting-for-file = Загрузка файла…
pdfjs-toggle-views-manager-button1 =
.title = Управление страницами
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Свойства цифровой подписи
.aria-label = Свойства цифровой подписи
pdfjs-digital-signature-properties-button-label = Свойства цифровой подписи
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Документ был подписан действительной цифровой подписью
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Документ подписан, но { $count } цифровая подпись не может быть проверены
[few] Документ подписан, но { $count } цифровых подписи не могут быть проверены
*[many] Документ подписан, но { $count } цифровых подписей не могут быть проверены
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Документ, подписанный { $count } недоверенным сертификатом
[few] Документ, подписанный { $count } недоверенными сертификатами
*[many] Документ, подписанный { $count } недоверенных сертификатов
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Документ, подписанный { $count } истёкшим сертификатом
[few] Документ, подписанный { $count } истёкшими сертификатами
*[many] Документ, подписанный { $count } истёкших сертификатов
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Документ имеет { $count } неверную цифровую подпись
[few] Документ имеет { $count } неверных цифровых подписей
*[many] Документ имеет { $count } неверных цифровых подписей
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Документ, подписанный { $count } отозванным сертификатом
[few] Документ, подписанный { $count } отозванными сертификатами
*[many] Документ, подписанный { $count } отозванных сертификатов
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Статус: Подпись проверена
pdfjs-digital-signature-properties-status-invalid = Статус: Подпись недействительна
pdfjs-digital-signature-properties-status-unknown = Статус: Не удалось проверить (не поддерживается)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Сертификат: Доверенный ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Сертификат: Недоступен
pdfjs-digital-signature-properties-certificate-untrusted = Сертификат: Недоверенный
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Сертификат: Неизвестный издатель ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Сертификат: Самоподписанный ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Сертификат: Недоверенный издатель ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Сертификат: Истёк срок действия
pdfjs-digital-signature-properties-certificate-expired-with-date = Сертификат: Истёк срок действия ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Сертификат: Отозван
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -87,6 +87,7 @@ pdfjs-scroll-horizontal-button-label = Iscurrimentu orizontale
pdfjs-scroll-wrapped-button =
.title = Imprea s'iscurrimentu continu
pdfjs-scroll-wrapped-button-label = Iscurrimentu continu
pdfjs-spread-none-button-label = Pàginas individuales
## Document properties dialog
@ -133,6 +134,19 @@ pdfjs-document-properties-linearized = Visualizatzione web lestra:
pdfjs-document-properties-linearized-yes = Eja
pdfjs-document-properties-linearized-no = Nono
pdfjs-document-properties-close-button = Serra
pdfjs-digital-signature-properties-view-certificate = Ammustra su tzertificadu
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Resone: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Data e ora: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
## Print
@ -179,6 +193,15 @@ pdfjs-thumb-page-title =
# $page (Number) - the page number
pdfjs-thumb-page-canvas =
.aria-label = Miniatura de sa pàgina { $page }
# Variables:
# $page (Number) - the page number
pdfjs-thumb-page-checkbox1 =
.title = Seletziona sa pàgina { $page }
# Variables:
# $page (Number) - the page number
# $total (Number) - the number of pages
pdfjs-thumb-page-title1 =
.title = Pàgina { $page } de { $total }
## Find panel button title and messages
@ -197,10 +220,27 @@ pdfjs-find-match-diacritics-checkbox-label = Respeta is diacrìticos
pdfjs-find-entire-word-checkbox-label = Faeddos intreos
pdfjs-find-reached-top = S'est lòmpidu a su cumintzu de su documentu, si sighit dae su bàsciu
pdfjs-find-reached-bottom = Acabbu de su documentu, si sighit dae s'artu
# Variables:
# $current (Number) - the index of the currently active find result
# $total (Number) - the total number of matches in the document
pdfjs-find-match-count =
{ $total ->
[one] { $current } currispondèntzia de { $total }
*[other] { $current } currispondèntzias de { $total }
}
# Variables:
# $limit (Number) - the maximum number of matches
pdfjs-find-match-count-limit =
{ $limit ->
[one] Prus de { $limit } currispondèntzia
*[other] Prus de { $limit } currispondèntzias
}
pdfjs-find-not-found = Testu no agatadu
## Predefined zoom values
pdfjs-page-scale-width = Larghesa de sa pàgina
pdfjs-page-scale-fit = Pàgina intrea
pdfjs-page-scale-auto = Ingrandimentu automàticu
pdfjs-page-scale-actual = Mannària reale
# Variables:
@ -222,6 +262,12 @@ pdfjs-missing-file-error = Ammancat s'archìviu PDF.
pdfjs-unexpected-response-error = Risposta imprevista de su serbidore.
pdfjs-rendering-error = Faddina in sa visualizatzione de sa pàgina.
## Annotations
# Variables:
# $dateObj (Date) - the modification date and time of the annotation
pdfjs-annotation-date-time-string = { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
## Password
pdfjs-password-label = Inserta sa crae pro abèrrere custu archìviu PDF.
@ -234,9 +280,13 @@ pdfjs-web-fonts-disabled = Is tipografias web sunt disativadas: is tipografias i
pdfjs-editor-free-text-button =
.title = Testu
pdfjs-editor-color-picker-free-text-input =
.title = Muda su colore de su testu
pdfjs-editor-free-text-button-label = Testu
pdfjs-editor-ink-button =
.title = Disinnu
pdfjs-editor-color-picker-ink-input =
.title = Muda su colore pro su disinnu
pdfjs-editor-ink-button-label = Disinnu
pdfjs-editor-stamp-button =
.title = Agiunghe o modìfica immàgines
@ -248,6 +298,33 @@ pdfjs-highlight-floating-button1 =
.title = Evidèntzia
.aria-label = Evidèntzia
pdfjs-highlight-floating-button-label = Evidèntzia
pdfjs-comment-floating-button =
.title = Cummenta
.aria-label = Cummenta
pdfjs-comment-floating-button-label = Cummenta
pdfjs-editor-comment-button =
.title = Cummenta
.aria-label = Cummenta
pdfjs-editor-comment-button-label = Cummenta
pdfjs-editor-signature-button =
.title = Agiunghe una firma
pdfjs-editor-signature-button-label = Agiunghe una firma
## Default editor aria labels
# “Highlight” is a noun, the string is used on the editor for highlights.
pdfjs-editor-highlight-editor =
.aria-label = Editore de sutaliniadura
# “Drawing” is a noun, the string is used on the editor for drawings.
pdfjs-editor-ink-editor =
.aria-label = Editore de disinnos
# Used when a signature editor is selected/hovered.
# Variables:
# $description (String) - a string describing/labeling the signature.
pdfjs-editor-signature-editor1 =
.aria-description = Editore de firmas: { $description }
pdfjs-editor-stamp-editor =
.aria-label = Editore de immàgines
## Remove button for the various kind of editor.
@ -259,6 +336,8 @@ pdfjs-editor-remove-stamp-button =
.title = Boga simmàgine
pdfjs-editor-remove-highlight-button =
.title = Boga sevidèntzia
pdfjs-editor-remove-signature-button =
.title = Boga·nche sa firma
##
@ -272,19 +351,47 @@ pdfjs-editor-stamp-add-image-button =
pdfjs-editor-stamp-add-image-button-label = Agiunghe unimmàgine
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Grussària
pdfjs-editor-add-signature-container =
.aria-label = Controllos de firma e firmas sarvadas
pdfjs-editor-signature-add-signature-button =
.title = Agiunghe una firma noa
pdfjs-editor-signature-add-signature-button-label = Agiunghe una firma noa
# Used on the button to use an already saved signature.
# Variables:
# $description (String) - a string describing/labeling the signature.
pdfjs-editor-add-saved-signature-button =
.title = Firma sarvada: { $description }
# .default-content is used as a placeholder in an empty text editor.
pdfjs-free-text2 =
.aria-label = Editore de testu
.default-content = Cumintza a iscrìere…
# Used to show how many comments are present in the pdf file.
# Variables:
# $count (Number) - the number of comments.
pdfjs-editor-comments-sidebar-title =
{ $count ->
[one] Cummentu
*[other] Cummentos
}
pdfjs-editor-comments-sidebar-close-button =
.title = Serra sa barra laterale
.aria-label = Serra sa barra laterale
pdfjs-editor-comments-sidebar-close-button-label = Serra sa barra laterale
# Instructional copy to add a comment by selecting text or an annotations.
pdfjs-editor-comments-sidebar-no-comments1 = As rilevadu una cosa de interessu? Sinnala·dda e agiunghe unu cummentu.
## Alt-text dialog
pdfjs-editor-alt-text-button-label = Testu alternativu
pdfjs-editor-alt-text-edit-button =
.aria-label = Modifica su testu alternativu
pdfjs-editor-alt-text-dialog-label = Sèbera unoptzione
pdfjs-editor-alt-text-dialog-description = Su testu alternativu (“alt text”) est ùtile pro persones chi non podent bìdere simmàgine o cando non benit carrigada.
pdfjs-editor-alt-text-add-description-label = Agiunghe una descritzione
pdfjs-editor-alt-text-mark-decorative-label = Sinnala comente decorativa
pdfjs-editor-alt-text-cancel-button = Annulla
pdfjs-editor-alt-text-save-button = Sarva
pdfjs-editor-alt-text-decorative-tooltip = Sinnalada comente decorativu
## Color picker
@ -304,7 +411,13 @@ pdfjs-editor-colorpicker-pink =
## New alt-text dialog
## Group note for entire feature: Alternative text (alt text) helps when people can't see the image. This feature includes a tool to create alt text automatically using an AI model that works locally on the user's device to preserve privacy.
# This is a button that users can click to open the alt text editor and add alt text when it is not present.
pdfjs-editor-new-alt-text-missing-button =
.aria-label = Mancat su testu alternativu
pdfjs-editor-new-alt-text-missing-button-label = Mancat su testu alternativu
# This is a button that opens up the alt text modal where users should review the alt text that was automatically generated.
pdfjs-editor-new-alt-text-to-review-button =
.aria-label = Revisiona su testu alternativu
pdfjs-editor-new-alt-text-to-review-button-label = Revisiona su testu alternativu
# "Created automatically" is a prefix that will be added to the beginning of any alt text that has been automatically generated. After the colon, the user will see/hear the actual alt text description. If the alt text has been edited by a human, this prefix will not appear.
# Variables:
@ -332,6 +445,19 @@ pdfjs-editor-alt-text-settings-show-dialog-button-label = Mustra deretu sedit
pdfjs-editor-alt-text-settings-show-dialog-description = Tagiudat a assegurare chi totu is immàgines tuas tèngiant unu testu alternativu.
pdfjs-editor-alt-text-settings-close-button = Serra
## "Annotations removed" bar
pdfjs-editor-undo-bar-message-freetext = Testu cantzelladu
pdfjs-editor-undo-bar-message-ink = Disinnu cantzelladu
pdfjs-editor-undo-bar-message-stamp = Immàgine cantzellada
pdfjs-editor-undo-bar-message-signature = Firma cantzellada
pdfjs-editor-undo-bar-undo-button =
.title = Iscontza
pdfjs-editor-undo-bar-undo-button-label = Iscontza
pdfjs-editor-undo-bar-close-button =
.title = Serra
pdfjs-editor-undo-bar-close-button-label = Serra
## Dialog buttons
pdfjs-editor-add-signature-cancel-button = Annulla

View File

@ -153,6 +153,29 @@ pdfjs-document-properties-linearized = Rýchle zobrazovanie z webu:
pdfjs-document-properties-linearized-yes = Áno
pdfjs-document-properties-linearized-no = Nie
pdfjs-document-properties-close-button = Zavrieť
pdfjs-digital-signature-properties-view-certificate = Zobraziť certifikát
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Dôvod: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Časová pečiatka: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Podpodpis ({ $count })
[few] Podpodpisy ({ $count })
[many] Podpodpisy ({ $count })
*[other] Podpodpisy ({ $count })
}
## Print
@ -748,6 +771,84 @@ pdfjs-views-manager-waiting-for-file = Nahráva sa súbor…
pdfjs-toggle-views-manager-button1 =
.title = Spravovať strany
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Vlastnosti digitálneho podpisu
.aria-label = Vlastnosti digitálneho podpisu
pdfjs-digital-signature-properties-button-label = Vlastnosti digitálneho podpisu
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokument bol podpísaný platným digitálnym podpisom
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokument bol podpísaný, ale { $count } digitálny podpis sa nepodarilo overiť
[few] Dokument bol podpísaný, ale { $count } digitálne podpisy sa nepodarilo overiť
[many] Dokument bol podpísaný, ale { $count } digitálnych podpisov sa nepodarilo overiť
*[other] Dokument bol podpísaný, ale { $count } digitálnych podpisov sa nepodarilo overiť
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokument bol podpísaný { $count } certifikátom, ktorý nie je dôveryhodný
[few] Dokument bol podpísaný { $count } certifikátmi, ktoré nie sú dôveryhodné
[many] Dokument bol podpísaný { $count } certifikátmi, ktoré nie sú dôveryhodné
*[other] Dokument bol podpísaný { $count } certifikátmi, ktoré nie sú dôveryhodné
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokument bol podpísaný { $count } certifikátom, ktorému vypršala platnosť
[few] Dokument bol podpísaný { $count } certifikátmi, ktorých platnosť vypršala
[many] Dokument bol podpísaný { $count } certifikátmi, ktorých platnosť vypršala
*[other] Dokument bol podpísaný { $count } certifikátmi, ktorých platnosť vypršala
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokument má { $count } neplatný digitálny podpis
[few] Dokument má { $count } neplatné digitálne podpisy
[many] Dokument má { $count } neplatných digitálnych podpisov
*[other] Dokument má { $count } neplatných digitálnych podpisov
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokument bol podpísaný { $count } zrušeným certifikátom
[few] Dokument bol podpísaný { $count } zrušenými certifikátmi
[many] Dokument bol podpísaný { $count } zrušenými certifikátmi
*[other] Dokument bol podpísaný { $count } zrušenými certifikátmi
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Stav: Podpis overený
pdfjs-digital-signature-properties-status-invalid = Stav: Podpis neplatný
pdfjs-digital-signature-properties-status-unknown = Stav: Nedá sa overiť (nepodporovaný)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certifikát: Dôveryhodný ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certifikát: Nie je k dispozícii
pdfjs-digital-signature-properties-certificate-untrusted = Certifikát: Nedôveryhodný
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certifikát: Neznámy vydavateľ ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certifikát: Samopodpísaný ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certifikát: Nedôveryhodný vydavateľ ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certifikát: Platnosť vypršala
pdfjs-digital-signature-properties-certificate-expired-with-date = Certifikát: Platnosť vypršala ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certifikát: Zrušený
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -132,8 +132,8 @@ pdfjs-document-properties-page-size-orientation-portrait = pokončno
pdfjs-document-properties-page-size-orientation-landscape = ležeče
pdfjs-document-properties-page-size-name-a-three = A3
pdfjs-document-properties-page-size-name-a-four = A4
pdfjs-document-properties-page-size-name-letter = Pismo
pdfjs-document-properties-page-size-name-legal = Pravno
pdfjs-document-properties-page-size-name-letter = Letter
pdfjs-document-properties-page-size-name-legal = Legal
## Variables:
## $width (Number) - the width of the (current) page
@ -153,6 +153,29 @@ pdfjs-document-properties-linearized = Hitri spletni ogled:
pdfjs-document-properties-linearized-yes = Da
pdfjs-document-properties-linearized-no = Ne
pdfjs-document-properties-close-button = Zapri
pdfjs-digital-signature-properties-view-certificate = Ogled digitalnega potrdila
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Razlog: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Časovni žig: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Podpodpis ({ $count })
[two] Podpodpisi ({ $count })
[few] Podpodpisi ({ $count })
*[other] Podpodpisi ({ $count })
}
## Print
@ -748,6 +771,23 @@ pdfjs-views-manager-waiting-for-file = Nalaganje datoteke …
pdfjs-toggle-views-manager-button1 =
.title = Upravljanje strani
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Lastnosti digitalnega podpisa
.aria-label = Lastnosti digitalnega podpisa
pdfjs-digital-signature-properties-button-label = Lastnosti digitalnega podpisa
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokument je bil podpisan z veljavnim digitalnim podpisom
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,28 @@ pdfjs-document-properties-linearized = Брз веб приказ:
pdfjs-document-properties-linearized-yes = Да
pdfjs-document-properties-linearized-no = Не
pdfjs-document-properties-close-button = Затвори
pdfjs-digital-signature-properties-view-certificate = Прикажи сертификат
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Разлог: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Временски жиг: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Подпотпис ({ $count })
[few] Подпотписа ({ $count })
*[other] Подпотписа ({ $count })
}
## Print
@ -740,6 +762,79 @@ pdfjs-views-manager-waiting-for-file = Отпремам датотеку…
pdfjs-toggle-views-manager-button1 =
.title = Управљај страницама
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Својства дигиталног потписа
.aria-label = Својства дигиталног потписа
pdfjs-digital-signature-properties-button-label = Својства дигиталног потписа
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Документ је потписан исправним дигиталним потписом
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Документ је потписан, али { $count } дигитални потпис није могао да се потврди
[few] Документ је потписан, али { $count } дигитална потписа нису могли да се потврде
*[other] Документ је потписан, али { $count } дигиталних потписа није могло да се потврде
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Документ је потписан са { $count } сертификатом који није поуздан
[few] Документ је потписан са { $count } сертификата који нису поуздани
*[other] Документ је потписан са { $count } сертификата који нису поуздани
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Документ је потписан са { $count } истеклим сертификатом
[few] Документ је потписан са { $count } истекла сертификата
*[other] Документ је потписан са { $count } истеклих сертификата
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Документ има { $count } неважећи дигитални потпис
[few] Документ има { $count } неважећа дигитална потписа
*[other] Документ има { $count } неважећих дигиталних потписа
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Документ је потписан са { $count } опозваним сертификатом
[few] Документ је потписан са { $count } опозвана сертификата
*[other] Документ је потписан са { $count } опозваних сертификата
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Статус: потврђен потпис
pdfjs-digital-signature-properties-status-invalid = Статус: неважећи потпис
pdfjs-digital-signature-properties-status-unknown = Статус: није могуће потврдити (неподржано)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Сертификат: поуздан ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Сертификат: недоступан
pdfjs-digital-signature-properties-certificate-untrusted = Сертификат: неповерљив
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Сертификат: непознат издавач ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Сертификат: самопотписан ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Сертификат: неповерљив издавач ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Сертификат: истекао
pdfjs-digital-signature-properties-certificate-expired-with-date = Сертификат: истекао ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Сертификат: опозван
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Snabb webbvisning:
pdfjs-document-properties-linearized-yes = Ja
pdfjs-document-properties-linearized-no = Nej
pdfjs-document-properties-close-button = Stäng
pdfjs-digital-signature-properties-view-certificate = Visa certifikat
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Orsak: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Tidsstämpel: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Undersignatur ({ $count })
*[other] Undersignaturer ({ $count })
}
## Print
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Överför fil…
pdfjs-toggle-views-manager-button1 =
.title = Hantera sidor
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Egenskaper för digital signatur
.aria-label = Egenskaper för digital signatur
pdfjs-digital-signature-properties-button-label = Egenskaper för digital signatur
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Dokumentet signerades med en giltig digital signatur
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Dokument signerat men { $count } digital signatur kunde inte verifieras
*[other] Dokument signerat men { $count } digitala signaturer kunde inte verifieras
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Dokument signerat med { $count } certifikat som inte är tillförlitligt
*[other] Dokument signerat med { $count } certifikat som inte är tillförlitliga
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Dokument signerat med { $count } utgånget certifikat
*[other] Dokument signerat med { $count } utgångna certifikat
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Dokumentet har { $count } ogiltig digital signatur
*[other] Dokumentet har { $count } ogiltiga digitala signaturer
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Dokument signerat med { $count } återkallat certifikat
*[other] Dokument signerat med { $count } återkallade certifikat
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Status: Signatur verifierad
pdfjs-digital-signature-properties-status-invalid = Status: Ogiltig signatur
pdfjs-digital-signature-properties-status-unknown = Status: Kan inte verifiera (stöds inte)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Certifikat: Tillförlitligt ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Certifikat: Ej tillgänglig
pdfjs-digital-signature-properties-certificate-untrusted = Certifikat: Otillförlitligt
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Certifikat: Okänd utfärdare ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Certifikat: Självsignerat ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Certifikat: Otillförlitlig utfärdare ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Certifikat: Utgånget
pdfjs-digital-signature-properties-certificate-expired-with-date = Certifikat: Utgånget ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Certifikat: Återkallat
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,27 @@ pdfjs-document-properties-linearized = Hızlı web görünümü:
pdfjs-document-properties-linearized-yes = Evet
pdfjs-document-properties-linearized-no = Hayır
pdfjs-document-properties-close-button = Kapat
pdfjs-digital-signature-properties-view-certificate = Sertifikayı göster
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Neden: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Zaman damgası: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures =
{ $count ->
[one] Alt imza ({ $count })
*[other] Alt imzalar ({ $count })
}
## Print
@ -496,11 +517,11 @@ pdfjs-editor-new-alt-text-added-button =
pdfjs-editor-new-alt-text-added-button-label = Alt metin eklendi
# This is a button that users can click to open the alt text editor and add alt text when it is not present.
pdfjs-editor-new-alt-text-missing-button =
.aria-label = Alternatif metin eksik
.aria-label = Alt metin eksik
pdfjs-editor-new-alt-text-missing-button-label = Alt metin eksik
# This is a button that opens up the alt text modal where users should review the alt text that was automatically generated.
pdfjs-editor-new-alt-text-to-review-button =
.aria-label = Alternatif metni incele
.aria-label = Alt metni incele
pdfjs-editor-new-alt-text-to-review-button-label = Alt metni incele
# "Created automatically" is a prefix that will be added to the beginning of any alt text that has been automatically generated. After the colon, the user will see/hear the actual alt text description. If the alt text has been edited by a human, this prefix will not appear.
# Variables:
@ -732,6 +753,74 @@ pdfjs-views-manager-waiting-for-file = Dosya yükleniyor…
pdfjs-toggle-views-manager-button1 =
.title = Sayfaları yönet
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Dijital imza özellikleri
.aria-label = Dijital imza özellikleri
pdfjs-digital-signature-properties-button-label = Dijital imza özellikleri
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Belge geçerli bir dijital imza ile imzalanmıştır
pdfjs-digital-signature-properties-banner-unknown =
{ $count ->
[one] Belge imzalanmış ancak { $count } dijital imza doğrulanamadı
*[other] Belge imzalanmış ancak { $count } dijital imza doğrulanamadı
}
pdfjs-digital-signature-properties-banner-untrusted =
{ $count ->
[one] Belge, güvenilmeyen { $count } sertifikayla imzalanmış
*[other] Belge, güvenilmeyen { $count } sertifikayla imzalanmış
}
pdfjs-digital-signature-properties-banner-expired =
{ $count ->
[one] Belge, süresi dolmuş { $count } sertifika ile imzalanmış
*[other] Belge, süresi dolmuş { $count } sertifika ile imzalanmış
}
pdfjs-digital-signature-properties-banner-invalid =
{ $count ->
[one] Belge { $count } geçersiz dijital imza içeriyor
*[other] Belge { $count } geçersiz dijital imza içeriyor
}
pdfjs-digital-signature-properties-banner-revoked =
{ $count ->
[one] Belge, iptal edilmiş { $count } sertifika ile imzalanmış
*[other] Belge, iptal edilmiş { $count } sertifika ile imzalanmış
}
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Durum: İmza doğrulandı
pdfjs-digital-signature-properties-status-invalid = Durum: İmza geçersiz
pdfjs-digital-signature-properties-status-unknown = Durum: Doğrulanamadı (desteklenmiyor)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Sertifika: Güvenilir ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Sertifika: Kullanılamıyor
pdfjs-digital-signature-properties-certificate-untrusted = Sertifika: Güvensiz
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Sertifika: Bilinmeyen yayıncı ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Sertifika: Kendi kendine imzalanmış ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Sertifika: Güvenilmeyen yayıncı ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Sertifika: Süresi dolmuş
pdfjs-digital-signature-properties-certificate-expired-with-date = Sertifika: Süresi dolmuş ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Sertifika: İptal edilmiş
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,23 @@ pdfjs-document-properties-linearized = Xem nhanh trên web:
pdfjs-document-properties-linearized-yes = Có
pdfjs-document-properties-linearized-no = Không
pdfjs-document-properties-close-button = Ðóng
pdfjs-digital-signature-properties-view-certificate = Xem chứng chỉ
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = Nguyên nhân: { $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = Timestamp: { DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures = Chữ ký thành phần ({ $count })
## Print
@ -469,7 +486,7 @@ pdfjs-editor-new-alt-text-description = Mô tả ngắn gọn dành cho người
pdfjs-editor-new-alt-text-disclaimer1 = Văn bản thay thế này được tạo tự động và có thể không chính xác.
pdfjs-editor-new-alt-text-disclaimer-learn-more-url = Tìm hiểu thêm
pdfjs-editor-new-alt-text-create-automatically-button-label = Tạo văn bản thay thế tự động
pdfjs-editor-new-alt-text-not-now-button = Không phải bây giờ
pdfjs-editor-new-alt-text-not-now-button = Để sau
pdfjs-editor-new-alt-text-error-title = Không thể tạo tự động văn bản thay thế
pdfjs-editor-new-alt-text-error-description = Vui lòng viết văn bản thay thế của riêng bạn hoặc thử lại sau.
pdfjs-editor-new-alt-text-error-close-button = Đóng
@ -700,6 +717,54 @@ pdfjs-views-manager-waiting-for-file = Đang tải lên tập tin…
pdfjs-toggle-views-manager-button1 =
.title = Quản lý trang
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = Thuộc tính chữ ký điện tử
.aria-label = Thuộc tính chữ ký điện tử
pdfjs-digital-signature-properties-button-label = Thuộc tính chữ ký điện tử
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = Tài liệu đã được ký bằng chữ ký điện tử hợp lệ
pdfjs-digital-signature-properties-banner-unknown = Tài liệu đã được ký nhưng không thể xác minh { $count } chữ ký điện tử
pdfjs-digital-signature-properties-banner-untrusted = Tài liệu được ký bằng { $count } chứng chỉ không đáng tin cậy
pdfjs-digital-signature-properties-banner-expired = Tài liệu được ký bằng { $count } chứng chỉ đã hết hạn
pdfjs-digital-signature-properties-banner-invalid = Tài liệu có { $count } chữ ký điện tử không hợp lệ
pdfjs-digital-signature-properties-banner-revoked = Tài liệu được ký bằng { $count } chứng chỉ đã bị thu hồi
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = Trạng thái: Chữ ký đã được xác minh
pdfjs-digital-signature-properties-status-invalid = Trạng thái: Chữ ký không hợp lệ
pdfjs-digital-signature-properties-status-unknown = Trạng thái: Không thể xác minh (không được hỗ trợ)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = Chứng chỉ: Đáng tin cậy ({ $issuer })
pdfjs-digital-signature-properties-certificate-unknown = Chứng chỉ: Không khả dụng
pdfjs-digital-signature-properties-certificate-untrusted = Chứng chỉ: Không đáng tin cậy
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = Chứng chỉ: Người cấp không xác định ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = Chứng chỉ: Tự ký ({ $issuer })
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = Chứng chỉ: Người cấp không đáng tin cậy ({ $issuer })
pdfjs-digital-signature-properties-certificate-expired = Chứng chỉ: Đã hết hạn
pdfjs-digital-signature-properties-certificate-expired-with-date = Chứng chỉ: Đã hết hạn ({ DATETIME($dateObj, dateStyle: "medium") })
pdfjs-digital-signature-properties-certificate-revoked = Chứng chỉ: Đã bị thu hồi
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

View File

@ -153,6 +153,19 @@ pdfjs-document-properties-linearized = 快速 Web 视图:
pdfjs-document-properties-linearized-yes = 是
pdfjs-document-properties-linearized-no = 否
pdfjs-document-properties-close-button = 关闭
pdfjs-digital-signature-properties-view-certificate = 查看证书
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = 原因:{ $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = 时间戳:{ DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
## Print

View File

@ -153,6 +153,23 @@ pdfjs-document-properties-linearized = 快速 Web 檢視:
pdfjs-document-properties-linearized-yes = 是
pdfjs-document-properties-linearized-no = 否
pdfjs-document-properties-close-button = 關閉
pdfjs-digital-signature-properties-view-certificate = 檢視憑證
# Shown beneath an invalid signature card to explain why verification
# failed. The text comes from NSS (e.g. "Signature integrity has been
# compromised", "PKCS#7 signature could not be parsed") and is not
# itself localized — it is the underlying error message produced by
# the verification backend.
# Variables:
# $reason (String) - error message describing why the signature
# could not be verified.
pdfjs-digital-signature-properties-reason = 原因:{ $reason }
# Variables:
# $dateObj (Date) - the signing time from the /Sig dict's /M entry.
pdfjs-digital-signature-properties-timestamp = 時間戳記:{ DATETIME($dateObj, dateStyle: "short", timeStyle: "medium") }
# Variables:
# $count (Number) - number of nested sub-signatures (one per earlier
# incremental revision of the document).
pdfjs-digital-signature-properties-sub-signatures = 子簽章({ $count }
## Print
@ -700,6 +717,54 @@ pdfjs-views-manager-waiting-for-file = 正在上傳檔案…
pdfjs-toggle-views-manager-button1 =
.title = 管理頁面
## Digital signature properties (signature verification panel)
pdfjs-digital-signature-properties-button =
.title = 數位簽章屬性
.aria-label = 數位簽章屬性
pdfjs-digital-signature-properties-button-label = 數位簽章屬性
## Banner shown above the signature list summarising the overall
## verification state of the document. Each variant is selected by the
## viewer based on the worst per-signature status; one signature is
## enough to lower the banner.
##
## Variables:
## $count (Number) - number of signatures at the worst level.
pdfjs-digital-signature-properties-banner-verified = 文件使用有效的數位簽章進行簽署
pdfjs-digital-signature-properties-banner-unknown = 文件已進行簽署,但無法驗證當中的 { $count } 筆數位簽章
pdfjs-digital-signature-properties-banner-untrusted = 文件已進行簽署,但當中的 { $count } 筆數位簽章不受信任
pdfjs-digital-signature-properties-banner-expired = 文件已進行簽署,但當中的 { $count } 筆數位簽章已過期
pdfjs-digital-signature-properties-banner-invalid = 文件中有 { $count } 筆無效的數位簽章
pdfjs-digital-signature-properties-banner-revoked = 文件已進行簽署,但當中的 { $count } 筆數位簽章已廢止
## Per-signature status row. Only three distinct strings are needed:
## the signature crypto either verified (the cert chain may still be
## untrusted/expired/revoked, but that's surfaced on the cert row
## below), or it failed, or its sub-format isn't supported.
pdfjs-digital-signature-properties-status-verified = 狀態:已驗證簽章
pdfjs-digital-signature-properties-status-invalid = 狀態:簽章無效
pdfjs-digital-signature-properties-status-unknown = 狀態:無法驗證(不支援)
## Per-signature certificate row. The variants with an issuer / date in
## parentheses embed fully-localized context — no English fall-through.
##
## Variables:
## $issuer (String) - issuer or subject common name from the cert.
## $dateObj (Date) - notAfter date for the expired-with-date form.
pdfjs-digital-signature-properties-certificate-trusted = 憑證:受信任({ $issuer }
pdfjs-digital-signature-properties-certificate-unknown = 憑證:無法使用
pdfjs-digital-signature-properties-certificate-untrusted = 憑證:未受信任
pdfjs-digital-signature-properties-certificate-untrusted-unknown-issuer = 憑證:未知的簽發者({ $issuer }
pdfjs-digital-signature-properties-certificate-untrusted-self-signed = 憑證:自行簽署({ $issuer }
pdfjs-digital-signature-properties-certificate-untrusted-untrusted-issuer = 憑證:未受信任的簽發者({ $issuer }
pdfjs-digital-signature-properties-certificate-expired = 憑證:已過期
pdfjs-digital-signature-properties-certificate-expired-with-date = 憑證:已過期({ DATETIME($dateObj, dateStyle: "medium") }
pdfjs-digital-signature-properties-certificate-revoked = 憑證:已廢止
## Main menu for adding/removing signatures
pdfjs-editor-delete-signature-button1 =

4478
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,33 +2,33 @@
"name": "pdf.js",
"type": "module",
"devDependencies": {
"@babel/core": "^7.29.0",
"@babel/preset-env": "^7.29.5",
"@babel/runtime": "^7.29.2",
"@eslint/json": "^1.2.0",
"@babel/core": "^8.0.1",
"@babel/preset-env": "^8.0.2",
"@babel/runtime": "^8.0.0",
"@eslint/json": "^2.0.1",
"@fluent/bundle": "^0.19.1",
"@fluent/dom": "^0.10.2",
"@metalsmith/layouts": "^3.0.0",
"@metalsmith/markdown": "^1.10.0",
"@napi-rs/canvas": "^1.0.0",
"@types/node": "^25.9.1",
"autoprefixer": "^10.5.0",
"@napi-rs/canvas": "^1.0.3",
"@types/node": "^26.1.2",
"autoprefixer": "^10.5.4",
"babel-loader": "^10.1.1",
"babel-plugin-add-header-comment": "^1.0.3",
"babel-plugin-istanbul": "^8.0.0",
"babel-plugin-istanbul": "^8.0.2",
"babel-plugin-polyfill-corejs3": "^1.0.0",
"cached-iterable": "^0.3.0",
"caniuse-lite": "^1.0.30001793",
"caniuse-lite": "^1.0.30001806",
"core-js": "^3.49.0",
"eslint": "^10.4.0",
"eslint": "^10.8.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import-x": "^4.16.2",
"eslint-plugin-import-x": "^4.17.1",
"eslint-plugin-jasmine": "^4.2.2",
"eslint-plugin-no-unsanitized": "^4.1.5",
"eslint-plugin-perfectionist": "^5.9.0",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-regexp": "^3.1.0",
"eslint-plugin-unicorn": "^64.0.0",
"globals": "^17.6.0",
"eslint-plugin-perfectionist": "^5.10.0",
"eslint-plugin-prettier": "^5.5.6",
"eslint-plugin-regexp": "^3.1.1",
"eslint-plugin-unicorn": "^72.0.0",
"globals": "^17.8.0",
"gulp": "^5.0.1",
"gulp-cli": "^3.1.0",
"gulp-postcss": "^10.0.0",
@ -39,28 +39,28 @@
"istanbul-lib-coverage": "^3.2.2",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.2.0",
"jasmine": "^6.2.0",
"jasmine": "^6.3.0",
"jsdoc": "^4.0.5",
"jstransformer-nunjucks": "^1.2.0",
"kleur": "^4.1.5",
"metalsmith": "^2.7.0",
"metalsmith-html-relative": "^2.0.12",
"metalsmith-html-relative": "^2.0.13",
"ordered-read-streams": "^2.0.0",
"pngjs": "^7.0.0",
"postcss": "^8.5.15",
"postcss-discard-comments": "^8.0.0",
"postcss": "^8.5.25",
"postcss-discard-comments": "^8.0.1",
"postcss-values-parser": "^8.0.0",
"prettier": "^3.8.3",
"puppeteer": "^25.1.0",
"stylelint": "^17.12.0",
"prettier": "^3.9.6",
"puppeteer": "^25.4.0",
"stylelint": "^17.14.1",
"stylelint-prettier": "^5.0.3",
"svglint": "^4.2.1",
"terser-webpack-plugin": "^5.6.0",
"tsc-alias": "^1.8.17",
"terser-webpack-plugin": "^5.6.1",
"tsc-alias": "^1.9.1",
"ttest": "^4.0.0",
"typescript": "^6.0.3",
"vinyl": "^3.0.1",
"webpack": "^5.107.1",
"webpack": "^5.109.2",
"webpack-stream": "^7.0.0"
},
"repository": {

View File

@ -1,5 +1,5 @@
{
"stableVersion": "5.7.284",
"baseVersion": "e6e06cf6b5307fe39e0de69c6c884f816b0cb21b",
"versionPrefix": "6.0."
"stableVersion": "6.2.108",
"baseVersion": "ce4ff55faaa83b39b0137dc458af6eea6f96235f",
"versionPrefix": "6.3."
}

File diff suppressed because it is too large Load Diff

View File

@ -25,11 +25,17 @@ class BaseStream {
}
}
/**
* @returns {number}
*/
// eslint-disable-next-line getter-return
get length() {
unreachable("Abstract getter `length` accessed");
}
/**
* @returns {boolean}
*/
// eslint-disable-next-line getter-return
get isEmpty() {
unreachable("Abstract getter `isEmpty` accessed");
@ -43,6 +49,10 @@ class BaseStream {
unreachable("Abstract method `getByte` called");
}
/**
* @param {number | undefined} [length]
* @returns {Uint8Array}
*/
getBytes(length) {
unreachable("Abstract method `getBytes` called");
}
@ -135,6 +145,10 @@ class BaseStream {
unreachable("Abstract method `makeSubStream` called");
}
clone() {
unreachable("Abstract method `clone` called");
}
/**
* @returns {Array | null}
*/

View File

@ -75,7 +75,7 @@ function calculateMD5(data, offset, length) {
i += 3;
const w = new Int32Array(16);
const { k, r } = PARAMS;
for (i = 0; i < paddedLength; ) {
for (i = 0; i < paddedLength;) {
for (j = 0; j < 16; ++j, i += 4) {
w[j] =
padded[i] |

View File

@ -96,7 +96,7 @@ function calculateSHA256(data, offset, length) {
const w = new Uint32Array(64);
const { k } = PARAMS;
// for each 512 bit block
for (i = 0; i < paddedLength; ) {
for (i = 0; i < paddedLength;) {
for (j = 0; j < 16; ++j) {
w[j] =
(padded[i] << 24) |

View File

@ -303,7 +303,7 @@ function calculateSHA512(data, offset, length, mode384 = false) {
let tmp3;
// for each 1024 bit block
for (i = 0; i < paddedLength; ) {
for (i = 0; i < paddedLength;) {
for (j = 0; j < 16; ++j) {
w[j].high =
(padded[i] << 24) |

View File

@ -19,7 +19,7 @@ import {
DocumentActionEventType,
FormatError,
info,
objectSize,
makeArr,
PermissionFlag,
shadow,
stringToUTF8String,
@ -52,9 +52,41 @@ import { clearGlobalCaches } from "./cleanup_helper.js";
import { ColorSpaceUtils } from "./colorspace_utils.js";
import { FileSpec } from "./file_spec.js";
import { MetadataParser } from "./metadata_parser.js";
import { soundStreamToWav } from "./sound.js";
import { stringToPDFString } from "./string_utils.js";
import { StructTreeRoot } from "./struct_tree.js";
/**
* @import {XRef} from "./xref.js";
*/
/**
* @callback GetAttachmentContent
* Callback used to lazily fetch attachment content.
* @param {string} id
* Unique attachment identifier.
* @returns {CatalogAttachmentContent}
* Result.
*/
/**
* @typedef {Uint8Array | null} CatalogAttachmentContent
* Attachment value.
*/
/**
* @typedef CatalogAttachment
* Attachment metadata.
* @property {CatalogAttachmentContent | undefined} [content]
* Value, when already available.
* @property {string} description
* Description.
* @property {string} filename
* Filename (just the basename) for display.
* @property {string} rawFilename
* File path.
*/
const isRef = v => v instanceof Ref;
const isValidExplicitDest = _isValidExplicitDest.bind(
@ -88,6 +120,12 @@ function fetchRemoteDest(action) {
class Catalog {
#actualNumPages = null;
#annotationAttachmentIdByRef = new RefSetCache();
#annotationAttachmentRefById = new Map();
#soundAttachmentIds = new Set();
#catDict = null;
builtInCMapCache = new Map();
@ -127,6 +165,44 @@ class Catalog {
return this.#catDict.clone();
}
/**
* Create an id for an attachment from a FileAttachment annotation.
*
* The id is registered here rather than parsed from a public string prefix in
* `attachmentContent`, since catalog attachment names can be arbitrary PDF
* strings and may otherwise collide with annotation-local ids.
*
* @param {Ref} ref
* File-spec or embedded-file stream reference.
* @param {boolean} [isSound]
* When set, the referenced stream holds raw PDF sound samples that
* `attachmentContent` wraps in a WAV container on fetch.
* @returns {string}
* Attachment id.
*/
getAttachmentIdForAnnotation(ref, isSound = false) {
let id = this.#annotationAttachmentIdByRef.get(ref);
if (!id) {
const baseId = `attachmentRef:${ref.toString()}`;
id = baseId;
let i = 1;
while (
this.#annotationAttachmentRefById.has(id) ||
this.attachments?.has(id)
) {
id = `${baseId}-${i++}`;
}
this.#annotationAttachmentIdByRef.put(ref, id);
this.#annotationAttachmentRefById.set(id, ref);
}
if (isSound) {
this.#soundAttachmentIds.add(id);
}
return id;
}
get version() {
const version = this.#catDict.get("Version");
if (version instanceof Name) {
@ -210,11 +286,11 @@ class Catalog {
/* suppressEncryption = */ !this.xref.encrypt?.encryptMetadata
);
if (stream instanceof BaseStream && stream.dict instanceof Dict) {
const type = stream.dict.get("Type");
const subtype = stream.dict.get("Subtype");
if (isName(type, "Metadata") && isName(subtype, "XML")) {
if (
stream instanceof BaseStream &&
isDict(stream.dict, "Metadata") &&
isName(stream.dict.get("Subtype"), "XML")
) {
// XXX: This should examine the charset the XML document defines,
// however since there are currently no real means to decode arbitrary
// charsets, let's just hope that the author of the PDF was reasonable
@ -224,7 +300,6 @@ class Catalog {
metadata = new MetadataParser(data).serializable;
}
}
}
} catch (ex) {
if (ex instanceof MissingDataException) {
throw ex;
@ -286,15 +361,11 @@ class Catalog {
}
#readStructTreeRoot() {
const rawObj = this.#catDict.getRaw("StructTreeRoot");
const obj = this.xref.fetchIfRef(rawObj);
if (!(obj instanceof Dict)) {
return null;
}
const root = new StructTreeRoot(this.xref, obj, rawObj);
root.init();
return root;
const rawObj = this.#catDict.getRaw("StructTreeRoot"),
obj = this.xref.fetchIfRef(rawObj);
return obj instanceof Dict
? new StructTreeRoot(this.xref, obj, rawObj)
: null;
}
get toplevelPagesDict() {
@ -369,6 +440,7 @@ class Catalog {
const outlineItem = {
action: data.action,
attachmentId: data.attachmentId,
attachment: data.attachment,
dest: data.dest,
url: data.url,
@ -691,15 +763,17 @@ class Catalog {
}
get destinations() {
const rawDests = this.#readDests(),
dests = Object.create(null);
for (const obj of rawDests) {
const dests = new Map();
for (const obj of this.#readDests()) {
if (obj instanceof NameTree) {
for (const [key, value] of obj.getAll()) {
const dest = fetchDest(value);
if (dest) {
dests[stringToPDFString(key, /* keepEscapeSequence = */ true)] =
dest;
dests.set(
stringToPDFString(key, /* keepEscapeSequence = */ true),
dest
);
}
}
} else if (obj instanceof Dict) {
@ -707,8 +781,10 @@ class Catalog {
const dest = fetchDest(value);
if (dest) {
// Always let the NameTree take precedence.
dests[stringToPDFString(key, /* keepEscapeSequence = */ true)] ||=
dest;
dests.getOrInsert(
stringToPDFString(key, /* keepEscapeSequence = */ true),
dest
);
}
}
}
@ -719,11 +795,10 @@ class Catalog {
getDestination(id) {
// Avoid extra lookup/parsing when all destinations are already available.
if (Object.hasOwn(this, "destinations")) {
return this.destinations[id] ?? null;
return this.destinations.get(id) ?? null;
}
const rawDests = this.#readDests();
for (const obj of rawDests) {
for (const obj of this.#readDests()) {
if (obj instanceof NameTree || obj instanceof Dict) {
const dest = fetchDest(obj.get(id));
if (dest) {
@ -735,13 +810,7 @@ class Catalog {
// Always fallback to checking all destinations, in order to support:
// - PDF documents with out-of-order NameTrees (fixes issue 10272).
// - Destination keys that use PDFDocEncoding (fixes issue 19835).
if (rawDests.length) {
const dest = this.destinations[id];
if (dest) {
return dest;
}
}
return null;
return this.destinations.get(id) ?? null;
}
#readDests() {
@ -1007,18 +1076,19 @@ class Catalog {
break;
case "PrintPageRange":
// The number of elements must be even.
if (Array.isArray(value) && value.length % 2 === 0) {
const isValid = value.every(
if (
Array.isArray(value) &&
value.length % 2 === 0 &&
value.every(
(page, i, arr) =>
Number.isInteger(page) &&
page > 0 &&
(i === 0 || page >= arr[i - 1]) &&
page <= this.numPages
);
if (isValid) {
)
) {
prefValue = value;
}
}
break;
case "NumCopies":
if (Number.isInteger(value) && value > 0) {
@ -1034,15 +1104,14 @@ class Catalog {
warn(`Bad value, for key "${key}", in ViewerPreferences: ${value}.`);
continue;
}
prefs ??= Object.create(null);
prefs[key] = prefValue;
(prefs ??= new Map()).set(key, prefValue);
}
return shadow(this, "viewerPreferences", prefs);
}
get openAction() {
const obj = this.#catDict.get("OpenAction");
const openAction = Object.create(null);
const openAction = new Map();
if (obj instanceof Dict) {
// Convert the OpenAction dictionary into a format that works with
@ -1054,36 +1123,92 @@ class Catalog {
Catalog.parseDestDictionary({ destDict, resultObj });
if (Array.isArray(resultObj.dest)) {
openAction.dest = resultObj.dest;
openAction.set("dest", resultObj.dest);
} else if (resultObj.action) {
openAction.action = resultObj.action;
openAction.set("action", resultObj.action);
}
} else if (isValidExplicitDest(obj)) {
openAction.dest = obj;
openAction.set("dest", obj);
}
return shadow(
this,
"openAction",
objectSize(openAction) > 0 ? openAction : null
);
return shadow(this, "openAction", openAction.size ? openAction : null);
}
/**
* Get attachments.
*
* @returns {Map<string, CatalogAttachment> | null}
* Attachments.
*/
get attachments() {
const obj = this.#catDict.get("Names");
/** @type {Map<string, CatalogAttachment> | null} */
let attachments = null;
if (obj instanceof Dict && obj.has("EmbeddedFiles")) {
const nameTree = new NameTree(obj.getRaw("EmbeddedFiles"), this.xref);
for (const [key, value] of nameTree.getAll()) {
const fs = new FileSpec(value);
attachments ??= Object.create(null);
attachments[stringToPDFString(key, /* keepEscapeSequence = */ true)] =
fs.serializable;
(attachments ??= new Map()).set(
stringToPDFString(key, /* keepEscapeSequence = */ true),
new FileSpec(value).serializable
);
}
}
return shadow(this, "attachments", attachments);
}
/**
* @param {string} id
* Unique attachment identifier.
* @returns {CatalogAttachmentContent | undefined}
* Content, or `undefined` when no named attachment exists for the id.
*/
#attachmentContentByName(id) {
const obj = this.#catDict.get("Names");
if (obj instanceof Dict && obj.has("EmbeddedFiles")) {
const nameTree = new NameTree(obj.getRaw("EmbeddedFiles"), this.xref);
for (const [key, value] of nameTree.getAll()) {
if (stringToPDFString(key, /* keepEscapeSequence = */ true) === id) {
return FileSpec.readContent(value);
}
}
}
return undefined;
}
/**
* Get content for an attachment.
*
* @param {string} id
* Unique attachment identifier (required).
* @returns {CatalogAttachmentContent}
* Content.
*/
attachmentContent(id) {
const namedContent = this.#attachmentContentByName(id);
if (namedContent !== undefined) {
return namedContent;
}
// Annotation-local attachments register the reference of their embedded
// content in the catalog, so it's re-fetched from the xref on demand
// instead of being cached (which would then need to survive `cleanup`).
// The reference points either at the file-spec dictionary or, for an inline
// file-spec, straight at the embedded-file stream.
const ref = this.#annotationAttachmentRefById.get(id);
if (ref) {
const target = this.xref.fetch(ref);
if (target instanceof BaseStream) {
const content = FileSpec.readStreamContent(target);
if (this.#soundAttachmentIds.has(id)) {
return soundStreamToWav(target, content) ?? content;
}
return content;
}
return target instanceof Dict ? FileSpec.readContent(target) : null;
}
return null;
}
get rawEmbeddedFiles() {
const obj = this.#catDict.get("Names");
if (!(obj instanceof Dict) || !obj.has("EmbeddedFiles")) {
@ -1117,13 +1242,9 @@ class Catalog {
let javaScript = null;
function appendIfJavaScriptDict(name, jsDict) {
if (!(jsDict instanceof Dict)) {
if (!(jsDict instanceof Dict) || !isName(jsDict.get("S"), "JavaScript")) {
return;
}
if (!isName(jsDict.get("S"), "JavaScript")) {
return;
}
let js = jsDict.get("JS");
if (js instanceof BaseStream) {
js = js.getString();
@ -1136,7 +1257,7 @@ class Catalog {
);
// Skip empty entries, similar to the `_collectJS` function.
if (js) {
(javaScript ||= new Map()).set(name, js);
(javaScript ??= new Map()).set(name, js);
}
}
@ -1167,14 +1288,10 @@ class Catalog {
);
if (javaScript) {
actions ||= Object.create(null);
actions ??= new Map();
for (const [key, val] of javaScript) {
if (key in actions) {
actions[key].push(val);
} else {
actions[key] = [val];
}
actions.getOrInsertComputed(key, makeArr).push(val);
}
}
return shadow(this, "jsActions", actions);
@ -1383,6 +1500,22 @@ class Catalog {
}
}
if (!Array.isArray(kids)) {
// Prevent errors in corrupt PDF documents that violate the
// specification by *inlining* Page dicts (fixes issue21436.pdf).
let type = currentNode.getRaw("Type");
if (type instanceof Ref) {
try {
type = await xref.fetchAsync(type);
} catch (ex) {
addPageError(ex);
break;
}
}
if (isName(type, "Page") || !currentNode.has("Kids")) {
addPageDict(currentNode, null);
break;
}
addPageError(
new FormatError("Page dictionary kids object is not an array.")
);
@ -1458,6 +1591,9 @@ class Catalog {
const xref = this.xref;
let total = 0,
ref = pageRef;
// Prevent circular references in the /Pages tree.
const visited = new RefSet();
visited.put(pageRef);
while (true) {
const node = await xref.fetchAsync(ref);
@ -1477,6 +1613,12 @@ class Catalog {
throw new FormatError("Node must be a dictionary.");
}
const parentRef = node.getRaw("Parent");
if (parentRef instanceof Ref) {
if (visited.has(parentRef)) {
throw new FormatError("Pages tree contains circular reference.");
}
visited.put(parentRef);
}
const parent = await node.getAsync("Parent");
if (!parent) {
@ -1556,8 +1698,8 @@ class Catalog {
* properties will be placed.
* @property {string} [docBaseUrl] - The document base URL that is used when
* attempting to recover valid absolute URLs from relative ones.
* @property {Object} [docAttachments] - The document attachments (may not
* exist in most PDF documents).
* @property {Record<string, CatalogAttachment> | null} [docAttachments] - The
* document attachments (may not exist in most PDF documents).
*/
/**
@ -1589,9 +1731,19 @@ class Catalog {
// reached (e.g. integer MCIDs or MCR/OBJR dicts without further K).
if (!pageRef) {
const queue = [seDict];
// Prevent circular references in the structure tree.
const visited = new RefSet();
visited.put(seRef);
while (queue.length > 0 && !pageRef) {
const node = queue.shift();
const kids = node.get("K");
let kids = node.getRaw("K");
if (kids instanceof Ref) {
if (visited.has(kids)) {
continue;
}
visited.put(kids);
kids = xref.fetch(kids);
}
let kidsArr;
if (Array.isArray(kids)) {
kidsArr = kids;
@ -1601,6 +1753,12 @@ class Catalog {
continue;
}
for (const kid of kidsArr) {
if (kid instanceof Ref) {
if (visited.has(kid)) {
continue;
}
visited.put(kid);
}
const kidObj = xref.fetchIfRef(kid);
if (!(kidObj instanceof Dict)) {
continue; // integer MCID leaf node, no Pg here
@ -1740,8 +1898,7 @@ class Catalog {
case "GoToR":
const urlDict = action.get("F");
if (urlDict instanceof Dict) {
const fs = new FileSpec(urlDict, /* skipContent = */ true);
({ rawFilename: url } = fs.serializable);
url = new FileSpec(urlDict).filename;
} else if (typeof urlDict === "string") {
url = urlDict;
} else {
@ -1766,22 +1923,21 @@ class Catalog {
case "GoToE":
const target = action.get("T");
let attachment;
/** @type {string | null} */
let id = null;
if (docAttachments && target instanceof Dict) {
if (target instanceof Dict) {
const relationship = target.get("R");
const name = target.get("N");
if (isName(relationship, "C") && typeof name === "string") {
attachment =
docAttachments[
stringToPDFString(name, /* keepEscapeSequence = */ true)
];
id = stringToPDFString(name, /* keepEscapeSequence = */ true);
}
}
if (attachment) {
resultObj.attachment = attachment;
if (docAttachments && id) {
resultObj.attachmentId = id;
resultObj.attachment = docAttachments.get(id);
// NOTE: the destination is relative to the *attachment*.
const attachmentDest = fetchRemoteDest(action);

View File

@ -58,11 +58,9 @@ class CCITTFaxStream extends DecodeStream {
if (this.eof) {
return this.buffer;
}
if (!bytes) {
bytes = this.stream.isAsync
bytes ??= this.stream.isAsync
? (await this.stream.asyncGetBytes()) || this.bytes
: this.bytes;
}
this.buffer = await JBig2CCITTFaxImage.instance.decode(
bytes,

View File

@ -546,7 +546,7 @@ class CFFParser {
let length = data.length;
for (let j = 0; j < length; ) {
for (let j = 0; j < length;) {
const value = data[j++];
let validationCommand = null;
if (value === 12) {
@ -775,14 +775,12 @@ class CFFParser {
} else if (localSubrIndex) {
localSubrToUse = localSubrIndex;
}
if (valid) {
valid = this.parseCharString(
valid &&= this.parseCharString(
state,
charstring,
localSubrToUse,
globalSubrIndex
);
}
if (state.width !== null) {
const nominalWidth = privateDictToUse.getByName("nominalWidthX");
widths[i] = nominalWidth + state.width;
@ -894,9 +892,22 @@ class CFFParser {
}
}
if (maxZoneHeight > 0) {
// The lower bound of AFDKO's valid window is `0.5 / maxZoneHeight`.
// When that bound is itself above the default BlueScale the font simply
// has small zones (e.g. Eurostile LT Std, or the SofiaPro fonts shipped
// with a near-default 0.037): even the default 0.039625 would be
// flagged as out-of-range, so this is the rendered intent and forcing
// BlueScale up only misaligns/collapses overshooting glyphs (notably
// with macOS's Core Text rasterizer). Only apply the lower clamp when
// its target does not exceed the default.
// Round the bound in order to avoid too long operand (issue 21466).
const PRECISION = 1e5;
const lowerBound = 0.5 / maxZoneHeight;
const minBlueScale =
blueScale < DEFAULT_BLUE_SCALE ? 0.5 / maxZoneHeight : -Infinity;
const maxBlueScale = 1 / maxZoneHeight;
lowerBound <= DEFAULT_BLUE_SCALE
? Math.ceil(lowerBound * PRECISION) / PRECISION
: -Infinity;
const maxBlueScale = Math.floor(PRECISION / maxZoneHeight) / PRECISION;
const clamped = MathClamp(blueScale, minBlueScale, maxBlueScale);
if (clamped !== blueScale) {
privateDict.setByName("BlueScale", clamped);
@ -1417,10 +1428,9 @@ class CFFFDSelect {
}
getFDIndex(glyphIndex) {
if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) {
return -1;
}
return this.fdSelect[glyphIndex];
return glyphIndex < 0 || glyphIndex >= this.fdSelect.length
? -1
: this.fdSelect[glyphIndex];
}
}

View File

@ -182,28 +182,14 @@ class ChunkedStream extends Stream {
}
getBytes(length) {
const bytes = this.bytes;
const pos = this.pos;
const strEnd = this.end;
const endPos = !length ? this.end : Math.min(pos + length, this.end);
if (!length) {
if (strEnd > this.progressiveDataLength) {
this.ensureRange(pos, strEnd);
if (endPos > this.progressiveDataLength) {
this.ensureRange(pos, endPos);
}
this.pos = strEnd;
return bytes.subarray(pos, strEnd);
}
let end = pos + length;
if (end > strEnd) {
end = strEnd;
}
if (end > this.progressiveDataLength) {
this.ensureRange(pos, end);
}
this.pos = end;
return bytes.subarray(pos, end);
this.pos = endPos;
return this.bytes.subarray(pos, endPos);
}
getByteRange(begin, end) {
@ -253,10 +239,10 @@ class ChunkedStream extends Stream {
};
Object.defineProperty(ChunkedStreamSubstream.prototype, "isDataLoaded", {
get() {
if (this.numChunksLoaded === this.numChunks) {
return true;
}
return this.getMissingChunks().length === 0;
return (
this.numChunksLoaded === this.numChunks ||
this.getMissingChunks().length === 0
);
},
configurable: true,
});
@ -274,13 +260,13 @@ class ChunkedStream extends Stream {
}
class ChunkedStreamManager {
aborted = false;
#aborted = false;
currRequestId = 0;
_chunksNeededByRequest = new Map();
_loadedStreamCapability = Promise.withResolvers();
#loadedStreamCapability = Promise.withResolvers();
_promisesByRequest = new Map();
@ -302,7 +288,7 @@ class ChunkedStreamManager {
while (true) {
const { value, done } = await rangeReader.read();
if (this.aborted) {
if (this.#aborted) {
chunks = null;
return; // Ignoring any data after abort.
}
@ -337,7 +323,7 @@ class ChunkedStreamManager {
const missingChunks = this.stream.getMissingChunks();
this._requestChunks(missingChunks);
}
return this._loadedStreamCapability.promise;
return this.#loadedStreamCapability.promise;
}
_requestChunks(chunks) {
@ -360,13 +346,13 @@ class ChunkedStreamManager {
const chunksToRequest = [];
for (const chunk of chunksNeeded) {
let requestIds = this._requestsByChunk.get(chunk);
if (!requestIds) {
requestIds = [];
this._requestsByChunk.set(chunk, requestIds);
const requestIds = this._requestsByChunk.getOrInsertComputed(
chunk,
() => {
chunksToRequest.push(chunk);
return [];
}
);
requestIds.push(requestId);
}
@ -383,7 +369,7 @@ class ChunkedStreamManager {
}
return capability.promise.catch(reason => {
if (this.aborted) {
if (this.#aborted) {
return; // Ignoring any pending requests after abort.
}
throw reason;
@ -473,7 +459,7 @@ class ChunkedStreamManager {
}
if (stream.isDataLoaded) {
this._loadedStreamCapability.resolve(stream);
this.#loadedStreamCapability.resolve(stream);
}
const loadedRequests = [];
@ -534,10 +520,6 @@ class ChunkedStreamManager {
});
}
onError(err) {
this._loadedStreamCapability.reject(err);
}
getBeginChunk(begin) {
return Math.floor(begin / this.chunkSize);
}
@ -547,12 +529,13 @@ class ChunkedStreamManager {
}
abort(reason) {
this.aborted = true;
this.#aborted = true;
this.pdfStream?.cancelAllRequests(reason);
for (const capability of this._promisesByRequest.values()) {
capability.reject(reason);
}
this.#loadedStreamCapability.reject(reason);
}
}

View File

@ -326,7 +326,7 @@ class CMap {
c = ((c << 8) | str.charCodeAt(offset + n)) >>> 0;
// Check each codespace range to see if it falls within.
const codespaceRange = codespaceRanges[n];
for (let k = 0, kk = codespaceRange.length; k < kk; ) {
for (let k = 0, kk = codespaceRange.length; k < kk;) {
const low = codespaceRange[k++];
const high = codespaceRange[k++];
if (c >= low && c <= high) {
@ -345,7 +345,7 @@ class CMap {
for (let n = 0, nn = codespaceRanges.length; n < nn; n++) {
// Check each codespace range to see if it falls within.
const codespaceRange = codespaceRanges[n];
for (let k = 0, kk = codespaceRange.length; k < kk; ) {
for (let k = 0, kk = codespaceRange.length; k < kk;) {
const low = codespaceRange[k++];
const high = codespaceRange[k++];
if (charCode >= low && charCode <= high) {

View File

@ -183,6 +183,21 @@ class ColorSpace {
unreachable("Should not call ColorSpace.getRgbBuffer");
}
/**
* Converts `count` unscaled colors to RGB, starting at `destOffset`.
* Components use the native color-space ranges expected by `getRgbItem`,
* and each output has a `3 + alpha01` byte stride.
* Subclasses may override this to batch expensive conversions.
*/
getRgbItems(src, count, dest, destOffset, alpha01) {
const { numComps } = this;
for (let i = 0, srcOffset = 0; i < count; i++, srcOffset += numComps) {
this.getRgbItem(src, srcOffset, dest, destOffset);
destOffset += 3 + alpha01;
}
}
/**
* Determines the number of bytes required to store the result of the
* conversion done by the getRgbBuffer method. As in getRgbBuffer,
@ -379,6 +394,20 @@ class AlternateCS extends ColorSpace {
this.base.getRgbItem(tmpBuf, 0, dest, destOffset);
}
getRgbItems(src, count, dest, destOffset, alpha01) {
const { base, numComps, tintFn } = this;
const baseNumComps = base.numComps;
// Tint first so the base color space can convert the batch at once.
const tinted = new Float32Array(count * baseNumComps);
for (let i = 0, srcOffset = 0, tintedOffset = 0; i < count; i++) {
tintFn(src, srcOffset, tinted, tintedOffset);
srcOffset += numComps;
tintedOffset += baseNumComps;
}
base.getRgbItems(tinted, count, dest, destOffset, alpha01);
}
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
assert(
@ -446,24 +475,36 @@ class PatternCS extends ColorSpace {
* The default color is `new Uint8Array([0])`.
*/
class IndexedCS extends ColorSpace {
#rgbLookup;
constructor(base, highVal, lookup) {
super("Indexed", 1);
this.base = base;
this.highVal = highVal;
const length = base.numComps * (highVal + 1);
this.lookup = new Uint8Array(length);
const count = highVal + 1;
const length = base.numComps * count;
const palette = new Uint8Array(length);
if (lookup instanceof BaseStream) {
const bytes = lookup.getBytes(length);
this.lookup.set(bytes);
palette.set(lookup.getBytes(length));
} else if (typeof lookup === "string") {
for (let i = 0; i < length; ++i) {
this.lookup[i] = lookup.charCodeAt(i) & 0xff;
palette[i] = lookup.charCodeAt(i);
}
} else {
throw new FormatError(`IndexedCS - unrecognized lookup table: ${lookup}`);
}
this.#rgbLookup = new Uint8ClampedArray(count * 3);
base.getRgbBuffer(
palette,
0,
count,
this.#rgbLookup,
0,
/* bits = */ 8,
/* alpha01 = */ 0
);
}
getRgbItem(src, srcOffset, dest, destOffset) {
@ -473,10 +514,12 @@ class IndexedCS extends ColorSpace {
'IndexedCS.getRgbItem: Unsupported "dest" type.'
);
}
const { base, highVal, lookup } = this;
const start =
MathClamp(Math.round(src[srcOffset]), 0, highVal) * base.numComps;
base.getRgbBuffer(lookup, start, 1, dest, destOffset, 8, 0);
const rgbLookup = this.#rgbLookup;
const pos = MathClamp(Math.round(src[srcOffset]), 0, this.highVal) * 3;
dest[destOffset] = rgbLookup[pos];
dest[destOffset + 1] = rgbLookup[pos + 1];
dest[destOffset + 2] = rgbLookup[pos + 2];
}
getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
@ -486,20 +529,21 @@ class IndexedCS extends ColorSpace {
'IndexedCS.getRgbBuffer: Unsupported "dest" type.'
);
}
const { base, highVal, lookup } = this;
const { numComps } = base;
const outputDelta = base.getOutputLength(numComps, alpha01);
const { highVal } = this;
const rgbLookup = this.#rgbLookup;
for (let i = 0; i < count; ++i) {
const lookupPos =
MathClamp(Math.round(src[srcOffset++]), 0, highVal) * numComps;
base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01);
destOffset += outputDelta;
const pos = MathClamp(Math.round(src[srcOffset++]), 0, highVal) * 3;
dest[destOffset++] = rgbLookup[pos];
dest[destOffset++] = rgbLookup[pos + 1];
dest[destOffset++] = rgbLookup[pos + 2];
destOffset += alpha01;
}
}
getOutputLength(inputLength, alpha01) {
return this.base.getOutputLength(inputLength * this.base.numComps, alpha01);
return inputLength * (3 + alpha01);
}
isDefaultDecode(decode, bpc) {

View File

@ -243,9 +243,7 @@ class ColorSpaceUtils {
break;
case "Pattern":
baseCS = cs[1] || null;
if (baseCS) {
baseCS = this.#subParse(baseCS, options);
}
baseCS &&= this.#subParse(baseCS, options);
return new PatternCS(baseCS);
case "I":
case "Indexed":

View File

@ -18,12 +18,12 @@ import {
assert,
BaseException,
makeArr,
objectSize,
Util,
warn,
} from "../shared/util.js";
import { Dict, isName, isRefsEqual, Name, Ref, RefSet } from "./primitives.js";
import { BaseStream } from "./base_stream.js";
import { CONTROL_CHAR_REGEXP } from "../shared/css_utils.js";
import { stringToPDFString } from "./string_utils.js";
const PDF_VERSION_REGEXP = /^[1-9]\.\d$/;
@ -342,7 +342,8 @@ function lookupNormalRect(arr, fallback) {
* each part of the path.
*/
function parseXFAPath(path) {
const positionPattern = /(.+)\[(\d+)\]$/;
// Anchoring prevents retrying the match at every character.
const positionPattern = /^(.+)\[(\d+)\]$/;
return path.split(".").map(component => {
const m = component.match(positionPattern);
if (m) {
@ -376,7 +377,7 @@ function escapePDFName(str) {
if (start < i) {
buffer.push(str.substring(start, i));
}
buffer.push(`#${char.toString(16)}`);
buffer.push(`#${char.toString(16).padStart(2, "0")}`);
start = i + 1;
}
}
@ -386,7 +387,7 @@ function escapePDFName(str) {
}
if (start < str.length) {
buffer.push(str.substring(start, str.length));
buffer.push(str.substring(start));
}
return buffer.join("");
@ -450,7 +451,7 @@ function _collectJS(entry, xref, list, parents) {
}
function collectActions(xref, dict, eventType) {
const actions = Object.create(null);
const actions = new Map();
const additionalActionsDicts = getInheritableProperty({
dict,
key: "AA",
@ -476,7 +477,7 @@ function collectActions(xref, dict, eventType) {
const list = [];
_collectJS(rawActionDict, xref, list, parents);
if (list.length > 0) {
actions[action] = list;
actions.set(action, list);
}
}
}
@ -488,10 +489,10 @@ function collectActions(xref, dict, eventType) {
const list = [];
_collectJS(actionDict, xref, list, parents);
if (list.length > 0) {
actions.Action = list;
actions.set("Action", list);
}
}
return objectSize(actions) > 0 ? actions : null;
return actions.size ? actions : null;
}
const XMLEntities = {
@ -533,7 +534,7 @@ function encodeToXmlString(str) {
buffer.push(str.substring(start, i));
}
buffer.push(`&#x${char.toString(16).toUpperCase()};`);
if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) {
if (char > 0xffff) {
// char is represented by two u16
i++;
}
@ -545,7 +546,7 @@ function encodeToXmlString(str) {
return str;
}
if (start < str.length) {
buffer.push(str.substring(start, str.length));
buffer.push(str.substring(start));
}
return buffer.join("");
}
@ -561,6 +562,17 @@ function validateFontName(fontFamily, mustWarn = false) {
}
return false;
}
// A <string> is terminated by a newline, which for CSS also includes the
// form feed character; see https://drafts.csswg.org/css-syntax/#newline.
// The font family is escaped before being used, see `serializeFontFamily`,
// hence this only prevents values that cannot sensibly name a font from
// being used at all (the unquoted case below is already this strict).
if (CONTROL_CHAR_REGEXP.test(fontFamily)) {
if (mustWarn) {
warn(`FontFamily contains control characters: ${fontFamily}.`);
}
return false;
}
} else {
// See https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident.
for (const ident of fontFamily.split(/[ \t]+/)) {
@ -575,6 +587,18 @@ function validateFontName(fontFamily, mustWarn = false) {
return true;
}
// Strip the spaces preceding a digit, since e.g. "Wingdings 3" is not a valid
// font name in the css specs.
// The optional trailing digit is matched as part of the space run, so that a
// failing match cannot backtrack over the spaces; otherwise the replacement
// would be quadratic in the number of consecutive spaces.
function normalizeCSSFontFamily(fontFamily) {
return fontFamily.replaceAll(
/( +)(\d)?/g,
(_, spaces, digit) => digit ?? " "
);
}
function validateCSSFont(cssFontInfo) {
// See https://developer.mozilla.org/en-US/docs/Web/CSS/font-style.
const DEFAULT_CSS_FONT_OBLIQUE = "14";
@ -751,6 +775,7 @@ export {
lookupRect,
MAX_INT_32,
MissingDataException,
normalizeCSSFontFamily,
numberToString,
ParserEOFException,
parseXFAPath,

View File

@ -13,6 +13,10 @@
* limitations under the License.
*/
/**
* @import {BaseStream} from "./base_stream.js";
*/
import {
bytesToString,
FormatError,
@ -26,10 +30,11 @@ import {
warn,
} from "../shared/util.js";
import { calculateSHA384, calculateSHA512 } from "./calculate_sha_other.js";
import { Dict, isName, Name } from "./primitives.js";
import { Dict, isDict, isName, Name } from "./primitives.js";
import { calculateMD5 } from "./calculate_md5.js";
import { calculateSHA256 } from "./calculate_sha256.js";
import { DecryptStream } from "./decrypt_stream.js";
import { saslPrep } from "./sasl_prep.js";
/**
* @typedef {typeof AES128Cipher | typeof AES256Cipher | typeof ARCFourCipher
@ -754,6 +759,9 @@ class CipherTransform {
/** @type {Map<string, CipherConstructors>} */
#cipherCache = new Map();
/** @type {Name | null} */
embeddedFilterName = null;
/**
* @param {ResolveCipher} resolveCipher
* Resolve a cipher constructor from a crypt filter name.
@ -789,7 +797,11 @@ class CipherTransform {
* @returns {DecryptStream}
*/
createStream(stream, length, cryptFilterName = null) {
const Cipher = this.#getCipher(cryptFilterName || this.streamFilterName);
const defaultFilterName =
this.embeddedFilterName && isDict(stream.dict, "EmbeddedFile")
? this.embeddedFilterName
: this.streamFilterName;
const Cipher = this.#getCipher(cryptFilterName || defaultFilterName);
const cipher = new Cipher();
return new DecryptStream(
stream,
@ -842,7 +854,18 @@ class CipherTransform {
}
}
function utf8PasswordToBytes(password) {
try {
password = utf8StringToString(password);
} catch {
warn("CipherTransformFactory: Unable to convert UTF8 encoded password.");
}
return stringToBytes(password);
}
class CipherTransformFactory {
#fileId;
static get _defaultPasswordBytes() {
return shadow(
this,
@ -1042,6 +1065,7 @@ class CipherTransformFactory {
}
this.filterName = filter.name;
this.dict = dict;
this.#fileId = fileId;
const algorithm = dict.get("V");
if (
!Number.isInteger(algorithm) ||
@ -1077,6 +1101,29 @@ class CipherTransformFactory {
throw new FormatError("invalid key length");
}
let cf = null;
let stmf = Name.get("Identity");
let strf = Name.get("Identity");
let eff = stmf;
if (algorithm >= 4) {
cf = dict.get("CF");
if (cf instanceof Dict) {
// The 'CF' dictionary itself should not be encrypted, and by setting
// `suppressEncryption` we can prevent an infinite loop inside of
// `XRef_fetchUncompressed` if the dictionary contains indirect
// objects (fixes issue7665.pdf).
cf.suppressEncryption = true;
}
stmf = dict.get("StmF") || Name.get("Identity");
strf = dict.get("StrF") || Name.get("Identity");
eff = dict.get("EFF") || stmf;
}
this.cf = cf;
this.stmf = stmf;
this.strf = strf;
this.eff = eff;
const ownerBytes = stringToBytes(dict.get("O")),
userBytes = stringToBytes(dict.get("U"));
// prepare keys
@ -1091,19 +1138,20 @@ class CipherTransformFactory {
this.encryptMetadata = encryptMetadata;
const fileIdBytes = stringToBytes(fileId);
let passwordBytes;
let passwordBytes, rawPasswordBytes;
if (password) {
if (revision === 6) {
try {
password = utf8StringToString(password);
} catch {
warn(
"CipherTransformFactory: Unable to convert UTF8 encoded password."
);
}
const preppedPassword = saslPrep(password);
passwordBytes = utf8PasswordToBytes(preppedPassword);
if (preppedPassword !== password) {
rawPasswordBytes = utf8PasswordToBytes(password);
}
} else if (algorithm === 5) {
passwordBytes = utf8PasswordToBytes(password);
} else {
passwordBytes = stringToBytes(password);
}
}
let encryptionKey;
if (algorithm !== 5) {
@ -1126,9 +1174,12 @@ class CipherTransformFactory {
const ownerEncryption = stringToBytes(dict.get("OE"));
const userEncryption = stringToBytes(dict.get("UE"));
const perms = stringToBytes(dict.get("Perms"));
for (const candidate of rawPasswordBytes
? [passwordBytes, rawPasswordBytes]
: [passwordBytes]) {
encryptionKey = this.#createEncryptionKey20(
revision,
passwordBytes,
candidate,
ownerPassword,
ownerValidationSalt,
ownerKeySalt,
@ -1140,9 +1191,28 @@ class CipherTransformFactory {
userEncryption,
perms
);
if (encryptionKey) {
break;
}
}
}
if (!encryptionKey) {
if (!password) {
if (
this.algorithm >= 4 &&
isName(this.stmf, "Identity") &&
isName(this.strf, "Identity")
) {
const effCF = this.cf?.get(this.eff.name);
const authEvent = effCF?.get("AuthEvent");
if (isName(authEvent, "EFOpen")) {
// For EFOpen with Identity as default stream/string filters, defer
// password prompting until an EmbeddedFile stream is actually read.
this.encryptionKey = null;
return;
}
}
throw new PasswordException(
"No password given",
PasswordResponses.NEED_PASSWORD
@ -1182,21 +1252,23 @@ class CipherTransformFactory {
} else {
this.encryptionKey = encryptionKey;
}
}
if (algorithm >= 4) {
const cf = dict.get("CF");
if (cf instanceof Dict) {
// The 'CF' dictionary itself should not be encrypted, and by setting
// `suppressEncryption` we can prevent an infinite loop inside of
// `XRef_fetchUncompressed` if the dictionary contains indirect
// objects (fixes issue7665.pdf).
cf.suppressEncryption = true;
}
this.cf = cf;
this.stmf = dict.get("StmF") || Name.get("Identity");
this.strf = dict.get("StrF") || Name.get("Identity");
this.eff = dict.get("EFF") || this.stmf;
}
/**
* Set password.
*
* @param {string} password
* New password.
* @returns {undefined}
* Nothing.
*/
setPassword(password) {
const transform = new CipherTransformFactory(
this.dict,
this.#fileId,
password
);
this.encryptionKey = transform.encryptionKey;
}
/**
@ -1220,6 +1292,18 @@ class CipherTransformFactory {
if (!cfm || cfm.name === "None") {
return NullCipher;
}
if (!this.encryptionKey) {
throw new PasswordException(
"No password given",
PasswordResponses.NEED_PASSWORD
);
}
if (this.algorithm === 5 || cfm.name === "AESV3") {
// V=5 always uses 256-bit AES with the file encryption key, even
// when a producer wrongly sets the crypt filter's CFM to AESV2
// (bug 2046659).
return AES256Cipher.bind(null, this.encryptionKey);
}
if (cfm.name === "V2") {
return ARCFourCipher.bind(
null,
@ -1242,13 +1326,16 @@ class CipherTransformFactory {
)
);
}
if (cfm.name === "AESV3") {
return AES256Cipher.bind(null, this.encryptionKey);
}
throw new FormatError("Unknown crypto method");
};
return new CipherTransform(resolveCipher, this.strf, this.stmf);
const transform = new CipherTransform(
resolveCipher,
this.strf,
this.stmf
);
transform.embeddedFilterName = this.eff;
return transform;
}
// algorithms 1 and 2

Some files were not shown because too many files have changed in this diff Show More