Compare commits

...

317 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
306 changed files with 19293 additions and 5284 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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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,7 +46,7 @@ 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') }}

View File

@ -18,19 +18,19 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
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@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
uses: github/codeql-action/autobuild@e0647621c2984b5ed2f768cb892365bf2a616ad1 # v4.37.2
- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
uses: github/codeql-action/analyze@e0647621c2984b5ed2f768cb892365bf2a616ad1 # v4.37.2

View File

@ -4,6 +4,7 @@ on:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/images/**'
- 'test/pdfs/**'
@ -21,6 +22,7 @@ on:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/images/**'
- 'test/pdfs/**'
@ -53,13 +55,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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'
@ -68,7 +70,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') }}
@ -80,7 +82,7 @@ jobs:
run: npx gulp botbrowsertest --headless -j$(nproc) --coverage --coverage-output build/coverage/browser --noChrome
- 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') }}

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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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

@ -4,9 +4,11 @@ on:
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
@ -14,9 +16,11 @@ on:
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
@ -45,13 +49,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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'
@ -60,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'

View File

@ -4,6 +4,7 @@ on:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/test.mjs'
- 'test/integration/**'
@ -15,6 +16,7 @@ on:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/test.mjs'
- 'test/integration/**'
@ -47,13 +49,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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,7 +89,7 @@ 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') }}

View File

@ -15,13 +15,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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

@ -4,6 +4,7 @@ on:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/test.mjs'
- 'test/unit/**'
@ -15,6 +16,7 @@ on:
paths:
- 'gulpfile.mjs'
- 'external/**'
- 'package-lock.json'
- 'src/**'
- 'test/test.mjs'
- 'test/unit/**'
@ -47,13 +49,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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,7 +76,7 @@ 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') }}

View File

@ -23,13 +23,13 @@ jobs:
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
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

@ -136,14 +136,31 @@ browsable HTML report instead, or pass several formats at once, e.g.
### Finding which tests cover a given line
Run a browser test task with `--coverage-per-test` to build an index
(`per-test-index.json`) in the coverage directory, then query it to list the
tests that exercised a specific source line or function:
`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 botbrowsertest --coverage-per-test
$ 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

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

@ -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

@ -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();
@ -1683,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,
@ -1725,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",
@ -1734,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,
@ -2396,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");
@ -2460,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

@ -390,3 +390,12 @@ 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

@ -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] 또는 이미지 파일 찾아보기
@ -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 = 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
@ -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 =

4075
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.7",
"@babel/preset-env": "^7.29.7",
"@babel/runtime": "^7.29.7",
"@eslint/json": "^2.0.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": "^26.0.0",
"autoprefixer": "^10.5.1",
"@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.2",
"babel-plugin-polyfill-corejs3": "^1.0.0",
"cached-iterable": "^0.3.0",
"caniuse-lite": "^1.0.30001799",
"caniuse-lite": "^1.0.30001806",
"core-js": "^3.49.0",
"eslint": "^10.5.0",
"eslint": "^10.8.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import-x": "^4.17.0",
"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.1",
"eslint-plugin-perfectionist": "^5.10.0",
"eslint-plugin-prettier": "^5.5.6",
"eslint-plugin-regexp": "^3.1.0",
"eslint-plugin-unicorn": "^68.0.0",
"globals": "^17.7.0",
"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",
@ -44,23 +44,23 @@
"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": "^8.5.25",
"postcss-discard-comments": "^8.0.1",
"postcss-values-parser": "^8.0.0",
"prettier": "^3.8.4",
"puppeteer": "^25.2.0",
"stylelint": "^17.13.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.1",
"tsc-alias": "^1.8.17",
"tsc-alias": "^1.9.1",
"ttest": "^4.0.0",
"typescript": "^6.0.3",
"vinyl": "^3.0.1",
"webpack": "^5.107.2",
"webpack": "^5.109.2",
"webpack-stream": "^7.0.0"
},
"repository": {

View File

@ -1,5 +1,5 @@
{
"stableVersion": "6.0.227",
"baseVersion": "b168293c173b0b9befe462c0b254136cf038c3ef",
"versionPrefix": "6.1."
"stableVersion": "6.2.108",
"baseVersion": "ce4ff55faaa83b39b0137dc458af6eea6f96235f",
"versionPrefix": "6.3."
}

View File

@ -74,6 +74,7 @@ import { Catalog } from "./catalog.js";
import { ColorSpaceUtils } from "./colorspace_utils.js";
import { createImage } from "./editor/pdf_images.js";
import { FileSpec } from "./file_spec.js";
import { getSoundFormat } from "./sound.js";
import { JpegStream } from "./jpeg_stream.js";
import { ObjectLoader } from "./object_loader.js";
import { OperatorList } from "./operator_list.js";
@ -291,6 +292,9 @@ class AnnotationFactory {
case "Screen":
return new ScreenAnnotation(parameters);
case "Sound":
return new SoundAnnotation(parameters);
default:
if (!collectFields) {
if (!subtype) {
@ -315,10 +319,7 @@ class AnnotationFactory {
const pageRef = annotDict.getRaw("P");
if (pageRef instanceof Ref) {
try {
const pageIndex = await pdfManager.ensureCatalog("getPageIndex", [
pageRef,
]);
return pageIndex;
return await pdfManager.ensureCatalog("getPageIndex", [pageRef]);
} catch (ex) {
info(`_getPageIndex -- not a valid page reference: "${ex}".`);
}
@ -1331,6 +1332,8 @@ class Annotation {
const text = [];
const buffer = [];
let firstPositionX = Infinity;
let firstPositionY = Infinity;
let firstPosition = null;
const sink = {
desiredSize: Math.Infinity,
@ -1341,7 +1344,8 @@ class Annotation {
if (item.str === undefined) {
continue;
}
firstPosition ||= item.transform.slice(-2);
firstPositionX = Math.min(firstPositionX, item.transform[4]);
firstPositionY = Math.min(firstPositionY, item.transform[5]);
buffer.push(item.str);
if (item.hasEOL) {
text.push(buffer.join("").trimEnd());
@ -1362,6 +1366,10 @@ class Annotation {
});
this.reset();
if (firstPositionX !== Infinity) {
firstPosition = [firstPositionX, firstPositionY];
}
if (buffer.length) {
text.push(buffer.join("").trimEnd());
}
@ -1509,7 +1517,7 @@ class Annotation {
* usually indirect; when it's inline its embedded-file stream still isn't
* (streams are always indirect), so fall back to that ref.
*/
_getAttachmentId(fsDict, fsRef, annotationGlobals) {
_getAttachmentId(fsDict, fsRef, annotationGlobals, isSound = false) {
if (!(fsDict instanceof Dict)) {
return undefined;
}
@ -1517,7 +1525,7 @@ class Annotation {
fsRef = FileSpec.pickPlatformItem(fsDict.get("EF"), /* raw = */ true);
}
return fsRef instanceof Ref
? annotationGlobals.catalog.getAttachmentIdForAnnotation(fsRef)
? annotationGlobals.catalog.getAttachmentIdForAnnotation(fsRef, isSound)
: undefined;
}
@ -2879,10 +2887,7 @@ class TextWidgetAnnotation extends WidgetAnnotation {
this.data.doNotScroll = this.hasFieldFlag(AnnotationFieldFlag.DONOTSCROLL);
// Check if we have a date or time.
const {
data: { actions },
} = this;
const { actions } = this.data;
if (!actions) {
return;
}
@ -2890,32 +2895,35 @@ class TextWidgetAnnotation extends WidgetAnnotation {
const AFDateTime =
/^AF(Date|Time)_(?:Keystroke|Format)(?:Ex)?\(['"]?([^'"]+)['"]?\);$/;
let canUseHTMLDateTime = false;
const aFormat = actions.get("Format"),
aKeystroke = actions.get("Keystroke");
if (
(actions.Format?.length === 1 &&
actions.Keystroke?.length === 1 &&
AFDateTime.test(actions.Format[0]) &&
AFDateTime.test(actions.Keystroke[0])) ||
(actions.Format?.length === 0 &&
actions.Keystroke?.length === 1 &&
AFDateTime.test(actions.Keystroke[0])) ||
(actions.Keystroke?.length === 0 &&
actions.Format?.length === 1 &&
AFDateTime.test(actions.Format[0]))
(aFormat?.length === 1 &&
aKeystroke?.length === 1 &&
AFDateTime.test(aFormat[0]) &&
AFDateTime.test(aKeystroke[0])) ||
(aFormat?.length === 0 &&
aKeystroke?.length === 1 &&
AFDateTime.test(aKeystroke[0])) ||
(aKeystroke?.length === 0 &&
aFormat?.length === 1 &&
AFDateTime.test(aFormat[0]))
) {
// If the Format and Keystroke actions are the same, we can just use
// the Format action.
canUseHTMLDateTime = true;
}
const actionsToVisit = [];
if (actions.Format) {
actionsToVisit.push(...actions.Format);
if (aFormat) {
actionsToVisit.push(...aFormat);
}
if (actions.Keystroke) {
actionsToVisit.push(...actions.Keystroke);
if (aKeystroke) {
actionsToVisit.push(...aKeystroke);
}
if (canUseHTMLDateTime) {
delete actions.Keystroke;
actions.Format = actionsToVisit;
actions.delete("Keystroke");
actions.set("Format", actionsToVisit);
}
for (const formatAction of actionsToVisit) {
@ -3307,13 +3315,11 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
return super.getOperatorList(evaluator, task, intent, annotationStorage);
}
if (value === null || value === undefined) {
// There is no default appearance so use the one derived
// from the field value.
value = this.data.checkBox
// There is no default appearance, `value === null || value === undefined`,
// so use the one derived from the field value.
value ??= this.data.checkBox
? this.data.fieldValue === this.data.exportValue
: this.data.fieldValue === this.data.buttonValue;
}
return this.#getOperatorListForAppearance(
evaluator,
@ -4098,6 +4104,8 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
}
class SignatureWidgetAnnotation extends WidgetAnnotation {
_hasValueFromXFA = false;
constructor(params) {
super(params);
@ -4705,9 +4713,7 @@ class PolylineAnnotation extends MarkupAnnotation {
const strokeAlpha = dict.get("CA");
let fillColor = getRgbColor(dict.getArray("IC"), null);
if (fillColor) {
fillColor = getPdfColorArray(fillColor);
}
fillColor &&= getPdfColorArray(fillColor);
let operator;
if (fillColor) {
@ -4785,19 +4791,19 @@ class InkAnnotation extends MarkupAnnotation {
if (!Array.isArray(rawInkLists)) {
return;
}
for (let i = 0, ii = rawInkLists.length; i < ii; ++i) {
for (const rawInkList of rawInkLists) {
// The raw ink lists array contains arrays of numbers representing
// the alternating horizontal and vertical coordinates, respectively,
// of each vertex. Convert this to an array of objects with x and y
// coordinates.
if (!Array.isArray(rawInkLists[i])) {
if (!Array.isArray(rawInkList)) {
continue;
}
const inkList = new Float32Array(rawInkLists[i].length);
const inkList = new Float32Array(rawInkList.length);
this.data.inkLists.push(inkList);
for (let j = 0, jj = rawInkLists[i].length; j < jj; j += 2) {
const x = xref.fetchIfRef(rawInkLists[i][j]),
y = xref.fetchIfRef(rawInkLists[i][j + 1]);
for (let j = 0, jj = rawInkList.length; j < jj; j += 2) {
const x = xref.fetchIfRef(rawInkList[j]),
y = xref.fetchIfRef(rawInkList[j + 1]);
if (typeof x === "number" && typeof y === "number") {
inkList[j] = x;
inkList[j + 1] = y;
@ -5488,15 +5494,23 @@ class MediaAnnotation extends Annotation {
* when `assetRef` isn't itself a reference.
* @param {string} asset.filename
* @param {string} asset.contentType
* @param {boolean} [asset.wrapSound]
* When set, the embedded bytes are raw PDF sound samples that the catalog
* wraps in a WAV container when fetched (see `soundStreamToWav`).
* @param {Object} annotationGlobals
*/
_setMediaData(
{ assetRef, assetDict, filename, contentType },
{ assetRef, assetDict, filename, contentType, wrapSound = false },
annotationGlobals
) {
this.data.noHTML = false;
this.data.richMedia = {
fileId: this._getAttachmentId(assetDict, assetRef, annotationGlobals),
fileId: this._getAttachmentId(
assetDict,
assetRef,
annotationGlobals,
wrapSound
),
filename,
contentType,
};
@ -5825,6 +5839,45 @@ class ScreenAnnotation extends MediaAnnotation {
}
}
class SoundAnnotation extends MediaAnnotation {
constructor(params) {
super(params);
const { dict, xref, annotationGlobals } = params;
const soundRef = dict.getRaw("Sound");
if (!(soundRef instanceof Ref)) {
return;
}
let sound;
try {
sound = xref.fetch(soundRef);
} catch (ex) {
if (ex instanceof MissingDataException) {
throw ex;
}
// A corrupt sound stream: fall back to rendering the appearance.
warn(`SoundAnnotation: "${ex}".`);
return;
}
if (!(sound instanceof BaseStream) || !getSoundFormat(sound.dict)) {
// No embedded samples, or an encoding we can't turn into a playable WAV
// (compressed, or an unusual bit depth); just render the appearance.
return;
}
this._setMediaData(
{
assetRef: soundRef,
assetDict: sound.dict,
filename: "sound.wav",
contentType: "audio/wav",
wrapSound: true,
},
annotationGlobals
);
}
}
export {
Annotation,
AnnotationBorderStyle,

View File

@ -19,7 +19,7 @@ import {
DocumentActionEventType,
FormatError,
info,
objectSize,
makeArr,
PermissionFlag,
shadow,
stringToUTF8String,
@ -52,6 +52,7 @@ 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";
@ -123,6 +124,8 @@ class Catalog {
#annotationAttachmentRefById = new Map();
#soundAttachmentIds = new Set();
#catDict = null;
builtInCMapCache = new Map();
@ -171,15 +174,15 @@ class Catalog {
*
* @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) {
getAttachmentIdForAnnotation(ref, isSound = false) {
let id = this.#annotationAttachmentIdByRef.get(ref);
if (id) {
return id;
}
if (!id) {
const baseId = `attachmentRef:${ref.toString()}`;
id = baseId;
@ -193,6 +196,10 @@ class Catalog {
this.#annotationAttachmentIdByRef.put(ref, id);
this.#annotationAttachmentRefById.set(id, ref);
}
if (isSound) {
this.#soundAttachmentIds.add(id);
}
return id;
}
@ -756,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) {
@ -772,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
);
}
}
}
@ -784,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) {
@ -800,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() {
@ -1072,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) {
@ -1099,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
@ -1119,18 +1123,14 @@ 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);
}
/**
@ -1198,7 +1198,11 @@ class Catalog {
if (ref) {
const target = this.xref.fetch(ref);
if (target instanceof BaseStream) {
return FileSpec.readStreamContent(target);
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;
}
@ -1238,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();
@ -1257,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);
}
}
@ -1288,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);
@ -1595,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);
@ -1614,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) {
@ -1726,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;
@ -1738,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

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

@ -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;
@ -1430,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

@ -239,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,
});

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;
}
}
@ -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++;
}
@ -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

@ -34,6 +34,7 @@ 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
@ -853,6 +854,15 @@ class CipherTransform {
}
}
function utf8PasswordToBytes(password) {
try {
password = utf8StringToString(password);
} catch {
warn("CipherTransformFactory: Unable to convert UTF8 encoded password.");
}
return stringToBytes(password);
}
class CipherTransformFactory {
#fileId;
@ -1128,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) {
@ -1163,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,
@ -1177,6 +1191,10 @@ class CipherTransformFactory {
userEncryption,
perms
);
if (encryptionKey) {
break;
}
}
}
if (!encryptionKey) {
if (!password) {
@ -1280,7 +1298,7 @@ class CipherTransformFactory {
PasswordResponses.NEED_PASSWORD
);
}
if (this.algorithm === 5) {
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).
@ -1308,9 +1326,6 @@ class CipherTransformFactory {
)
);
}
if (cfm.name === "AESV3") {
return AES256Cipher.bind(null, this.encryptionKey);
}
throw new FormatError("Unknown crypto method");
};

View File

@ -111,10 +111,9 @@ class DecodeStream extends BaseStream {
async getImageData(length, decoderOptions) {
if (!this.canAsyncDecodeImageFromBuffer) {
if (this.isAsyncDecoder) {
return this.decodeImage(null, length, decoderOptions);
}
return this.getBytes(length, decoderOptions);
return this.isAsyncDecoder
? this.decodeImage(null, length, decoderOptions)
: this.getBytes(length, decoderOptions);
}
const data = await this.stream.asyncGetBytes();
return this.decodeImage(data, length, decoderOptions);

View File

@ -25,6 +25,7 @@ import {
LINE_FACTOR,
OPS,
shadow,
Util,
warn,
} from "../shared/util.js";
import { ColorSpaceUtils } from "./colorspace_utils.js";
@ -144,7 +145,8 @@ class AppearanceStreamEvaluator extends EvaluatorPreprocessor {
result = stack.pop() || result;
break;
case OPS.setTextMatrix:
result.scaleFactor *= Math.hypot(args[0], args[1]);
const tm = Util.transform(this.stateManager.state.ctm, args);
result.scaleFactor *= Math.hypot(tm[0], tm[1]);
break;
case OPS.setFont:
const [fontName, fontSize] = args;
@ -152,7 +154,7 @@ class AppearanceStreamEvaluator extends EvaluatorPreprocessor {
result.fontName = fontName.name;
}
if (typeof fontSize === "number" && fontSize > 0) {
result.fontSize = fontSize * result.scaleFactor;
result.fontSize = fontSize;
}
break;
case OPS.setFillColorSpace:
@ -182,6 +184,10 @@ class AppearanceStreamEvaluator extends EvaluatorPreprocessor {
case OPS.showSpacedText:
case OPS.nextLineShowText:
case OPS.nextLineSetSpacingShowText:
// The font (Tf) and the text matrix (Tm) can be set in any order,
// so the scale factor is applied here, when text is actually shown
// and both are known to be in effect.
result.fontSize *= result.scaleFactor;
breakLoop = true;
break;
}

View File

@ -21,7 +21,6 @@ import {
InvalidPDFException,
isArrayEqual,
makeArr,
objectSize,
PageActionEventType,
RenderingIntentFlag,
shadow,
@ -43,6 +42,7 @@ import {
isWhiteSpace,
lookupNormalRect,
MissingDataException,
normalizeCSSFontFamily,
PDF_VERSION_REGEXP,
RESOURCES_KEYS_OPERATOR_LIST,
RESOURCES_KEYS_TEXT_CONTENT,
@ -81,6 +81,7 @@ import { XFAFactory } from "./xfa/factory.js";
import { XRef } from "./xref.js";
const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
const SIGNATURE_TAIL_CHUNK_SIZE = 65536;
class Page {
#resourcesPromise = null;
@ -1004,6 +1005,12 @@ function find(stream, signature, limit = 1024, backwards = false) {
class PDFDocument {
#pagePromises = new Map();
// Map<id, {byteRange: number[4], pkcs7: Uint8Array}> — populated by the
// `signatures` getter, consumed by `getSignatureData`. We deliberately
// keep the signed byte spans out of the metadata array and only slice
// them out of the stream when the viewer actually asks to verify.
#signatureData = null;
#version = null;
constructor(pdfManager, stream) {
@ -1188,7 +1195,10 @@ class PDFDocument {
recursionDepth
);
}
const isSignature = isName(field.get("FT"), "Sig");
const isSignature = isName(
getInheritableProperty({ dict: field, key: "FT" }),
"Sig"
);
const rectangle = field.get("Rect");
const isInvisible =
Array.isArray(rectangle) && rectangle.every(value => value === 0);
@ -1273,13 +1283,13 @@ class PDFDocument {
if (!streams) {
return null;
}
const data = Object.create(null);
const data = new Map();
for (const [key, stream] of streams) {
if (!stream) {
continue;
}
try {
data[key] = stringToUTF8String(stream.getString());
data.set(key, stringToUTF8String(stream.getString()));
} catch {
warn("XFA - Invalid utf-8 string.");
return null;
@ -1387,9 +1397,7 @@ class PDFDocument {
if (!(descriptor instanceof Dict)) {
continue;
}
let fontFamily = descriptor.get("FontFamily");
// For example, "Wingdings 3" is not a valid font name in the css specs.
fontFamily = fontFamily.replaceAll(/ +(\d)/g, "$1");
const fontFamily = normalizeCSSFontFamily(descriptor.get("FontFamily"));
const fontWeight = descriptor.get("FontWeight");
// Angle is expressed in degrees counterclockwise in PDF
@ -1871,12 +1879,15 @@ class PDFDocument {
name = name === "" ? partName : `${name}.${partName}`;
} else {
let obj = field;
// The `Parent` chain can be cyclic, hence the local `RefSet`.
const walkedRefs = new RefSet();
while (true) {
obj = obj.getRaw("Parent") || parentRef;
if (obj instanceof Ref) {
if (visitedRefs.has(obj)) {
if (visitedRefs.has(obj) || walkedRefs.has(obj)) {
break;
}
walkedRefs.put(obj);
obj = await xref.fetchAsync(obj);
}
if (!(obj instanceof Dict)) {
@ -1950,7 +1961,7 @@ class PDFDocument {
const { acroForm } = annotationGlobals;
const visitedRefs = new RefSet();
const allFields = Object.create(null);
const allFields = new Map();
const fieldPromises = new Map();
const orphanFields = new RefSetCache();
for (const fieldRef of acroForm.get("Fields")) {
@ -1971,7 +1982,7 @@ class PDFDocument {
Promise.all(promises).then(fields => {
fields = fields.filter(field => !!field);
if (fields.length > 0) {
allFields[name] = fields;
allFields.set(name, fields);
}
})
);
@ -1979,7 +1990,7 @@ class PDFDocument {
await Promise.all(allPromises);
return {
allFields: objectSize(allFields) > 0 ? allFields : null,
allFields: allFields.size ? allFields : null,
orphanFields,
};
});
@ -1987,6 +1998,258 @@ class PDFDocument {
return shadow(this, "fieldObjects", promise);
}
async #collectSignatureFields(fields, out, visitedRefs) {
if (!Array.isArray(fields)) {
return;
}
for (const fieldRef of fields) {
if (fieldRef instanceof Ref) {
if (visitedRefs.has(fieldRef)) {
continue;
}
visitedRefs.put(fieldRef);
}
const field = await this.xref.fetchIfRefAsync(fieldRef);
if (!(field instanceof Dict)) {
continue;
}
if (isName(await field.getAsync("FT"), "Sig")) {
const sigDict = await field.getAsync("V");
if (sigDict instanceof Dict) {
const parsed = await this.#parseSignatureDict(
field,
sigDict,
fieldRef
);
if (parsed) {
out.push(parsed);
}
}
}
if (field.has("Kids")) {
// A terminal field can have Widget annotations as children, so its
// own signature must be collected before walking the field tree.
await this.#collectSignatureFields(
await field.getAsync("Kids"),
out,
visitedRefs
);
}
}
}
async #getByteRange(begin, end) {
try {
return this.stream.getByteRange(begin, end);
} catch (ex) {
if (!(ex instanceof MissingDataException)) {
throw ex;
}
await this.pdfManager.requestRange(begin, end);
return this.#getByteRange(begin, end);
}
}
async #coversWholeDocument(signedEnd, modificationsAfterSignature) {
if (modificationsAfterSignature > 0) {
return false;
}
const fileLength = this.stream.end;
for (
let begin = signedEnd;
begin < fileLength;
begin += SIGNATURE_TAIL_CHUNK_SIZE
) {
const end = Math.min(begin + SIGNATURE_TAIL_CHUNK_SIZE, fileLength);
const tail = await this.#getByteRange(begin, end);
for (const byte of tail) {
if (
byte !== 0x00 && // null
byte !== 0x09 && // horizontal tab
byte !== 0x0a && // line feed
byte !== 0x0c && // form feed
byte !== 0x0d && // carriage return
byte !== 0x20 // space
) {
return false;
}
}
}
return true;
}
async #parseSignatureDict(field, sigDict, fieldRef) {
const byteRange = await sigDict.getAsync("ByteRange");
if (
!Array.isArray(byteRange) ||
byteRange.length !== 4 ||
byteRange.some(n => !Number.isInteger(n) || n < 0)
) {
return null;
}
// Slice the two ByteRange byte spans out of the underlying PDF stream.
// ByteRange = [a, b, c, d] means signed bytes are [a..a+b] and [c..c+d];
// the gap covers the /Contents hex blob itself.
const [a, b, c, d] = byteRange;
// `/ByteRange` offsets are absolute, so compare against `stream.end`
// (raw buffer end), not `stream.length` (post-`moveStart` payload).
const fileLength = this.stream.end || 0;
// Reject signatures whose /ByteRange is structurally implausible: it
// must start at the file head, define a non-empty first span, leave
// room for the /Contents blob between the two spans, and fit within
// the file. Without this a crafted PDF can claim to cover the whole
// document while only signing a small prologue.
if (
a !== 0 ||
b <= 0 ||
a + b > c ||
c + d > fileLength ||
fileLength === 0
) {
return null;
}
const contents = await sigDict.getAsync("Contents");
if (typeof contents !== "string" || contents.length === 0) {
return null;
}
const [
filterName,
subFilterName,
t,
name,
reason,
location,
contactInfo,
m,
] = await Promise.all([
sigDict.getAsync("Filter"),
sigDict.getAsync("SubFilter"),
field.getAsync("T"),
sigDict.getAsync("Name"),
sigDict.getAsync("Reason"),
sigDict.getAsync("Location"),
sigDict.getAsync("ContactInfo"),
sigDict.getAsync("M"),
]);
const filter = filterName instanceof Name ? filterName.name : null,
subFilter = subFilterName instanceof Name ? subFilterName.name : null;
let signatureType = null;
if (subFilter === "adbe.pkcs7.detached") {
signatureType = 0;
} else if (subFilter === "adbe.pkcs7.sha1") {
signatureType = 1;
}
const refKey = fieldRef instanceof Ref ? fieldRef.toString() : "inline";
return {
id: `${refKey}:${a}-${b}-${c}-${d}`,
fieldName: typeof t === "string" ? stringToPDFString(t) : "",
signerName: typeof name === "string" ? stringToPDFString(name) : null,
reason: typeof reason === "string" ? stringToPDFString(reason) : null,
location:
typeof location === "string" ? stringToPDFString(location) : null,
contactInfo:
typeof contactInfo === "string" ? stringToPDFString(contactInfo) : null,
signingTime: typeof m === "string" ? m : null,
filter,
subFilter,
signatureType,
byteRange,
pkcs7: stringToBytes(contents),
revisionIndex: 0,
parentId: null,
};
}
get signatures() {
const promise = this.pdfManager
.ensureDoc("formInfo")
.then(async formInfo => {
if (!formInfo.hasSignatures || !formInfo.hasFields) {
return null;
}
const annotationGlobals = await this.annotationGlobals;
if (!annotationGlobals) {
return null;
}
const fields = annotationGlobals.acroForm.get("Fields");
const collected = [];
await this.#collectSignatureFields(fields, collected, new RefSet());
await Promise.all(
collected.map(async signature => {
const signedEnd = signature.byteRange[2] + signature.byteRange[3];
signature.modificationsAfterSignature =
this.xref.countUpdatesAfter(signedEnd);
signature.coversWholeDocument = await this.#coversWholeDocument(
signedEnd,
signature.modificationsAfterSignature
);
})
);
// Group sub-signatures by ByteRange containment: outer revision is
// the largest covering signature (largest c + d). Sort descending,
// then point each later signature at the smallest enclosing parent
// that came before it.
collected.sort(
(a, b) =>
b.byteRange[2] + b.byteRange[3] - (a.byteRange[2] + a.byteRange[3])
);
for (let i = 0, ii = collected.length; i < ii; i++) {
const sig = collected[i];
sig.revisionIndex = i;
for (let j = i - 1; j >= 0; j--) {
const candidate = collected[j];
if (
candidate.byteRange[2] + candidate.byteRange[3] >
sig.byteRange[2] + sig.byteRange[3]
) {
sig.parentId = candidate.id;
break;
}
}
}
// Keep the PKCS#7 blob and byte-range information worker-side so the
// metadata array stays small. The viewer fetches the signed bytes on
// demand via `getSignatureData(id)`, one signature at a time, only
// when verification is about to run.
const signatureData = new Map();
const metadata = collected.map(sig => {
const { pkcs7, ...rest } = sig;
signatureData.set(sig.id, { byteRange: sig.byteRange, pkcs7 });
return rest;
});
this.#signatureData = signatureData;
return metadata.length ? metadata : null;
});
return shadow(this, "signatures", promise);
}
async getSignatureData(id) {
// Ensure parsing is finished and `#signatureData` is populated.
await this.signatures;
const signature = this.#signatureData?.get(id);
if (!signature) {
return null;
}
const { byteRange, pkcs7 } = signature;
const [a, b, c, d] = byteRange;
const data = await Promise.all([
this.#getByteRange(a, a + b),
this.#getByteRange(c, c + d),
]);
return { data, pkcs7 };
}
get hasJSActions() {
const promise = this.pdfManager.ensureDoc("_parseHasJSActions");
return shadow(this, "hasJSActions", promise);
@ -2005,9 +2268,9 @@ class PDFDocument {
return true;
}
if (fieldObjects?.allFields) {
return Object.values(fieldObjects.allFields).some(fieldObject =>
fieldObject.some(object => object.actions !== null)
);
return fieldObjects.allFields
.values()
.some(fieldObj => fieldObj.some(obj => obj.actions !== null));
}
return false;
}

View File

@ -104,6 +104,10 @@ class XRefWrapper {
return this._getNewRef();
}
countUpdatesAfter(offset) {
return null;
}
fetchIfRef(obj) {
return obj instanceof Ref ? this.fetch(obj) : obj;
}
@ -259,7 +263,7 @@ class PDFEditor {
) {
if (obj instanceof Ref) {
const {
currentDocument: { oldRefMapping },
currentDocument: { fieldToParent, oldRefMapping },
} = this;
const existingRef = oldRefMapping.get(obj);
if (existingRef) {
@ -267,6 +271,12 @@ class PDFEditor {
}
const oldRef = obj;
obj = await xref.fetchAsync(oldRef);
const mappedRef = oldRefMapping.get(oldRef);
if (mappedRef) {
// Another concurrent traversal may have allocated the clone while the
// source object was being fetched.
return mappedRef;
}
if (typeof obj === "number") {
// Simple value; no need to create a new reference.
return obj;
@ -295,9 +305,17 @@ class PDFEditor {
}
}
let cloneSource = true;
if (fieldToParent.has(oldRef) && obj instanceof Dict) {
// Avoid following a widget's field hierarchy while cloning the page,
// without mutating the source dictionary cached by its XRef.
obj = this.cloneDict(obj);
obj.delete("Parent");
cloneSource = false;
}
this.xref[newRef.num] = await this.#collectDependencies(
obj,
true,
cloneSource,
xref,
resourceStreamPath
);
@ -455,12 +473,7 @@ class PDFEditor {
// Re-entry means a (malformed) cycle back to this stream: allocate its
// reference now to break the loop, like the generic path's eager alloc.
if (resourceStreamPath.has(oldRef)) {
let ref = oldRefMapping.get(oldRef);
if (!ref) {
ref = this.newRef;
oldRefMapping.put(oldRef, ref);
}
return ref;
return oldRefMapping.getOrPutComputed(oldRef, () => this.newRef);
}
const key = oldRef.toString();
@ -530,6 +543,14 @@ class PDFEditor {
return ref;
}
async #resolveStructKids(rawKids, xref) {
if (rawKids instanceof Ref) {
const fetched = await xref.fetchAsync(rawKids);
return Array.isArray(fetched) ? fetched : [rawKids];
}
return Array.isArray(rawKids) ? rawKids : [rawKids];
}
async #cloneStructTreeNode(
parentStructRef,
node,
@ -547,19 +568,11 @@ class PDFEditor {
if (pg instanceof Ref && !pagesMap.has(pg)) {
return null;
}
let kids;
const k = (kids = node.getRaw("K"));
if (k instanceof Ref) {
// We're only interested by ref referencing nodes and not an array.
if (visited.has(k)) {
const k = node.getRaw("K");
if (k instanceof Ref && visited.has(k)) {
return null;
}
kids = await xref.fetchAsync(k);
if (!Array.isArray(kids)) {
kids = [k];
}
}
kids = Array.isArray(kids) ? kids : [kids];
const kids = await this.#resolveStructKids(k, xref);
const newKids = [];
const structElemIndices = [];
for (let kid of kids) {
@ -620,10 +633,15 @@ class PDFEditor {
if (!kidRef) {
continue;
}
const newKidRef = oldRefMapping.get(kidRef);
if (!newKidRef) {
// Only keep the reference when its target was actually copied. A link
// annotation targeting a removed page is dropped, so skip its OBJR.
const oldObjRef = kid.getRaw("Obj");
if (oldObjRef instanceof Ref && !oldRefMapping.get(oldObjRef)) {
continue;
}
const newKidRef =
oldRefMapping.get(kidRef) ||
(await this.#collectDependencies(kidRef, true, xref));
const newKid = this.xref[newKidRef.num];
// Fix the missing StructParent entry in the referenced object.
const objRef = newKid.getRaw("Obj");
@ -709,12 +727,21 @@ class PDFEditor {
}
for (let attr of attributes) {
attr = this.xrefWrapper.fetchIfRef(attr);
if (!(attr instanceof Dict)) {
// An attribute array may interleave dictionaries and revision
// numbers (ISO 32000-2, 14.7.6.3).
continue;
}
if (isName(attr.get("O"), "Table") && attr.has("Headers")) {
const headers = this.xrefWrapper.fetchIfRef(attr.getRaw("Headers"));
if (Array.isArray(headers)) {
for (let i = 0, ii = headers.length; i < ii; i++) {
const header = this.xrefWrapper.fetchIfRef(headers[i]);
if (typeof header !== "string") {
continue;
}
const newId = dedupIDs.get(
stringToPDFString(headers[i], /* keepEscapeSequence = */ false)
stringToPDFString(header, /* keepEscapeSequence = */ false)
);
if (newId) {
headers[i] = newId;
@ -1206,15 +1233,12 @@ class PDFEditor {
if (!isName(annotationDict.get("Subtype"), "Link")) {
if (isName(annotationDict.get("Subtype"), "Widget")) {
hasSignatureAnnotations ||= isName(
annotationDict.get("FT"),
getInheritableProperty({ dict: annotationDict, key: "FT" }),
"Sig"
);
const parentRef = annotationDict.get("Parent") || null;
// We remove the parent to avoid visiting it when cloning the
// annotation.
// It'll be fixed later in #mergeAcroForms when merging the
// AcroForms.
annotationDict.delete("Parent");
const parentRef = annotationDict.getRaw("Parent") || null;
// The parent will be omitted from the annotation clone to avoid
// visiting it, then restored by #mergeAcroForms.
fieldToParent.put(annotationRef, parentRef);
}
@ -1222,6 +1246,13 @@ class PDFEditor {
return;
}
const action = annotationDict.get("A");
if (action instanceof Dict && !isName(action.get("S"), "GoTo")) {
// Only GoTo actions point to pages in the current document. Other
// actions, such as GoToR, must not be filtered using the current
// document's page map.
newAnnotations[newAnnotationIndex] = annotationRef;
return;
}
const dest =
action instanceof Dict
? action.get("D")
@ -1233,9 +1264,9 @@ class PDFEditor {
) {
// Keep the annotation as is: it isn't linking to a deleted page.
newAnnotations[newAnnotationIndex] = annotationRef;
} else if (typeof dest === "string") {
} else if (dest instanceof Name || typeof dest === "string") {
const destString = stringToPDFString(
dest,
dest instanceof Name ? dest.name : dest,
/* keepEscapeSequence = */ true
);
if (destinations.has(destString)) {
@ -1516,17 +1547,24 @@ class PDFEditor {
}
// Get the kids.
let kids = structTreeRoot.dict.get("K");
if (!kids) {
const rawKids = structTreeRoot.dict.getRaw("K");
if (!rawKids) {
continue;
}
kids = Array.isArray(kids) ? kids : [kids];
const kids = await this.#resolveStructKids(rawKids, xref);
for (let kid of kids) {
const kidRef = kid instanceof Ref ? kid : null;
if (kidRef && removedStructElements.has(kidRef)) {
kid = await xref.fetchIfRefAsync(kid);
if (!(kid instanceof Dict)) {
continue;
}
kid = await xref.fetchIfRefAsync(kid);
let setAsSpan = false;
if (kidRef && removedStructElements.has(kidRef)) {
if (!isName(kid.get("S"), "Link")) {
continue;
}
setAsSpan = true;
}
const newKidRef = await this.#cloneStructTreeNode(
kidRef,
kid,
@ -1538,6 +1576,12 @@ class PDFEditor {
);
if (newKidRef) {
structTreeKids.push(newKidRef);
if (kidRef) {
oldRefMapping.put(kidRef, newKidRef);
}
if (setAsSpan) {
this.xref[newKidRef.num].setIfName("S", "Span");
}
}
}
@ -1595,7 +1639,7 @@ class PDFEditor {
}
const { destinations, pagesMap } = documentData;
const newDestinations = (documentData.destinations = new Map());
for (const [key, dest] of Object.entries(destinations)) {
for (const [key, dest] of destinations) {
const pageRef = dest[0];
const pageData = pageRef instanceof Ref && pagesMap.get(pageRef);
if (!pageData) {
@ -2089,14 +2133,14 @@ class PDFEditor {
* If the document has some fields but no Fields entry in the AcroForm, we
* need to fix that by creating a Fields entry with the oldest parent field
* for each field.
* @param {Map<Ref, Ref>} fieldToParent
* @param {RefSetCache} fieldToParent
* @param {XRef} xref
* @returns {Array<Ref>}
*/
#fixFields(fieldToParent, xref) {
const newFields = [];
const processed = new RefSet();
for (const [fieldRef, parentRef] of fieldToParent) {
for (const [fieldRef, parentRef] of fieldToParent.items()) {
if (!parentRef) {
newFields.push(fieldRef);
continue;
@ -2210,11 +2254,7 @@ class PDFEditor {
if (data.parentRef) {
newKid.set("Parent", data.parentRef);
}
if (
acroFormDefaultAppearance &&
isName(newKid.get("FT"), "Tx") &&
!newKid.has("DA")
) {
if (acroFormDefaultAppearance && !newKid.has("DA")) {
// Fix the DA later since we need to have all the fields tree.
daToFix.push(newKid);
}
@ -2232,6 +2272,10 @@ class PDFEditor {
}
for (const field of daToFix) {
const fieldType = getInheritableProperty({ dict: field, key: "FT" });
if (!isName(fieldType, "Tx")) {
continue;
}
const da = getInheritableProperty({ dict: field, key: "DA" });
if (!da) {
// No DA in a parent field, we can set the default one.
@ -2239,36 +2283,27 @@ class PDFEditor {
}
}
const resourcesValuesCache = new Map();
for (const field of drToFix) {
const ap = field.get("AP");
for (const [, value] of ap) {
if (!(value instanceof BaseStream)) {
continue;
}
let resources = value.dict.getRaw("Resources");
if (!resources) {
const newResourcesRef =
await resourcesValuesCache.getOrInsertComputed(
const fixAppearanceResources = async stream => {
let resources = stream.dict.getRaw("Resources");
resources &&= this.xrefWrapper.fetchIfRef(resources);
if (!(resources instanceof Dict)) {
const newResourcesRef = await resourcesValuesCache.getOrInsertComputed(
acroFormDefaultResources,
() => this.#cloneObject(acroFormDefaultResources, xref)
);
value.dict.set("Resources", newResourcesRef);
continue;
stream.dict.set("Resources", newResourcesRef);
return;
}
resources = xref.fetchIfRef(resources);
for (const [
resKey,
resValue,
] of acroFormDefaultResources.getRawEntries()) {
if (!resources.has(resKey)) {
if (resources.has(resKey)) {
continue;
}
let newResValue = resValue;
if (resValue instanceof Ref) {
newResValue = await this.#collectDependencies(
resValue,
true,
xref
);
newResValue = await this.#collectDependencies(resValue, true, xref);
} else if (
resValue instanceof Dict ||
resValue instanceof BaseStream ||
@ -2281,6 +2316,19 @@ class PDFEditor {
}
resources.set(resKey, newResValue);
}
};
for (const field of drToFix) {
const ap = field.get("AP");
for (const [, value] of ap) {
if (value instanceof BaseStream) {
await fixAppearanceResources(value);
} else if (value instanceof Dict) {
for (const [, stream] of value) {
if (stream instanceof BaseStream) {
await fixAppearanceResources(stream);
}
}
}
}
}
@ -2645,7 +2693,15 @@ class PDFEditor {
#makeNameNumTree(map, areNames) {
const allEntries = map.sort(
areNames
? ([keyA], [keyB]) => keyA.localeCompare(keyB)
? ([keyA], [keyB]) => {
if (keyA < keyB) {
return -1;
}
if (keyA > keyB) {
return 1;
}
return 0;
}
: ([keyA], [keyB]) => keyA - keyB
);
const maxLeaves =
@ -2722,7 +2778,7 @@ class PDFEditor {
/* keepEscapeSequence = */ true
);
for (let i = 1; ; i++) {
const deduped = `${displayName}_${i}`;
const deduped = stringToAsciiOrUTF16BE(`${displayName}_${i}`);
if (!embeddedFiles.has(deduped)) {
name = deduped;
break;
@ -2768,7 +2824,10 @@ class PDFEditor {
this.namesDict.set(
"Dests",
this.#makeNameNumTree(
Array.from(namedDestinations.entries()),
Array.from(namedDestinations, ([name, dest]) => [
stringToAsciiOrUTF16BE(name),
dest,
]),
/* areNames = */ true
)
);
@ -2855,7 +2914,7 @@ class PDFEditor {
acroForm.set("SigFlags", this.acroFormSigFlags);
}
acroForm.setIfArray("CO", this.acroFormCalculationOrder);
acroForm.setIfDict("DR", this.acroFormDefaultResources);
acroForm.setIfDefined("DR", this.acroFormDefaultResources);
if (this.acroFormDefaultAppearance) {
acroForm.set("DA", this.acroFormDefaultAppearance);
}

View File

@ -200,8 +200,7 @@ async function createImage(bitmap, xref, { closeBitmap = false } = {}) {
const colorCounter = new Set();
let hasAlpha = false;
let useFlate = true;
for (let i = 0, ii = buf32.length; i < ii; i++) {
const v = buf32[i];
for (const v of buf32) {
if ((isLE ? v >>> 24 : v & 0xff) !== 0xff) {
hasAlpha = true;
break;

View File

@ -33,10 +33,6 @@ import {
import { CheckedOperatorList, OperatorList } from "./operator_list.js";
import { CMapFactory, IdentityCMap } from "./cmap.js";
import { Cmd, Dict, EOF, isName, Name, Ref, RefSet } from "./primitives.js";
import {
compileFontPathInfo,
compilePatternInfo,
} from "./obj_bin_transform_core.js";
import {
compileType3Glyph,
FontFlags,
@ -83,6 +79,7 @@ import { BaseStream } from "./base_stream.js";
import { bidi } from "./bidi.js";
import { ColorSpace } from "./colorspace.js";
import { ColorSpaceUtils } from "./colorspace_utils.js";
import { compilePatternInfo } from "./obj_bin_transform_core.js";
import { getFontSubstitution } from "./font_substitutions.js";
import { getGlyphsUnicode } from "./glyphlist.js";
import { getMetrics } from "./metrics.js";
@ -143,12 +140,7 @@ function normalizeBlendMode(value, parsingArray = false) {
return "source-over";
}
if (!(value instanceof Name)) {
if (parsingArray) {
return null;
}
return "source-over";
}
if (value instanceof Name) {
switch (value.name) {
case "Normal":
case "Compatible":
@ -184,11 +176,9 @@ function normalizeBlendMode(value, parsingArray = false) {
case "Luminosity":
return "luminosity";
}
if (parsingArray) {
return null;
}
warn(`Unsupported blend mode: ${value.name}`);
return "source-over";
}
return parsingArray ? null : "source-over";
}
function addCachedImageOps(
@ -1991,40 +1981,64 @@ class PartialEvaluator {
return;
}
case OPS.setFillColor:
if (!isNumberArray(args, null)) {
continue;
}
cs = stateManager.state.fillColorSpace;
args = [cs.getRgbHex(args, 0)];
fn = OPS.setFillRGBColor;
break;
case OPS.setStrokeColor:
if (!isNumberArray(args, null)) {
continue;
}
cs = stateManager.state.strokeColorSpace;
args = [cs.getRgbHex(args, 0)];
fn = OPS.setStrokeRGBColor;
break;
case OPS.setFillGray:
if (!isNumberArray(args, null)) {
continue;
}
stateManager.state.fillColorSpace = ColorSpaceUtils.gray;
args = [ColorSpaceUtils.gray.getRgbHex(args, 0)];
fn = OPS.setFillRGBColor;
break;
case OPS.setStrokeGray:
if (!isNumberArray(args, null)) {
continue;
}
stateManager.state.strokeColorSpace = ColorSpaceUtils.gray;
args = [ColorSpaceUtils.gray.getRgbHex(args, 0)];
fn = OPS.setStrokeRGBColor;
break;
case OPS.setFillCMYKColor:
if (!isNumberArray(args, null)) {
continue;
}
stateManager.state.fillColorSpace = ColorSpaceUtils.cmyk;
args = [ColorSpaceUtils.cmyk.getRgbHex(args, 0)];
fn = OPS.setFillRGBColor;
break;
case OPS.setStrokeCMYKColor:
if (!isNumberArray(args, null)) {
continue;
}
stateManager.state.strokeColorSpace = ColorSpaceUtils.cmyk;
args = [ColorSpaceUtils.cmyk.getRgbHex(args, 0)];
fn = OPS.setStrokeRGBColor;
break;
case OPS.setFillRGBColor:
if (!isNumberArray(args, null)) {
continue;
}
stateManager.state.fillColorSpace = ColorSpaceUtils.rgb;
args = [ColorSpaceUtils.rgb.getRgbHex(args, 0)];
break;
case OPS.setStrokeRGBColor:
if (!isNumberArray(args, null)) {
continue;
}
stateManager.state.strokeColorSpace = ColorSpaceUtils.rgb;
args = [ColorSpaceUtils.rgb.getRgbHex(args, 0)];
break;
@ -2041,6 +2055,9 @@ class PartialEvaluator {
break;
}
if (cs.name === "Pattern") {
if (!Array.isArray(args)) {
continue;
}
next(
self.handleColorN(
operatorList,
@ -2058,6 +2075,9 @@ class PartialEvaluator {
);
return;
}
if (!isNumberArray(args, null)) {
continue;
}
args = [cs.getRgbHex(args, 0)];
fn = OPS.setFillRGBColor;
break;
@ -2074,6 +2094,9 @@ class PartialEvaluator {
break;
}
if (cs.name === "Pattern") {
if (!Array.isArray(args)) {
continue;
}
next(
self.handleColorN(
operatorList,
@ -2091,6 +2114,9 @@ class PartialEvaluator {
);
return;
}
if (!isNumberArray(args, null)) {
continue;
}
args = [cs.getRgbHex(args, 0)];
fn = OPS.setStrokeRGBColor;
break;
@ -3273,9 +3299,7 @@ class PartialEvaluator {
const spaceFactor =
((textState.font.vertical ? 1 : -1) * textState.fontSize) / 1000;
const elements = args[0];
for (let i = 0, ii = elements.length; i < ii; i++) {
const item = elements[i];
for (const item of args[0]) {
if (typeof item === "string") {
showSpacedTextBuffer.push(item);
} else if (typeof item === "number" && item !== 0) {
@ -4775,10 +4799,10 @@ class PartialEvaluator {
function buildPath(fontChar) {
const glyphName = `${font.loadedName}_path_${fontChar}`;
try {
if (font.renderer.hasBuiltPath(fontChar)) {
return;
const buffer = font.renderer.getPath(fontChar);
if (!buffer) {
return; // Previously compiled, and sent to the main-thread.
}
const buffer = compileFontPathInfo(font.renderer.getPathJs(fontChar));
handler.send("commonobj", [glyphName, "FontPath", buffer], [buffer]);
} catch (reason) {
if (evaluatorOptions.ignoreErrors) {

View File

@ -26,6 +26,7 @@ import {
warn,
} from "../shared/util.js";
import { CFFParser } from "./cff_parser.js";
import { compileFontPathInfo } from "./obj_bin_transform_core.js";
import { getGlyphsUnicode } from "./glyphlist.js";
import { isNumberArray } from "./core_utils.js";
import { StandardEncoding } from "./encodings.js";
@ -781,6 +782,10 @@ class Commands {
}
class CompiledFont {
#compiledCharCodes = new Set();
#compiledGlyphs = new Map();
constructor(fontMatrix) {
if (
(typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) &&
@ -789,9 +794,6 @@ class CompiledFont {
unreachable("Cannot initialize CompiledFont.");
}
this.fontMatrix = fontMatrix;
this.compiledGlyphs = Object.create(null);
this.compiledCharCodeToGlyphId = Object.create(null);
}
static get NOOP() {
@ -805,26 +807,29 @@ class CompiledFont {
);
}
getPathJs(unicode) {
getPath(unicode) {
const { charCode, glyphId } = lookupCmap(this.cmap, unicode);
let fn = this.compiledGlyphs[glyphId],
compileEx;
if (fn === undefined) {
if (
this.#compiledGlyphs.has(glyphId) &&
this.#compiledCharCodes.has(charCode)
) {
return null; // Previously compiled.
}
const path = this.#compiledGlyphs.getOrInsertComputed(glyphId, () => {
try {
fn = this.compileGlyph(this.glyphs[glyphId], glyphId);
return this.compileGlyph(this.glyphs[glyphId], glyphId);
} catch (ex) {
fn = CompiledFont.NOOP; // Avoid attempting to re-compile a corrupt glyph.
return ex; // Avoid attempting to re-compile a corrupt glyph.
}
});
this.#compiledCharCodes.add(charCode);
compileEx = ex;
if (path instanceof Error) {
throw path;
}
this.compiledGlyphs[glyphId] = fn;
}
this.compiledCharCodeToGlyphId[charCode] ??= glyphId;
if (compileEx) {
throw compileEx;
}
return fn;
return compileFontPathInfo(path);
}
compileGlyph(code, glyphId) {
@ -857,14 +862,6 @@ class CompiledFont {
compileGlyphImpl() {
unreachable("Children classes should implement this.");
}
hasBuiltPath(unicode) {
const { charCode, glyphId } = lookupCmap(this.cmap, unicode);
return (
this.compiledGlyphs[glyphId] !== undefined &&
this.compiledCharCodeToGlyphId[charCode] !== undefined
);
}
}
class TrueTypeCompiled extends CompiledFont {

View File

@ -1525,9 +1525,9 @@ class Font {
}
const [nameTable] = readNameTable(potentialTables.name);
for (let j = 0, jj = nameTable.length; j < jj; j++) {
for (let k = 0, kk = nameTable[j].length; k < kk; k++) {
const nameEntry = nameTable[j][k]?.replaceAll(/\s/g, "");
for (const nameArr of nameTable) {
for (const entry of nameArr) {
const nameEntry = entry?.replaceAll(/\s/g, "");
if (!nameEntry) {
continue;
}
@ -3710,7 +3710,7 @@ class Font {
for (let i = 0, ii = str.length; i < ii; i++) {
const unicode = str.codePointAt(i);
if (unicode > 0xd7ff && (unicode < 0xe000 || unicode > 0xfffd)) {
if (unicode > 0xffff) {
// unicode is represented by two uint16
i++;
}

View File

@ -151,9 +151,8 @@ function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) {
glyphId = glyphNames.indexOf(glyphName);
if (glyphId === -1) {
if (!glyphsUnicodeMap) {
glyphsUnicodeMap = getGlyphsUnicode();
}
glyphsUnicodeMap ??= getGlyphsUnicode();
const standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
if (standardGlyphName !== glyphName) {
glyphId = glyphNames.indexOf(standardGlyphName);

View File

@ -13,6 +13,8 @@
* limitations under the License.
*/
import { makeSet } from "../shared/util.js";
const ON_CURVE_POINT = 1 << 0;
const X_SHORT_VECTOR = 1 << 1;
const Y_SHORT_VECTOR = 1 << 2;
@ -610,24 +612,20 @@ class CompositeGlyph {
size += 2;
if (this.flags & 2) {
// Arguments are signed.
if (
!(
if (!(
this.argument1 >= -128 &&
this.argument1 <= 127 &&
this.argument2 >= -128 &&
this.argument2 <= 127
)
) {
)) {
size += 2;
}
} else if (
!(
} else if (!(
this.argument1 >= 0 &&
this.argument1 <= 255 &&
this.argument2 >= 0 &&
this.argument2 <= 255
)
) {
)) {
size += 2;
}
@ -639,24 +637,20 @@ class CompositeGlyph {
if (this.flags & ARGS_ARE_XY_VALUES) {
// Arguments are signed.
if (
!(
if (!(
this.argument1 >= -128 &&
this.argument1 <= 127 &&
this.argument2 >= -128 &&
this.argument2 <= 127
)
) {
)) {
this.flags |= ARG_1_AND_2_ARE_WORDS;
}
} else if (
!(
} else if (!(
this.argument1 >= 0 &&
this.argument1 <= 255 &&
this.argument2 >= 0 &&
this.argument2 <= 255
)
) {
)) {
this.flags |= ARG_1_AND_2_ARE_WORDS;
}
@ -764,13 +758,7 @@ function pruneCompositeGlyphCycles(glyfTable, locaEntries, numGlyphs) {
stack.push({ node: next, idx: 0 });
continue;
}
let removeSet = backEdges.get(top.node);
if (!removeSet) {
removeSet = new Set();
backEdges.set(top.node, removeSet);
}
removeSet.add(compIdx);
backEdges.getOrInsertComputed(top.node, makeSet).add(compIdx);
}
}

View File

@ -61,30 +61,28 @@ class IccColorSpace extends ColorSpace {
switch (numComps) {
case 1:
inType = DataType.Gray8;
this.#convertPixel = (src, srcOffset, css) =>
qcms_convert_one(this.#transformer, src[srcOffset] * 255, css);
this.#convertPixel = (src, srcOffset) =>
qcms_convert_one(this.#transformer, src[srcOffset] * 255);
break;
case 3:
inType = DataType.RGB8;
this.#convertPixel = (src, srcOffset, css) =>
this.#convertPixel = (src, srcOffset) =>
qcms_convert_three(
this.#transformer,
src[srcOffset] * 255,
src[srcOffset + 1] * 255,
src[srcOffset + 2] * 255,
css
src[srcOffset + 2] * 255
);
break;
case 4:
inType = DataType.CMYK;
this.#convertPixel = (src, srcOffset, css) =>
this.#convertPixel = (src, srcOffset) =>
qcms_convert_four(
this.#transformer,
src[srcOffset] * 255,
src[srcOffset + 1] * 255,
src[srcOffset + 2] * 255,
src[srcOffset + 3] * 255,
css
src[srcOffset + 3] * 255
);
break;
default:
@ -105,15 +103,31 @@ class IccColorSpace extends ColorSpace {
}
getRgbHex(src, srcOffset) {
this.#convertPixel(src, srcOffset, /* css */ true);
return QCMS._cssColor;
const color = this.#convertPixel(src, srcOffset);
return Util.makeHexColor(color >> 16, (color >> 8) & 0xff, color & 0xff);
}
getRgbItem(src, srcOffset, dest, destOffset) {
const color = this.#convertPixel(src, srcOffset);
dest[destOffset] = color >> 16;
dest[destOffset + 1] = (color >> 8) & 0xff;
dest[destOffset + 2] = color & 0xff;
}
getRgbItems(src, count, dest, destOffset, alpha01) {
const { numComps } = this;
const length = count * numComps;
const scaled = new Uint8Array(length);
// Uint8Array matches the truncation and wrapping of the scalar Wasm calls.
for (let i = 0; i < length; i++) {
scaled[i] = src[i] * 255;
}
QCMS._destBuffer = dest;
QCMS._destOffset = destOffset;
QCMS._destLength = 3;
this.#convertPixel(src, srcOffset, /* css */ false);
// `scaled` is freshly allocated, so unlike in getRgbBuffer it can never
// alias `dest`: an RGBA destination always has an alpha channel to keep.
QCMS._keepAlpha = alpha01 === 1;
qcms_convert_array(this.#transformer, scaled, alpha01 === 1);
QCMS._destBuffer = null;
}
@ -125,12 +139,12 @@ class IccColorSpace extends ColorSpace {
src[i] *= scale;
}
}
QCMS._mustAddAlpha = alpha01 && dest.buffer === src.buffer;
QCMS._destBuffer = dest;
QCMS._destOffset = destOffset;
QCMS._destLength = count * (3 + alpha01);
qcms_convert_array(this.#transformer, src);
QCMS._mustAddAlpha = false;
// The wasm side always fills alpha in, so say when the destination's own
// alpha must survive: an /SMask has been decoded into it by now.
QCMS._keepAlpha = alpha01 === 1 && dest.buffer !== src.buffer;
qcms_convert_array(this.#transformer, src, alpha01 === 1);
QCMS._destBuffer = null;
}
@ -157,7 +171,6 @@ class IccColorSpace extends ColorSpace {
});
isUsable = !!this._module;
QCMS._memory = this._module.memory;
QCMS._makeHexColor = Util.makeHexColor.bind(Util);
} catch (e) {
warn(`ICCBased color space: "${e}".`);
}

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