Compare commits

..

316 Commits

Author SHA1 Message Date
calixteman
2a68724b53
Merge pull request #17793 from calixteman/zoom_wheel_ctrl
When zooming the scrollbar can disappear and then no scrollend is triggered
2024-03-15 16:30:39 +01:00
Calixte Denizet
65d618635c When zooming the scrollbar can disappear and then no scrollend is triggered 2024-03-15 15:37:06 +01:00
Jonas Jenwald
30e69956db
Merge pull request #17694 from Snuffleupagus/validate-defaultOptions
Add better validation for the "PREFERENCE" kind `AppOptions`
2024-03-12 18:24:37 +01:00
Jonas Jenwald
e650b95253
Merge pull request #17714 from Snuffleupagus/Node-fs-promise
Use `fs/promises` in the Node.js-specific code in the `src/`-folder
2024-03-12 18:09:33 +01:00
calixteman
a7d47af474
Merge pull request #17732 from calixteman/editor_highlight_floating_button
[Editor] Add a floating button close to the selected text to highlight it (bug 1867742)
2024-03-12 15:43:19 +01:00
Jonas Jenwald
b54887cfab
Merge pull request #17717 from Snuffleupagus/pr-17681-follow-up
Combine a few lines in the `dist-pre` target (PR 17681 follow-up)
2024-03-12 15:15:19 +01:00
Calixte Denizet
b4267cd294 [Editor] Add a floating button close to the selected text to highlight it (bug 1867742)
For now keep this feature behind a pref in order to make some experiments before
deciding to enable it.
2024-03-12 15:06:46 +01:00
Jonas Jenwald
eb160726ee
Merge pull request #17726 from Snuffleupagus/OptionalContent-Usage
[api-minor] Implement basic support for OptionalContent `Usage` dicts (issue 5764, bug 1826783)
2024-03-12 14:09:57 +01:00
Jonas Jenwald
70b6ddc5d9 Move the /SetOCGState handling into the OptionalContentConfig class (PR 15377 follow-up)
This helps ensure that /SetOCGState actions always take the `Usage` dictionary into account as expected.
2024-03-12 13:18:15 +01:00
Jonas Jenwald
3c78ff5fb0 [api-minor] Implement basic support for OptionalContent Usage dicts (issue 5764, bug 1826783)
The following are some highlights of this patch:
 - In the Worker we only extract a *subset* of the potential contents of the `Usage` dictionary, to avoid having to implement/test a bunch of code that'd be completely unused in the viewer.

 - In order to still allow the user to *manually* override the default visible layers in the viewer, the viewable/printable state is purposely *not* enforced during initialization in the `OptionalContentConfig` constructor.

 - Printing will now always use the *default* visible layers, rather than using the same state as the viewer (as was the case previously).
   This ensures that the printing-output will correctly take the `Usage` dictionary into account, and in practice toggling of visible layers rarely seem to be necessary except in the viewer itself (if at all).[1]

---
[1] In the unlikely case that it'd ever be deemed necessary to support fine-grained control of optional content visibility during printing, some new (additional) UI would likely be needed to support that case.
2024-03-12 13:18:15 +01:00
calixteman
e647311a89
Merge pull request #17788 from calixteman/bug1881743
[Editor] Improve the accessibility of the highlight editor (bug 1881743)
2024-03-11 21:57:11 +01:00
Calixte Denizet
f676c2c0c8 [Editor] Improve the accessibility of the highlight editor (bug 1881743) 2024-03-11 14:21:43 +01:00
Jonas Jenwald
b14f696071
Merge pull request #17711 from Snuffleupagus/importl10n-Fetch-API
Use the Fetch API to download the l10n files
2024-03-08 11:51:34 +01:00
Jonas Jenwald
ea4b55a0e6 Update l10n files 2024-03-08 10:09:51 +01:00
Jonas Jenwald
2b407990e2 Use the Fetch API to download the l10n files
Given that the Fetch API is supported since Node.js 18 we should be able to use it when downloading l10n files, which allows us to simplify the code and to make it fully `async`.
2024-03-08 10:08:15 +01:00
calixteman
fb9e438442
Merge pull request #17781 from calixteman/stamp_altext_button_cp
[Editor] Make sure the alt-text button is there when pasting an image from an other tab
2024-03-07 21:44:53 +01:00
calixteman
406018934a
Merge pull request #17778 from calixteman/highlight_show_all
[Editor] Add a toggle button to show/hide all the highlights (bug 1867740)
2024-03-07 18:49:09 +01:00
Calixte Denizet
0f8dda1af0 [Editor] Make sure the alt-text button is there when pasting an image from an other tab 2024-03-07 18:24:34 +01:00
Calixte Denizet
39aeea3e94 [Editor] Add a toggle button to show/hide all the highlights (bug 1867740) 2024-03-07 13:16:59 +01:00
calixteman
6bb6ce6a5d
Merge pull request #17767 from calixteman/automation_win_listener
In the m-c automation, give the possibility to remove window listeners when a test ended
2024-03-06 14:39:58 +01:00
Calixte Denizet
6d0835dc52 In the m-c automation, give the possibility to remove window listeners when a test ended
The goal is to avoid to have some exceptions in the logs when a test finished.
2024-03-06 14:21:57 +01:00
calixteman
9ee4c6528d
Merge pull request #17776 from calixteman/bug1883609
[Annotations] Widget annotations must be in front of the other ones (bug 1883609)
2024-03-06 10:53:11 +01:00
Calixte Denizet
4e1b96c781 [Annotations] Widget annotations must be in front of the other ones (bug 1883609) 2024-03-05 19:04:58 +01:00
calixteman
f634cb533c
Merge pull request #17775 from calixteman/bug1883632
[Editor] Let a free highlight be clipped when its bounding box exceeds the page limits (bug 1883632)
2024-03-05 17:14:48 +01:00
Calixte Denizet
bd5875d066 [Editor] Let a free highlight be clipped when its bounding box exceeds the page limits (bug 1883632) 2024-03-05 16:47:07 +01:00
calixteman
f1272ee435
Merge pull request #17771 from calixteman/bug1832519
[GeckoView] Remove the open-in-app button (bug 1832519)
2024-03-05 14:11:12 +01:00
calixteman
b447a62fea
Merge pull request #17772 from calixteman/reporttelemetry
Don't stringify data for telemetry
2024-03-05 12:54:24 +01:00
Calixte Denizet
ba3e559583 Don't stringify data for telemetry 2024-03-04 20:17:47 +01:00
Calixte Denizet
3cb58f84a2 [GeckoView] Remove the open-in-app button (bug 1832519) 2024-03-04 19:32:12 +01:00
calixteman
c451b6d684
Merge pull request #17764 from calixteman/telemetry_null_stats
[Editor] Use a null instead of an empty stats object when sending the telemetry
2024-03-04 19:16:57 +01:00
calixteman
a55f976e2e
Merge pull request #17766 from calixteman/escape_color_picker
[Editor] Unselect highlight editor when pressing Escape when the focus is on the color picker without a dropdown menu
2024-03-04 19:16:34 +01:00
calixteman
7c9d3af85b
Merge pull request #17768 from calixteman/bug1883394
[Editor] Set the creation method for free highlights to 'main_toolbar' (bug 1883394)
2024-03-04 19:16:15 +01:00
Calixte Denizet
ecb4262b13 [Editor] Set the creation method for free highlights to 'main_toolbar' (bug 1883394) 2024-03-04 16:58:50 +01:00
Calixte Denizet
1859412507 [Editor] Unselect highlight editor when pressing Escape when the focus is on the color picker without a dropdown menu 2024-03-04 16:32:09 +01:00
Calixte Denizet
d096dc79b2 [Editor] Use a null instead of an empty stats object when sending the telemetry 2024-03-04 10:18:24 +01:00
Jonas Jenwald
dd3adc84db
Merge pull request #17761 from Snuffleupagus/thicknessPicker-disabled
[Editor] Indicate if the highlight-thickness slider is disabled
2024-03-01 17:01:05 +01:00
Jonas Jenwald
e781b553cb [Editor] Reduce a bit of CSS duplication for the highlight-thickness "indicators" 2024-03-01 16:18:39 +01:00
Jonas Jenwald
c7e7122e25 [Editor] Indicate if the highlight-thickness slider is disabled
The fact that the highlight-thickness can only be changed in "free" mode isn't really obvious visually in the toolbar, so attempt to provide at least some indication of the `disabled`-state by "dimming" the slider.
2024-03-01 16:18:31 +01:00
calixteman
29c493d36b
Merge pull request #17760 from calixteman/fix_quadpoints
[Editor] Fix the quadpoints value when serializing an highlight annotation
2024-03-01 13:08:44 +01:00
Calixte Denizet
30101cbb31 [Editor] Fix the quadpoints value when serializing an highlight annotation
The coordinates of each point in a box are in the page coordinates system.
2024-03-01 11:36:16 +01:00
Jonas Jenwald
61036383b5
Merge pull request #17710 from Snuffleupagus/pr-17277-followup
Simplify the `XMLHttpRequest`-branch in the `fetchData` helper function (PR 17277 follow-up)
2024-03-01 10:23:02 +01:00
calixteman
8f75e34b6f
Merge pull request #17757 from calixteman/bug1881219
[Editor] Enable the thickness input when no editors are selected (bug 1881219)
2024-02-29 23:26:49 +01:00
Calixte Denizet
7af90bb8bc [Editor] Enable the thickness input when no editors are selected (bug 1881219) 2024-02-29 23:05:33 +01:00
calixteman
c409121251
Merge pull request #17756 from calixteman/bug1882248
[Editor] Make the delete button clickable with the space key (bug 1882248)
2024-02-29 19:57:57 +01:00
Calixte Denizet
f52bf2836f [Editor] Make the delete button clickable with the space key (bug 1882248) 2024-02-29 19:05:38 +01:00
calixteman
7cc34cf4a7
Merge pull request #17755 from calixteman/bug1881684
[Editor] Add the possibility to move the caret with the keyboard once  an highlight has been made (bug 1881684)
2024-02-29 18:38:17 +01:00
Calixte Denizet
a9f47e87d5 [Editor] Add the possibility to move the caret with the keyboard once an highlight has been made (bug 1881684) 2024-02-29 18:18:13 +01:00
Jonas Jenwald
9600c48d4f
Merge pull request #17750 from Snuffleupagus/pr-17748-followup
Inline the `HighlightEditor.#telemetryType` getter at its only call-site (PR 17748 follow-up)
2024-02-29 10:34:37 +01:00
Jonas Jenwald
a92b38e71c Inline the HighlightEditor.#telemetryType getter at its only call-site (PR 17748 follow-up) 2024-02-28 20:47:01 +01:00
calixteman
9fe15d4a01
Merge pull request #17748 from calixteman/highlight_telemetry_followup
[Editor] Count the colors used when highlighting whatever the highlight kind is
2024-02-28 20:00:15 +01:00
Calixte Denizet
3a7e638fce [Editor] Count the colors used when highlighting whatever the highlight kind is 2024-02-28 18:24:24 +01:00
calixteman
07abd647f4
Merge pull request #17737 from calixteman/highlight_telemetry
[Editor] Add some telemetry for the highlight feature (bug 1866437)
2024-02-28 15:20:57 +01:00
Calixte Denizet
65342d2bee [Editor] Add some telemetry for the highlight feature (bug 1866437) 2024-02-28 10:17:11 +01:00
calixteman
b1a04fc184
Merge pull request #17738 from calixteman/issue17730
Always add links in the annotation layer
2024-02-28 09:34:10 +01:00
Calixte Denizet
e0b843d991 Always add links in the annotation layer
Fixes #17730.
2024-02-27 22:48:08 +01:00
calixteman
06aef89502
Merge pull request #17733 from calixteman/puppeteer_22_1_0
Update puppeteer to 22.3.0
2024-02-27 13:46:30 +01:00
Calixte Denizet
5e7941afbf Update puppeteer to 22.3.0 2024-02-27 12:19:54 +01:00
calixteman
e42b114e80
Merge pull request #17724 from calixteman/issue17707
Avoid to have to wait to zoom after scrolling
2024-02-26 11:05:10 +01:00
Calixte Denizet
9e042e7acc Avoid to have to wait to zoom after scrolling
Allow to zoom with the wheel once the scrolling is finished.
It's now possible to know that thanks to the scrollend event.

Fixes #17707.
2024-02-25 21:40:48 +01:00
calixteman
ca4ab064e5
Merge pull request #17720 from calixteman/editor_simplify_highlighting
[Editor] In caret browsing mode, allow to select in pressing shift and arrow down (bug 1881802)
2024-02-25 17:52:11 +01:00
Calixte Denizet
0520f2f0cb [Editor] In caret browsing mode, allow to select in pressing shift and arrow down (bug 1881802)
In implementing caret browsing mode in pdf.js, I didn't notice that selectstart isn't always triggered.
So this patch removes the use of selectstart and rely only on selectionchange.
In order to simplify the selection management, the selection code is moved in the AnnotationUIManager:
 - it simplifies the code;
 - it allows to have only one listener for selectionchange instead of having one by visible page
   for selectstart.
I had to add a delay in the integration tests for highlighting (there's a comment with an explanation),
it isn't really nice, but it's the only way I found and in real life there always is a delay between
press and release.
2024-02-25 15:35:30 +01:00
calixteman
1bd6af6dae
Merge pull request #17722 from calixteman/issue17721
Fix the string GlobalConstants.IDS_INVALID_DATE
2024-02-23 21:49:42 +01:00
Calixte Denizet
fe41e789de Fix the string GlobalConstants.IDS_INVALID_DATE 2024-02-23 21:39:06 +01:00
Jonas Jenwald
346efe919a
Merge pull request #17718 from Snuffleupagus/hexNumbers-tweak
Tweak how the `hexNumbers` Array, used by `Util.makeHexColor`, is built
2024-02-23 18:17:10 +01:00
calixteman
b8b8f1af66
Merge pull request #17719 from calixteman/bug1881692
[Editor] In caret browsing mode, get the caret position in the text layer (bug 1881692)
2024-02-23 17:11:51 +01:00
Calixte Denizet
bb19cf9b64 [Editor] In caret browsing mode, get the caret position in the text layer (bug 1881692)
The function caretPositionFromPoint return the position within the last visible element
and sometimes there are some elements on top of the ones in the text layer.
So the idea is to hide the visible elements which aren't in the text layer in order
to get the right caret position.
2024-02-23 16:50:19 +01:00
calixteman
101e8efad7
Merge pull request #17708 from calixteman/editor_highlight_context_menu
[Editor] Add the possibility to create an highlight from the context menu when some text is selected (bug 1867739)
2024-02-23 16:39:03 +01:00
Calixte Denizet
e1f6f5179f [Editor] Add the possibility to create an highlight from the context menu when some text is selected (bug 1867739) 2024-02-23 16:18:03 +01:00
Jonas Jenwald
49a2aff532 Tweak how the hexNumbers Array, used by Util.makeHexColor, is built
*Please note:* This is a micro optimization, hence I fully understand if the patch is rejected.

Currently we create two temporary Arrays and have to iterate twice in total when building the final `hexNumbers` Array.
With this patch there's only one temporary Array and a single iteration required to build the final `hexNumbers` Array.
2024-02-23 14:20:53 +01:00
Jonas Jenwald
dab8a2eaa4 Combine a few lines in the dist-pre target (PR 17681 follow-up)
In PR 17681 I completely missed that we can combine a number of lines in the `dist-pre` target, which helps reduce code size a little bit.
2024-02-23 13:32:04 +01:00
Jonas Jenwald
db2849cc17 Use fs/promises in the Node.js-specific code in the src/-folder
This is available in all Node.js versions that we currently support, and using it allows us to remove callback-functions; please see https://nodejs.org/docs/latest-v18.x/api/fs.html#promises-api
2024-02-22 16:50:13 +01:00
Jonas Jenwald
33c5ef349e Simplify the XMLHttpRequest-branch in the fetchData helper function (PR 17277 follow-up) 2024-02-21 23:00:24 +01:00
calixteman
72b8b29147
Merge pull request #17701 from calixteman/alt_text_ai
[Editor] Add the possibility to query some ML stuff to guess an alt text for an image
2024-02-21 10:14:40 +01:00
calixteman
0fb8a23051
Merge pull request #17702 from calixteman/bug1868759
[Editor] Disable annotation layer when highlighting (bug 1868759)
2024-02-21 09:49:48 +01:00
Calixte Denizet
46416bb131 [Editor] Add the possibility to query some ML stuff to guess an alt text for an image
It's only for an experimental purpose.
2024-02-20 21:29:33 +01:00
Calixte Denizet
95f9bedc7c [Editor] Disable annotation layer when highlighting (bug 1868759)
When highlighting, the annotation editor layer is disabled to get pointer events
from the text layer, but the annotation layer must be then disabled either in
order to avoid bad interactions.
2024-02-20 21:17:05 +01:00
Jonas Jenwald
38004b65b1 Re-factor how the compatibilityParams, in the viewer, are handled
Previously we'd simply export this directly from `web/app_options.js`, which meant that it'd be technically possible to *accidentally* modify the `compatibilityParams` Object when accessing it.
To avoid this we instead introduce a new `AppOptions`-method that is used to lookup data in `compatibilityParams`, which means that we no longer need to export this Object.

Based on these changes, it's now possible to simplify some existing code in `AppOptions` by taking full advantage of the nullish coalescing (`??`) operator.
2024-02-20 18:38:18 +01:00
Jonas Jenwald
90b2664622 Add better validation for the "PREFERENCE" kind AppOptions
Given that the "PREFERENCE" kind is used e.g. to generate the preference-list for the Firefox PDF Viewer, those options need to be carefully validated.
With this patch we'll now check this unconditionally in development mode, during testing, and when creating the preferences in the gulpfile.
2024-02-20 18:38:15 +01:00
calixteman
70015ffe6b
Merge pull request #17688 from calixteman/editor_no_scroll_unselect
[Editor] Avoid to scroll when an editor is unselected
2024-02-20 17:00:43 +01:00
calixteman
99fa713fba
Merge pull request #17690 from calixteman/issue17689
Avoid to access to a missing cidSystemInfo property
2024-02-19 12:04:07 +01:00
Calixte Denizet
a6eadf8150 Avoid to access to a missing cidSystemInfo property
Fixes #17689.
2024-02-19 09:55:23 +01:00
Calixte Denizet
c2fcc66302 [Editor] Avoid to scroll when an editor is unselected 2024-02-18 19:21:45 +01:00
Tim van der Meij
d96fd80ca0
Merge pull request #17687 from Snuffleupagus/pr-17686-followup
Disable source-map generation in the minified builds (PR 17686 follow-up)
2024-02-18 13:35:23 +01:00
Jonas Jenwald
673639c54b Disable source-map generation in the minified builds (PR 17686 follow-up)
As part of the changes in PR 17686 we "accidentally" enabled source-maps for the *minified* builds, which seems unnecessary since those have never been included in the `pdfjs-dist` output.
Locally this patch reduces the run-time of `gulp minified` by ~15 percent.
2024-02-17 22:14:37 +01:00
Tim van der Meij
4ac8ee8b6d
Merge pull request #17686 from Snuffleupagus/Webpack-TerserPlugin
Run minification directly during Webpack building
2024-02-17 19:42:35 +01:00
Jonas Jenwald
091e861531 Run minification directly during Webpack building
Rather than first building the library and then use Terser "manually" to minify the files, we can utilize a Webpack plugin to combine these steps which helps to simplify the gulpfile.
2024-02-17 18:51:34 +01:00
Tim van der Meij
8487c67cb8
Merge pull request #17684 from timvandermeij/modernize-webserver-pt2
Modernize the webserver code (part 2)
2024-02-17 18:22:51 +01:00
Tim van der Meij
33955980c8
Merge pull request #17685 from timvandermeij/updates
Update dependencies and translations to the most recent versions
2024-02-17 18:09:51 +01:00
Tim van der Meij
2e6fa797d9
Improve the webserver's constructor
This makes the webserver configurable during instantiation rather than
having to set the parameters afterwards.
2024-02-17 16:22:10 +01:00
Tim van der Meij
985ba77579
Modernize the remainder of the webserver's code and enable the no-var ESLint rule
This commit also moves the content type logic into a helper method to
ever so slightly reduce duplication.
2024-02-17 16:22:10 +01:00
Tim van der Meij
0015eb2431
Modernize the webserver's handler method
This commit converts `var` to `const`/`let`, gives the variables more
readable names and annotates the code to make the flow clearer.
2024-02-17 16:22:10 +01:00
Tim van der Meij
6ef813af01
Extract and modernize the webserver's request checking code
The `handler` method contained this code in two inline functions,
triggered via callbacks, which made the `handler` method big and harder
to read. Moreover, this code relied on variables from the outer scope,
which made it harder to reason about because the inputs and outputs
weren't easily visible.

This commit fixes the problems by extracting the request checking code
into a dedicated private method, and modernizing it to use e.g. `const`/
`let` instead of `var` and using template strings. The logic is now
self-contained in a single method that can be read from top to bottom
without callbacks and with comments annotating each check/section.
2024-02-17 16:22:10 +01:00
Tim van der Meij
43cdc1ca8a
Update translations to the most recent versions 2024-02-17 16:00:18 +01:00
Tim van der Meij
6baa439e15
Update dependencies to the most recent versions 2024-02-17 16:00:18 +01:00
Tim van der Meij
f1a225889b
Merge pull request #17681 from Snuffleupagus/parseMinified-changes
Tweak the `parseMinified` handling slightly in the gulpfile
2024-02-17 15:08:30 +01:00
Tim van der Meij
678c79cc78
Merge pull request #17678 from Snuffleupagus/pr-17637-followup
Remove unneeded `tweakWebpackOutput` usage in the gulpfile (PR 17637 follow-up)
2024-02-17 14:58:24 +01:00
Tim van der Meij
fd5d040073
Merge pull request #17667 from Snuffleupagus/createPrintService-params
Change `PDFPrintServiceFactory.createPrintService` to take a parameter object
2024-02-17 14:54:53 +01:00
Jonas Jenwald
179a3ecee6
Merge pull request #17680 from Snuffleupagus/issue-17679
Add a dummy `beginMarkedContentProps` operator when optional content parsing fails (issue 17679)
2024-02-17 14:29:08 +01:00
Jonas Jenwald
b767e12111
Merge pull request #17676 from Snuffleupagus/app-findBar-optional-chain
Access `PDFViewerApplication.findBar` safely in more spots (PR 15831 follow-up)
2024-02-17 13:54:00 +01:00
Jonas Jenwald
a7bcc81eb1 Add a dummy beginMarkedContentProps operator when optional content parsing fails (issue 17679) 2024-02-17 13:45:16 +01:00
Jonas Jenwald
75a5b2051d Tweak the parseMinified handling slightly in the gulpfile
- Run the minification in "parallel" since that should be a *tiny* bit more efficient.
 - Don't rename the minified files since that seems unnecessary, especially considering that they are only used in the `dist-pre` target where we currently change the name back manually.
2024-02-16 16:54:13 +01:00
Jonas Jenwald
751611f690 Remove unneeded tweakWebpackOutput usage in the gulpfile (PR 17637 follow-up)
After the changes in PR 17637 there's no longer any reason to invoke `tweakWebpackOutput` without an argument, since the `__non_webpack_import__` re-writing was moved into the Babel plugin.
This way we can avoid a (little) bit of unnecessary parsing during building.
2024-02-16 11:42:40 +01:00
Jonas Jenwald
b420bd8b20 Access PDFViewerApplication.findBar safely in more spots (PR 15831 follow-up)
Note that this patch is the result of code-inspection, and the code as written doesn't (currently) cause any bugs in e.g. the GeckoView PDF Viewer.
2024-02-15 11:25:29 +01:00
calixteman
a83a8d7e4f
Merge pull request #17674 from calixteman/issue17671
Fix the endoffset of the last glyph when it's followed by a null offset in the loca table
2024-02-15 10:19:55 +01:00
Jonas Jenwald
dbda3ec5f9
Merge pull request #17637 from Snuffleupagus/babel-plugin-__non_webpack_import__
Move the `__non_webpack_import__` re-writing into the Babel plugin
2024-02-14 22:23:24 +01:00
Calixte Denizet
fcad3718f0 Fix the endoffset of the last glyph when it's followed by a null offset in the loca table
It fixes #17671.
2024-02-14 17:20:04 +01:00
Jonas Jenwald
a204f434f3 Change PDFPrintServiceFactory.createPrintService to take a parameter object
By "modernizing" the method to use a parameter object instead, we avoid having to pass along the needed parameters individually.
2024-02-13 21:28:02 +01:00
calixteman
14874e50b7
Merge pull request #17636 from calixteman/bug1878916
When updating, write the xref table in the same format as the previous one (bug 1878916)
2024-02-13 14:45:14 +01:00
Calixte Denizet
2133da166e When updating, write the xref table in the same format as the previous one (bug 1878916)
The specs are unclear about what kind of xref table format must be used.
In checking the validity of some pdfs in the preflight tool from Acrobat
we can guess that having the same format is the correct way to do.
The pdf in the mentioned bug, after having been changed, wasn't correctly
displayed in neither Chrome nor Acrobat: it's now fixed.
2024-02-13 14:14:37 +01:00
Jonas Jenwald
e60329cea1
Merge pull request #17666 from Snuffleupagus/issue-17665
Skip any whitespace after the first object in linearized PDFs (issue 17665)
2024-02-13 12:39:36 +01:00
Jonas Jenwald
37e98e39f6 Skip any whitespace after the first object in linearized PDFs (issue 17665)
This way the code is now consistent with the non-linearized branch in the `PDFDocument.startXRef` getter.
2024-02-12 22:05:36 +01:00
calixteman
05b035602e
Merge pull request #17664 from calixteman/bug1879281
[Editor] Ends a free highlight where the mouse pointer is (bug 1879281)
2024-02-12 18:39:18 +01:00
Calixte Denizet
750b8e328a [Editor] Ends a free highlight where the mouse pointer is (bug 1879281) 2024-02-12 17:26:33 +01:00
Jonas Jenwald
eb5e6e68d6
Merge pull request #17663 from Snuffleupagus/pr-17428-test
Tweak the issue 11878 unit-test parsing time check (PR 17428 follow-up)
2024-02-12 14:14:29 +01:00
calixteman
f0343dcfdb
Merge pull request #17662 from calixteman/bug1879108
[Editor] Set rotated free highlight at the right position after having changed its thickness (bug 1879108)
2024-02-12 12:41:43 +01:00
Jonas Jenwald
19ef3e367b Tweak the issue 11878 unit-test parsing time check (PR 17428 follow-up)
This unit-test has been failing occasionally in Chrome and Node.js, hence we tweak the parsing time check to reduce the likelihood of that happening.
2024-02-12 12:31:55 +01:00
Jonas Jenwald
18959e80be
Merge pull request #17661 from timvandermeij/modernize-webserver
Modernize the webserver code (part 1)
2024-02-12 11:50:24 +01:00
Jonas Jenwald
4ab0ad3216 Move the __non_webpack_import__ re-writing into the Babel plugin
Note how we're using custom `__non_webpack_import__`-calls in the code-base, that we replace during the post-processing stage of the build, to be able to write `import`-calls that Webpack will leave alone during parsing.
This work-around is necessary since we let Babel discards all comments, given that we generally don't need/want them in the builds, hence why we cannot utilize `/* webpackIgnore: true */`-comments in the source-code.

After the changes in PR 17563 it thus seems to me that we should be able to just move this re-writing into the Babel plugin instead.
2024-02-12 10:49:43 +01:00
Jonas Jenwald
d742daf4b7
Merge pull request #17647 from Snuffleupagus/babel-rm-empty-nodes
Remove empty, top-level, nodes in the Babel plugin
2024-02-12 09:25:59 +01:00
Calixte Denizet
de1985abbb [Editor] Set rotated free highlight at the right position after having changed its thickness (bug 1879108) 2024-02-11 21:06:56 +01:00
Tim van der Meij
ce4fe0c234
Extract and modernize the webserver's directory listing code
The `handler` method contained this code in an inline function, which
made the `handler` method big and harder to read. Moreover, this code
relied on variables from the outer scope, which made it harder to reason
about because the inputs and outputs weren't easily visible.

This commit fixes the problems by extracting the directory listing code
into a dedicated private method, and modernizing it to use e.g. `const`/
`let` instead of `var` and using template strings.
2024-02-11 20:06:21 +01:00
calixteman
5cfaff508c
Merge pull request #17651 from calixteman/add_enableStamp_pref
Revert "Remove the `enableStampEditor` preference" (bug 1879588)
2024-02-11 18:53:09 +01:00
calixteman
f15b4b34fd
Merge pull request #17650 from calixteman/editor_highlight_keyboard
[Editor] Add a way to highlight text in using the keyboard (bug 1877426)
2024-02-11 18:52:37 +01:00
calixteman
9980447d25
Merge pull request #17652 from calixteman/editor_disable_thickness
[Editor] Disable the thickness slider for non-free highlight
2024-02-11 18:32:36 +01:00
Tim van der Meij
336fcffd28
Extract and modernize the webserver's range file serving code
The `handler` method contained this code in an inline function, which
made the `handler` method big and harder to read. Moreover, this code
relied on variables from the outer scope, which made it harder to reason
about because the inputs and outputs weren't easily visible.

This commit fixes the problems by extracting the range file serving code
into a dedicated private method, and modernizing it to use e.g. `const`/
`let` instead of `var` and using template strings.
2024-02-11 17:04:38 +01:00
Tim van der Meij
56d9930a7b
Extract and modernize the webserver's file serving code
The `handler` method contained this code in an inline function, which
made the `handler` method big and harder to read. Moreover, this code
relied on variables from the outer scope, which made it harder to reason
about because the inputs and outputs weren't easily visible.

This commit fixes the problems by extracting the file serving code into
a dedicated private method, and modernizing it to use e.g. `const`/`let`
instead of `var` and using template strings.
2024-02-11 17:04:30 +01:00
Tim van der Meij
12b9685714
Convert the webserver to a proper class with private methods 2024-02-11 16:56:53 +01:00
Tim van der Meij
440208daa6
Merge pull request #17658 from Snuffleupagus/ESLint-more-rules
Enable the `no-new-symbol` and `require-yield` ESLint rules
2024-02-11 13:50:33 +01:00
Jonas Jenwald
8f67ea6dc6 Enable the no-new-symbol and require-yield ESLint rules
Given that we use both `Symbol`s and generator functions in the code-base enabling these rules cannot hurt (and there's no existing failures). Please find additional information at:
 - https://eslint.org/docs/latest/rules/no-new-symbol
 - https://eslint.org/docs/latest/rules/require-yield
2024-02-11 13:27:22 +01:00
Tim van der Meij
4b7382edcb
Merge pull request #17657 from Snuffleupagus/eslint-jasmine-no-dupes
Prevent duplicate names in unit/integration tests
2024-02-11 12:18:31 +01:00
Tim van der Meij
422e46dae9
Merge pull request #17655 from timvandermeij/updates
Update translations and dependencies to the most recent versions
2024-02-11 12:09:54 +01:00
Jonas Jenwald
5732faee1e Prevent duplicate names in unit/integration tests
Having identical names for different test-cases may result in less helpful output, which we can avoid with the use of the ESLint Jasmine plugin.
This patch enables the rules at the `branch` level, to limit the amount/scope of the changes slightly. (We could thus make this rule more strict in the future, if that's deemed useful.)

Please refer to:
 - https://github.com/tlvince/eslint-plugin-jasmine/blob/master/docs/rules/no-spec-dupes.md
 - https://github.com/tlvince/eslint-plugin-jasmine/blob/master/docs/rules/no-suite-dupes.md
2024-02-11 11:45:09 +01:00
Jonas Jenwald
485e9cecd7
Merge pull request #17646 from Snuffleupagus/app-break-import-cycles
Break import cycles, in the viewer, for `PDFViewerApplication`
2024-02-10 23:22:49 +01:00
Jonas Jenwald
e98b9b019a Break import cycles, in the viewer, for PDFViewerApplication
Currently the `web/app.js` file pulls in various build-specific dependencies, via the use of import maps, and those files in turn import from `web/app.js` thus creating undesirable import cycles.
To avoid this we instead pass in a `PDFViewerApplication`-reference, immediately after it's been created, to the relevant code.

Note that we use an ESLint plugin rule, see `import/no-cycle`, that is normally able to catch import cycles. However, in this case import maps are involved which is why this wasn't caught.
2024-02-10 23:15:57 +01:00
Tim van der Meij
28418598e5
Update puppeteer to version 22.0.0
This is a major version bump that requires two changes on our side:

- The new headless mode is now the default, so we can remove our
  transformation code (see https://github.com/puppeteer/puppeteer/pull/11815).
- The `page.waitForTimeout` API is removed. Sadly we still used it in
  the integration tests (but fortunately much less than before we worked
  on fixing intermittent failures), so until we remove the final
  occurrences we provide an implementation ourselves (see
  https://github.com/puppeteer/puppeteer/pull/11780).

The full changelog can be found here:
https://github.com/puppeteer/puppeteer/releases/tag/puppeteer-core-v22.0.0
2024-02-10 19:05:36 +01:00
Tim van der Meij
4feab0c1fa
Update gulp-postcss to version 10.0.0
This is a major version bump, but the breaking changes don't affect us;
please see https://github.com/postcss/gulp-postcss/releases/tag/10.0.0.
2024-02-10 19:05:28 +01:00
Tim van der Meij
29a665981a
Update eslint-plugin-unicorn to version 51.0.1
This is a major version bump, but the breaking changes don't affect us;
please see https://github.com/sindresorhus/eslint-plugin-unicorn/releases.
2024-02-10 19:04:54 +01:00
Tim van der Meij
913c2caf37
Update globals to version 14.0.0
This is a major version bump, but the breaking changes don't affect us;
please see https://github.com/sindresorhus/globals/releases/tag/v14.0.0.
2024-02-10 19:04:50 +01:00
Tim van der Meij
7da6f94ca3
Update dependencies to the most recent versions 2024-02-10 19:04:48 +01:00
Tim van der Meij
b278a74b6b
Update translations to the most recent versions 2024-02-10 19:04:46 +01:00
Calixte Denizet
b5e446213e [Editor] Disable the thickness slider for non-free highlight 2024-02-09 22:54:53 +01:00
Calixte Denizet
8fc6c5c8a6 [Editor] Add a way to highlight text in using the keyboard (bug 1877426) 2024-02-09 22:52:24 +01:00
Calixte Denizet
bcc95460b6 Revert "Remove the enableStampEditor preference" (bug 1879588)
This reverts commit e820688510e2c1c24088e76a178a82ef8ebcaf4d.
2024-02-09 18:21:21 +01:00
Jonas Jenwald
14ef0b4211 Remove empty, top-level, nodes in the Babel plugin
Looking at the *built* files you'll notice some lines containing nothing more than a semicolon. This is the result of (mostly top-level) `if`-statements, which include `PDFJSDev`-checks, that evalute to `false` during Babel parsing.

This has always annoyed me a bit, and looking at Babel plugin it seems that we can fix this simply by *removing* the relevant nodes.
2024-02-09 13:58:24 +01:00
calixteman
7cfcd00a38
Merge pull request #17645 from calixteman/update_quickjs_3f81070e573e3592728dbbbd04c84c498b20d6dc
Update quickjs to 3f81070e573e3592728dbbbd04c84c498b20d6dc
2024-02-09 13:56:21 +01:00
Calixte Denizet
275b6748b6 Update quickjs to 3f81070e573e3592728dbbbd04c84c498b20d6dc
According to:
3f81070e57
this is a new release of quickjs.
2024-02-09 11:51:24 +01:00
calixteman
964bfe522b
Merge pull request #17643 from calixteman/bug1879113
[Editor] Compute the position of the last point before applying rotation (bug 1879113)
2024-02-08 21:30:22 +01:00
Calixte Denizet
8d61fc1fde [Editor] Compute the position of the last point before applying rotation (bug 1879113) 2024-02-08 21:08:24 +01:00
Jonas Jenwald
0d5183a49f
Merge pull request #17634 from Snuffleupagus/rm-preprocessor-require
Remove support for `require` statements from the build system
2024-02-08 16:22:17 +01:00
calixteman
939134ee55
Merge pull request #17639 from calixteman/bug1879102
[Editor] Correctly rotate the mask when rotation a free highlight (bug 1879102)
2024-02-08 16:13:58 +01:00
Calixte Denizet
c4ac7eef95 [Editor] Correctly rotate the mask when rotation a free highlight (bug 1879102) 2024-02-08 15:29:29 +01:00
calixteman
d7479a59b7
Merge pull request #17638 from calixteman/bug1879107
[Editor] Set the right color to size samples in the highlight thickness panelwhen in HCM (bug 1879107)
2024-02-08 15:25:14 +01:00
Calixte Denizet
3f68a08ef3 [Editor] Set the right color to size samples in the highlight thickness panelwhen in HCM (bug 1879107) 2024-02-08 14:31:10 +01:00
Jonas Jenwald
6da9448f6c Remove the web-com import map (PR 17588 follow-up)
With the changes in PR 17588 we're already importing the relevant code via the `web/app.js` file.
2024-02-07 16:33:27 +01:00
Jonas Jenwald
898172e9d2 Re-factor PDFPrintServiceFactory to use import maps
This is very old code, which can (ever so slightly) be simplified now that import maps are available.
2024-02-07 16:33:25 +01:00
Jonas Jenwald
6a78cf0d93 Remove support for require statements from the build system
This part of the (modern) preprocessor is now dead code, since we no longer use `require` statements anywhere in the main code-base.

Note that as part of the changes leading up to PDF.js version `4` we removed all[1] the remaining `require` statements, and we also have an ESLint rule to ensure that no new ones are accidentally added.

---
[1] With two small exceptions, in benchmarking-code and in the Webpack-example.
2024-02-07 13:34:46 +01:00
calixteman
60fd9d583d
Merge pull request #17611 from calixteman/caret_browsing_mode
Implement caret browsing mode (bug 807730)
2024-02-07 10:16:52 +01:00
Calixte Denizet
81466ee039 Implement caret browsing mode (bug 807730)
The users will be able to navigate within the pdf in using the arrows
and they'll be able to select some text, for example in order to
highlight it.
2024-02-07 09:35:22 +01:00
Tim van der Meij
7d9cc49010
Merge pull request #17620 from Snuffleupagus/PDFDataTransportStream-signature
Simplify the signature of the `PDFDataTransportStream` constructor
2024-02-04 15:24:26 +01:00
Jonas Jenwald
06cd278808 Simplify the signature of the PDFDataTransportStream constructor
Given that we need to pass in a `PDFDataRangeTransport`-instance a number of the needed parameters can be obtained from it, rather than having to specify them manually.
2024-02-03 13:10:42 +01:00
Jonas Jenwald
247af2ee09
Merge pull request #17619 from Snuffleupagus/string-split-limit
Use a limit, in more places, when splitting strings
2024-02-02 15:04:12 +01:00
Jonas Jenwald
363dce6744 Use a limit, in more places, when splitting strings
This should be a *tiny* bit more efficient, since it avoids parsing substrings that we don't care about.

*Please note:* I cannot find an ESLint rule to enforce this automatically.
2024-02-02 13:10:52 +01:00
Jonas Jenwald
af4d2fa53c
Merge pull request #17610 from Snuffleupagus/createBundleFallback-dev-path
Point the *development mode* fallback locale-path to the `l10n`-folder (issue 17609, PR 17603 follow-up)
2024-02-01 14:22:19 +01:00
Jonas Jenwald
da8297115f Point the *development mode* fallback locale-path to the l10n-folder (issue 17609, PR 17603 follow-up) 2024-02-01 13:03:36 +01:00
calixteman
cbbd1fcaa3
Merge pull request #17608 from wojtekmaj/fix-annotation-layer-parameters
Make downloadManager optional in AnnotationLayerParameters
2024-02-01 12:06:27 +01:00
Wojciech Maj
f80ba44fb0
Make downloadManager optional in AnnotationLayerParameters
Continuation of fix started in #17038
2024-02-01 11:08:12 +01:00
calixteman
49bcce27c1
Merge pull request #17605 from calixteman/file_perm
Change file permissions for newly added cursors
2024-02-01 10:00:28 +01:00
Calixte Denizet
081be89f54 Change file permissions for newly added cursors 2024-02-01 09:56:59 +01:00
Jonas Jenwald
eb5c1d441a
Merge pull request #17604 from Snuffleupagus/externalServices-lazy-init
Initialize the `ExternalServices`-instance lazily in the viewer (PR 17588 follow-up)
2024-01-31 22:12:52 +01:00
Jonas Jenwald
f11dc611b3 Initialize the ExternalServices-instance lazily in the viewer (PR 17588 follow-up) 2024-01-31 20:22:57 +01:00
Jonas Jenwald
9588bceff5
Merge pull request #17603 from Snuffleupagus/GenericL10n-fallback
Ensure that `GenericL10n` works if the locale files cannot be loaded
2024-01-31 15:16:48 +01:00
Jonas Jenwald
97c2ce9da0 Ensure that GenericL10n works if the locale files cannot be loaded
- Ensure that localization works in the GENERIC viewer, even if the necessary locale files cannot be loaded.
   This was the behaviour prior to the introduction of Fluent, and it seems worthwhile to keep that (especially since we already bundle the en-US strings anyway).

 - Let the `GenericL10n`-implementation use the *bundled* en-US strings directly when no language is provided.

 - Remove the `NullL10n`-implementation, and simply fallback to `GenericL10n`, to reduce the maintenance burden of viewer-components localization.

 - Indirectly, given the previous point, stop exporting `NullL10n` in the viewer-components since it's now removed.
   Note that it was never really intended to be used directly and only existed as a fallback.

*Please note:* This doesn't affect the Firefox PDF Viewer, thanks to the use of import maps.
2024-01-31 14:07:11 +01:00
calixteman
833d7ac830
Merge pull request #17602 from calixteman/editor_free_highlight_lastpoint
[Editor] Fix the position of the free highlight toolbar
2024-01-30 20:34:47 +01:00
calixteman
245fd02141
Merge pull request #17586 from calixteman/editor_freehighlight_outline_inside
[Editor] Remove the outline which is inside the free highlight shape
2024-01-30 17:56:52 +01:00
calixteman
f7ed040aa6
Merge pull request #17598 from calixteman/update_highlight_cursors
[Editor] Update highlight cursors
2024-01-30 17:16:04 +01:00
Calixte Denizet
3064361099 [Editor] Update highlight cursors 2024-01-30 16:11:18 +01:00
Calixte Denizet
7529c1e3dc [Editor] Fix the position of the free highlight toolbar 2024-01-30 15:40:33 +01:00
Calixte Denizet
b88c6f9c39 [Editor] Remove the outline which is inside the free highlight shape
When an highlight is self-intersecting, the outline was drawn inside.
In order to remove it, we use a svg mask to exclude the shape inside
when drawing the outlines.
That leads to change the outline 1px,white-2px,blue-1px,white to a
2px,white-2px,blue: the part of the stroke which is inside the shape
is removed because of the mask.
2024-01-30 14:40:56 +01:00
Jonas Jenwald
56dabe9390
Merge pull request #17596 from nicolo-ribaudo/fix-babel-plugin
Fix transform of unary expression in Babel plugin
2024-01-29 12:57:42 +01:00
Nicolò Ribaudo
a352f28785
Fix transform of unary expression in Babel plugin
All of our static evaluation & dead-code elimination transforms need to
happen in post-order, transforming inner nodes first. This is so that
in complex nested cases all transforms see the simplified version of
their inner nodes.

For example:
  async getNimbusExperimentData() {
    if (!PDFJSDev.test("GECKOVIEW")) { return null; }
    // other code
  }
-> [evaluation of PDFJSDev.*]
  async getNimbusExperimentData() {
    if (!false) { return null; }
    // other code
  }
-> [!false -> true]
  async getNimbusExperimentData() {
    if (true) { return null; }
    // other code
  }
-> [if (true) -> replace with the if branch]
  async getNimbusExperimentData() {
    return null;
    // other code
  }
-> [early return -> remove dead code]
  async getNimbusExperimentData() {
    return null;
    // other code
  }

This was done correctly in all cases except for our `UnaryExpression`
transform, which was happening in pre-order.
2024-01-29 11:53:17 +01:00
Jonas Jenwald
802f702695
Merge pull request #17593 from Snuffleupagus/debuggerSrc-AppOptions
Move the `debuggerSrc`-parameter into the `AppOptions`
2024-01-28 18:54:15 +01:00
Jonas Jenwald
eb36fd375c Move the debuggerSrc-parameter into the AppOptions
Having this parameter among a list of DOM-elements seems slightly strange now, however this is very old code hence the explanation for why this was done is for historical reasons (as is often the case).
Hence we can simply move this into `AppOptions` instead, which seems more appropriate overall.
2024-01-28 18:47:51 +01:00
Tim van der Meij
2e2127cbb5
Merge pull request #17592 from Snuffleupagus/viewer-generate-fileInput
[GENERIC viewer] Generate the `fileInput` DOM-element dynamically
2024-01-28 18:11:21 +01:00
Jonas Jenwald
f394031c1d [GENERIC viewer] Generate the fileInput DOM-element dynamically
Given that only the GENERIC viewer supports opening more than one PDF document, we can simplify things a tiny bit by instead generating the necessary DOM-element in JavaScript.
2024-01-28 16:51:28 +01:00
Tim van der Meij
32a5bb83d4
Merge pull request #17591 from Snuffleupagus/issue-17399
Re-enable the `should compress and save text` unit-test (issue 17399)
2024-01-28 14:47:52 +01:00
Jonas Jenwald
384291234d Re-enable the should compress and save text unit-test (issue 17399)
This unit-test is now failing in up to date versions of Node.js respectively Chromium-browsers, since `CompressionStream` no longer produces consistent data across all environments/browsers.
However logging the compressed TypedArray produced by `writeStream`, with Firefox respectively Chrome, and then feeding *both* of those TypedArray as input to `DecompressionStream` produced the same (correct) result in both browsers.

Hence the *exact* output of `CompressionStream` shouldn't matter, as long as we're able to successfully decompress it when the resulting PDF document is opened with the PDF.js library, and the unit-test is thus extended to check this.
2024-01-28 14:31:07 +01:00
Tim van der Meij
ab392584f3
Merge pull request #17590 from timvandermeij/updates
Update dependencies/translations to the most recent versions
2024-01-28 12:10:20 +01:00
Tim van der Meij
94309edc9a
Disable the "should compress and save text" unit test in Chrome too
Starting with Chrome 120.0.6099.109 (shipped with Puppeteer 21.8.0+) the
unit test fails in Chrome as well. The issue is tracked in #17399, but
for now we'll only run the unit test in Firefox so we can continue to
update Puppeteer while also still having a browser in which it runs,
until we figure out why the behavior of `CompressionStream` changed.
2024-01-27 20:34:30 +01:00
Tim van der Meij
f103f277ac
Update translations to the most recent versions 2024-01-27 19:13:06 +01:00
Tim van der Meij
f855a6dae8
Update dependencies to the most recent versions 2024-01-27 19:12:59 +01:00
Tim van der Meij
a6e0b0292e
Merge pull request #17588 from Snuffleupagus/DefaultExternalServices-lighten
Re-factor `DefaultExternalServices` into a regular class, without static methods
2024-01-27 14:13:49 +01:00
Jonas Jenwald
c6594b73a7 Stub out the getNimbusExperimentData method in "regular" MOZCENTRAL builds 2024-01-27 13:12:54 +01:00
Jonas Jenwald
5dd25b6e80 Re-factor DefaultExternalServices into a regular class, without static methods
The `DefaultExternalServices` code, which is used to provide build-specific functionality, is very old. This results in a pattern where we first initialize `PDFViewerApplication.externalServices` and then *override* it for the different builds.

By converting `DefaultExternalServices` into a "regular" class, and leveraging import maps, we can directly initialize the correct instance depending on the build.
2024-01-27 12:07:15 +01:00
Jonas Jenwald
d1080e785a Remove the createPreferences method from DefaultExternalServices
Given the simplicity of the `createPreferences` method, we can leverage import maps to directly initialize the correct `Preferences`-instance depending on the build.
2024-01-27 11:38:42 +01:00
Jonas Jenwald
1698991ae2 Remove the createDownloadManager method from DefaultExternalServices
Given the simplicity of the `createDownloadManager` method, we can leverage import maps to directly initialize the correct `DownloadManager`-instance depending on the build.
2024-01-27 11:38:36 +01:00
calixteman
d8f77e6b84
Merge pull request #17582 from calixteman/editor_highlight_thickness_tooltip
[Editor] Add a tooltip to the slider to set the thickness of free highlights
2024-01-26 19:20:08 +01:00
calixteman
e63fafd0fb
Merge pull request #17581 from calixteman/editor_highlight_cursor
[Editor] Change the cursors for highlighting (bug 1876588)
2024-01-26 18:52:29 +01:00
Jonas Jenwald
3192d37aa7
Merge pull request #17587 from Snuffleupagus/fix-FontInspector-textLayer-opacity
Fix the textLayer-opacity when using the FontInspector (PR 17533 follow-up)
2024-01-26 18:37:50 +01:00
Calixte Denizet
0432d1e8e6 [Editor] Add a tooltip to the slider to set the thickness of free highlights 2024-01-26 18:34:26 +01:00
Jonas Jenwald
fed3ef1743 Fix the textLayer-opacity when using the FontInspector (PR 17533 follow-up) 2024-01-26 18:31:38 +01:00
Calixte Denizet
f3bdbedf9b [Editor] Change the cursors for highlighting (bug 1876588) 2024-01-26 18:17:05 +01:00
calixteman
4ec43488ff
Merge pull request #17580 from calixteman/freetext_icon
[Editor] Change the icon to add a FreeText annotation (bug 1876564)
2024-01-25 18:20:20 +01:00
Calixte Denizet
01280d8e08 [Editor] Change the icon to add a FreeText annotation (bug 1876564) 2024-01-25 17:18:28 +01:00
calixteman
bf92360095
Merge pull request #17574 from calixteman/improve_bezier_bbox
Reduce memory use and improve perfs when computing the bounding box of a bezier curve (bug 1875547)
2024-01-25 10:07:48 +01:00
calixteman
2f4017e22b
Merge pull request #17578 from Snuffleupagus/css-vars-unreferenced
Fix unreferenced CSS variables (PR 17533 follow-up)
2024-01-25 10:04:37 +01:00
Jonas Jenwald
1cbcb89dac Fix unreferenced CSS variables (PR 17533 follow-up)
The latest mozilla-central update has test failures, because some CSS variables are not "properly" referenced; in particular:
 - Give `--hcm-highlight-selected-filter` a default value, of `none`, similar to the previously existing HCM filter.
 - Remove the `--mix-blend-mode` variable, since it's unused.
2024-01-25 09:43:20 +01:00
Calixte Denizet
7f2428a77e Reduce memory use and improve perfs when computing the bounding box of a bezier curve (bug 1875547)
It isn't really a fix for the mentioned bug but it slightly improve things.
In reducing the memory use, the time spent in the GC is reduced either.
The algorithm to compute the bounding box is the same as before but it has just
been rewritten to be more efficient.
2024-01-24 23:41:14 +01:00
calixteman
a5d4660a75
Merge pull request #17568 from calixteman/editor_free_highlight_thickness
[Editor] Add the possibility to change the thickness of a free highlight (bug 1876096)
2024-01-24 22:37:40 +01:00
Calixte Denizet
2b8ecf5688 [Editor] Add the possibility to change the thickness of a free highlight (bug 1876096) 2024-01-24 22:04:39 +01:00
calixteman
f81f9bb7d3
Merge pull request #17564 from calixteman/editor_update_ui_undo
[Editor] Update the parameters in the UI of the last selected editor when undoing/redoing
2024-01-24 21:52:54 +01:00
Calixte Denizet
d713df28c3 [Editor] Update the parameters in the UI of the last selected editor when undoing/redoing 2024-01-24 18:16:51 +01:00
Jonas Jenwald
ae62787080
Merge pull request #17563 from nicolo-ribaudo/build-step-remove-custom-webpack
Replace the webpack+acorn transform with a Babel plugin
2024-01-23 19:00:28 +01:00
Nicolò Ribaudo
f724ae98a1
Replace the webpack+acorn transform with a Babel plugin
This commit converts the pdfjsdev-loader transform into a Babel plugin,
to skip a AST->string->AST round-trip.

Before this commit, the webpack build process was:
1. Babel parses the code
2. Babel transforms the AST
3. Babel generates the code
4. Acorn parses the code
5. pdfjsdev-loader transforms the AST
6. @javascript-obfuscator/escodegen generates the code
7. Webpack parses the file
8. Webpack concatenates the files

After this commit, it is reduced to:
1. Babel parses the code
2. Babel transforms the AST
3. babel-plugin-pdfjs-preprocessor transforms the AST
4. Babel generates the code
5. Webpack parses the file
6. Webpack concatenates the files

This change improves the build time by ~25% (tested on MacBook Air M2):
- `gulp lib`: 3.4s to 2.6s
- `gulp dist`: 36s to 29s
- `gulp generic`: 5.5s to 4.0s
- `gulp mozcentral`: 4.7s to 3.2s

The new Babel plugin doesn't support the `saveComments` option of
pdfjsdev-loader, and it just always discards comments. Even though
pdfjsdev-loader supported multiple values for that option, it was
effectively ignored due to `acorn` dropping comments by default.
2024-01-23 16:00:59 +01:00
Nicolò Ribaudo
f5bb9bc21b
Rename preprocessor2.mjs to babel-plugin-pdfjs-preprocessor.mjs
This is in preparation for the next commit, which will convert
preprocessor2.mjs to a Babel plugin. The purpose of this commit
is to help git track the rename regardless of the large amount
of changes.
2024-01-23 13:13:43 +01:00
Jonas Jenwald
8b24722113
Merge pull request #17562 from Snuffleupagus/evaluator-more-async
Add more `async` code in the `PartialEvaluator`
2024-01-23 10:35:27 +01:00
Jonas Jenwald
fa583427ef Always export the "raw" /ToUnicode-data from PartialEvaluator.preEvaluateFont (PR 13354 follow-up)
This, ever so slightly, simplifies the implementation in the `PartialEvaluator.extractDataStructures`-method.
2024-01-22 13:06:32 +01:00
Jonas Jenwald
f21a30dfb4 Convert the PartialEvaluator.readToUnicode method to be async 2024-01-22 12:47:06 +01:00
Jonas Jenwald
f5c01188dc Convert the PartialEvaluator.extractDataStructures method to be async 2024-01-22 12:47:06 +01:00
Jonas Jenwald
cf0797dfbd Use await consistently in the PartialEvaluator.setGState method 2024-01-22 12:47:06 +01:00
Jonas Jenwald
1cc83c4fdc Use await consistently in the PartialEvaluator.buildFormXObject method 2024-01-22 12:47:06 +01:00
calixteman
bba831821d
Merge pull request #17558 from calixteman/bug1669097
Print correctly documents containing chars with an unicode greater than 0xFFFF (bug 1669097)
2024-01-22 12:23:06 +01:00
Calixte Denizet
06601fd90c Print correctly documents containing chars with an unicode greater than 0xFFFF (bug 1669097) 2024-01-22 10:48:00 +01:00
Tim van der Meij
49b2d9b5af
Merge pull request #17556 from Snuffleupagus/issue-17554
Ensure that `EvaluatorPreprocessor.opMap` has a null-prototype (issue 17554)
2024-01-21 20:58:09 +01:00
Tim van der Meij
1ed68933e5
Merge pull request #17555 from timvandermeij/gulpfile-exit-code
Don't ignore `test.mjs` child process exit codes in the Gulpfile
2024-01-21 20:34:22 +01:00
Tim van der Meij
d549c2ef4c
Merge pull request #17553 from Snuffleupagus/async-handleSetFont
Add more `async` code when loading fonts in the `PartialEvaluator`
2024-01-21 20:00:29 +01:00
Jonas Jenwald
d7e41d4cb6 Ensure that EvaluatorPreprocessor.opMap has a null-prototype (issue 17554)
This accidentally regressed in PR 16956, sorry about that!
2024-01-21 19:59:13 +01:00
Tim van der Meij
6dd77b3c14
Don't ignore test.mjs child process exit codes in the Gulpfile
In the Gulpfile only the exit codes of `test.mjs` child processes
erroneously aren't checked. This causes failures in `test.mjs` to be
logged but not propagated to the master process, which in turn causes
test runners such as GitHub Actions to succeed because they only
monitor the master process. This is easy to reproduce by throwing an
error at the top of `test.mjs` and running `gulp makeref` or `gulp
unittest`: the error is logged, but the task that spawned the child
process succeeds and the master process exits with exit code 0. This is
problematic because it can easily cause errors to go by unnoticed.

This commit fixes the issue by making sure that the `test.mjs`
invocations are handled in the same way as the other child processes
in the file, i.e., if the child process exits with a non-zero exit code
then the master process also exits with a non-zero exit code. After this
patch the error is still logged, but the task now also fails and the
master process exits with exit code 1 to properly signal failure.
2024-01-21 19:37:13 +01:00
Jonas Jenwald
3c2c0ecd88 Use the ESLint arrow-body-style rule in more spots in src/core/evaluator.js 2024-01-21 17:42:33 +01:00
Jonas Jenwald
d1bef8cb86 Use await consistently in the PartialEvaluator.translateFont method 2024-01-21 17:36:50 +01:00
Jonas Jenwald
fc62eec901 Convert the handleSetFont methods, in src/core/evaluator.js, to be async 2024-01-21 17:32:05 +01:00
Jonas Jenwald
fce822cde0
Merge pull request #17550 from Snuffleupagus/arrow-fn-shorter
Use shorter arrow functions where possible
2024-01-21 17:21:32 +01:00
calixteman
10eef372ff
Merge pull request #17548 from calixteman/eslint_jasmine
Avoid to have focused tests in using eslint-plugin-jasmine
2024-01-21 16:36:41 +01:00
Jonas Jenwald
f9a384d711 Enable the arrow-body-style ESLint rule
This manually ignores some cases where the resulting auto-formatting would not, as far as I'm concerned, constitute a readability improvement or where we'd just end up with more overall indentation.

Please see https://eslint.org/docs/latest/rules/arrow-body-style
2024-01-21 16:20:55 +01:00
Jonas Jenwald
998184a00e Remove the no-confusing-arrow ESLint rule since it's deprecated
Please see https://eslint.org/docs/latest/rules/no-confusing-arrow
2024-01-21 15:45:28 +01:00
Jonas Jenwald
9dfe9c552c Use shorter arrow functions where possible
For arrow functions that are both simple and short, we can avoid using explicit `return` to shorten them even further without hurting readability.

For the `gulp mozcentral` build-target this reduces the overall size of the output by just under 1 kilo-byte (which isn't a lot but still can't hurt).
2024-01-21 10:13:12 +01:00
calixteman
6e46304357
Merge pull request #17539 from calixteman/color_picker_kb
[Editor] Don't add the keyboard listener on the color-picker each time the dropdown menu is shown
2024-01-20 22:24:37 +01:00
Calixte Denizet
99ee308f3d Avoid to have focused tests in using eslint-plugin-jasmine 2024-01-20 22:10:42 +01:00
Calixte Denizet
0cca9a0240 [Editor] Don't add the keyboard listener on the color-picker each time the dropdown menu is shown
and display/hide the dropdown menu when pressing arrow keys.
2024-01-20 21:57:54 +01:00
calixteman
f24246150e
Merge pull request #17541 from calixteman/issue17540
Use the original value of a field when propagating event (fixes #17540)
2024-01-20 21:51:37 +01:00
calixteman
03aa8a12d2
Merge pull request #17543 from calixteman/bug1869767
[Editor] Unselect highlights when the user click on the text layer (bug 1869767)
2024-01-20 21:50:19 +01:00
Tim van der Meij
626674553d
Merge pull request #17547 from timvandermeij/remove-dns-resolver-workaround
Remove DNS resolver workaround from the test framework
2024-01-20 20:23:37 +01:00
Tim van der Meij
c70edbced7
Remove DNS resolver workaround from the test framework
The `if` statement is no longer necessary because the Node.js versions
that didn't provide `dns.setDefaultResultOrder` are no longer supported,
but looking into this a bit more it turns out that the entire workaround
is no longer necessary because the issue got fixed in Firefox 105 in bug
1769994. Indeed, Firefox now starts nicely with the workaround removed.

Reverts 60ed3cd297c4045b90f4114a74e5baa4ef1c5056.
2024-01-20 20:05:08 +01:00
Tim van der Meij
c9b1a8f761
Merge pull request #17546 from Snuffleupagus/git-blame-ignore
Ignore auto-formatting patches in `git blame`
2024-01-20 14:04:55 +01:00
Tim van der Meij
9b0b099713
Merge pull request #17544 from Snuffleupagus/update-packages
Update packages and translations
2024-01-20 14:03:52 +01:00
Jonas Jenwald
c9755bdbc8 Ignore auto-formatting patches in git blame
When using Prettier to auto-format (parts of) the code-base you usually end up with *huge* patches that touch lots of lines without making any actual changes.
This often adds unnecessary steps when using `git blame`, however it's easy enough to avoid this; please refer to https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignore-commits-in-the-blame-view
2024-01-20 12:01:23 +01:00
Jonas Jenwald
2dd6910aa4 Update l10n files 2024-01-20 09:54:21 +01:00
Jonas Jenwald
a5a9357e15 Update npm packages 2024-01-20 09:52:57 +01:00
Calixte Denizet
5732c0c54a Use the original value of a field when propagating event (fixes #17540)
And avoid to not format a field when the value is 0.
2024-01-19 22:13:51 +01:00
Calixte Denizet
f3b76f5ae2 [Editor] Unselect highlights when the user click on the text layer (bug 1869767) 2024-01-19 20:16:55 +01:00
Jonas Jenwald
f8e3c79cb5
Merge pull request #17537 from Snuffleupagus/rm-isArrayBuffer
Remove the `isArrayBuffer` helper function
2024-01-19 15:37:02 +01:00
calixteman
f6c4b29aa2
Merge pull request #17531 from calixteman/editor_free_highlight_print_save
[Editor] Add support for printing/saving free highlight annotations
2024-01-19 15:23:29 +01:00
calixteman
5d2e7cf3fc
Merge pull request #17533 from calixteman/caret_mode
Make the caret visible in the text layer in caret browsing mode
2024-01-19 15:22:08 +01:00
Jonas Jenwald
b37536c38c Remove the isArrayBuffer helper function
This old helper function can now be replaced with `ArrayBuffer.isView()` and/or `instanceof ArrayBuffer` checks, as needed depending on the situation.
2024-01-19 14:10:52 +01:00
calixteman
a0e2b62245
Merge pull request #17534 from calixteman/bug1875357
[Editor] Change the arrow direction when the dropdown is visible in the color picker (bug 1875357)
2024-01-19 13:08:12 +01:00
Calixte Denizet
a1bf12537c [Editor] Change the arrow direction when the dropdown is visible in the color picker (bug 1875357)
and hide the dropdown when the user click outside of the color picker.
2024-01-19 13:02:11 +01:00
Calixte Denizet
d64f334f98 [Editor] Add support for printing/saving free highlight annotations 2024-01-19 12:58:46 +01:00
Calixte Denizet
83c78dbfa8 Make the caret visible in the text layer in caret browsing mode
In order to do that we must change the text layer opacity to 1 but
it has several implications:
 - the selection color must have an alpha component,
 - the background color of the span used for highlighted words
   must have an alpha component either, but now the opacity is 1
   we can use some backdrop-filters in HCM making the highlighted
   words more visible.
 - fix a regression caused by #17196: the css variable --hcm-highlight-filter
   has to live under the #viewer element because in HCM it's overwritten
   by js at this level, hence links annotations for example didn't
   have the right colors when hovered.
2024-01-18 19:44:21 +01:00
calixteman
1cdbcfef82
Merge pull request #17506 from calixteman/editor_free_highlight
[Editor] Add the ability to make a free highlight (i.e. without having to select some text) (bug 1856218)
2024-01-18 17:47:27 +01:00
Calixte Denizet
8fbfef0c07 [Editor] Add the ability to make a free highlight (i.e. without having to select some text) (bug 1856218)
The free highlighting is enabled when the mouse pointer isn't on some text.
Then we draw a shape with smoothed borders corresponding to the movement of
the mouse.
Printing/saving and changing the thickness will come later.
2024-01-18 16:26:04 +01:00
calixteman
a22b5a4f02
Merge pull request #17528 from calixteman/highlight_not_draggable
[Editor] Avoid to move a non-draggable editor with the keyboard
2024-01-16 22:27:14 +01:00
Jonas Jenwald
cb38882d74
Merge pull request #17529 from Snuffleupagus/skip-web-locale
Exclude the `web/locale/` folder from linting (PR 17525 follow-up)
2024-01-16 22:22:49 +01:00
Calixte Denizet
70a9d8f3bc [Editor] Avoid to move a non-draggable editor with the keyboard 2024-01-16 21:41:52 +01:00
calixteman
9c377922ef
Merge pull request #17527 from calixteman/color_pick_exception
[Editor] Avoid an exception when pressing space key to change the color of an highlight
2024-01-16 21:13:56 +01:00
Jonas Jenwald
79594ff876 Exclude the web/locale/ folder from linting (PR 17525 follow-up)
Given that the contents of this folder is generated by `gulp locale` it's essentially build-output and thus shouldn't be included in linting.
2024-01-16 20:25:01 +01:00
calixteman
bf6cc83e7a
Merge pull request #17525 from calixteman/prettier_json
Format json files in using prettier
2024-01-16 20:16:56 +01:00
Calixte Denizet
a76cc40ab8 [Editor] Avoid an exception when pressing space key to change the color of an highlight 2024-01-16 20:00:23 +01:00
Calixte Denizet
29de9bdce6 Format json files in using prettier 2024-01-16 19:40:25 +01:00
calixteman
e7d782e887
Merge pull request #17405 from calixteman/libertine
Add the font Linux Libertine as a possible substitution for Times New Roman
2024-01-16 14:32:30 +01:00
Calixte Denizet
10389c5017 Add the font Linux Libertine as a possible substitution for Times New Roman
and try to load the font family (guessed from the font name) before trying
the local substitution.
The local(...) command expects to have a real font name and not a predefined
substitution it's why we try the font family.
2024-01-16 12:31:23 +01:00
calixteman
51413be5b6
Merge pull request #17519 from calixteman/editor_movable_touchscreen
[Editor] Make editors draggable with touchscreens
2024-01-16 10:47:38 +01:00
Calixte Denizet
b8aab5d14e [Editor] Make editors draggable with touchscreens 2024-01-15 23:20:55 +01:00
calixteman
3110865484
Merge pull request #17517 from calixteman/editor_highlight_simplify_ser
[Editor] Slightly simplify the serialization of an highlight annotation
2024-01-15 18:50:37 +01:00
Calixte Denizet
ee72b32dc2 [Editor] Slightly simplify the serialization of an highlight annotation
We were computing width and height of the annotation before serializing
which is useless because the rect already contains this information.
2024-01-15 18:22:01 +01:00
calixteman
7769018316
Merge pull request #17514 from calixteman/issue17418
[Editor] Draw a line instead of a Bezier curve when an Ink has only one point
2024-01-15 14:23:04 +01:00
Calixte Denizet
e9946fa22a [Editor] Draw a line instead of a Bezier curve when an Ink has only one point
Fixes #17418.
2024-01-15 13:32:36 +01:00
calixteman
2ca20dea43
Merge pull request #17512 from calixteman/issue17492
Take into account empty lines when extracting text content from the appearance
2024-01-15 12:44:14 +01:00
calixteman
e98a813e09
Merge pull request #17511 from calixteman/issue17079
[Editor] Extract all the lines when adding a FreeText annotation
2024-01-15 10:40:49 +01:00
calixteman
d3b5f60995
Merge pull request #17513 from calixteman/update_l10n
Update l10n files
2024-01-15 10:18:46 +01:00
Calixte Denizet
7580770aac Update l10n files 2024-01-14 21:18:58 +01:00
Calixte Denizet
9765d57a26 [Editor] Extract all the lines when adding a FreeText annotation
Fixes #17079.
2024-01-14 21:11:51 +01:00
Calixte Denizet
405f573d70 Take into account empty lines when extracting text content from the appearance
Fixes #17492.
2024-01-14 20:23:29 +01:00
Tim van der Meij
dc92ab850a
Merge pull request #17508 from Snuffleupagus/pr-14388-followup
Consistently remove the "visibilitychange" listener in `PDFViewer` (PR 14388 follow-up)
2024-01-14 16:21:29 +01:00
Tim van der Meij
704747b143
Merge pull request #17489 from nicolo-ribaudo/gulp-cli-dep
Update `gulp-cli` to 2.3.0 and explicitly add it as a dependency
2024-01-14 16:18:26 +01:00
Tim van der Meij
07cb42243c
Merge pull request #17507 from Snuffleupagus/version-4.1
Bump library version to `4.1`
2024-01-14 16:09:18 +01:00
Tim van der Meij
ff93dfc560
Merge pull request #17490 from nicolo-ribaudo/macos-m2-note
Add note about running `npm install` on MacOS
2024-01-14 16:04:54 +01:00
Jonas Jenwald
b168f71fde Consistently remove the "visibilitychange" listener in PDFViewer (PR 14388 follow-up)
By always removing the "visibilitychange" listener in the `PDFViewer.#onePageRenderedOrForceFetch`-method we can (ever so slightly) reduce duplication in the code.
2024-01-13 10:51:26 +01:00
Jonas Jenwald
6dc225bdbb Bump library version to 4.1 2024-01-13 09:28:56 +01:00
Jonas Jenwald
56ca2fd658
Merge pull request #17504 from Snuffleupagus/GlobalWorkerOptions-validate
[api-minor] Validate the `workerPort`/`workerSrc` options
2024-01-13 09:23:29 +01:00
Jonas Jenwald
f0af52032b [api-minor] Validate the workerPort/workerSrc options
Ensure that users cannot provide incorrect values when trying to set the global worker-options.
This patch was prompted by occasionally seeing users manually loading the `pdf.worker.mjs`-file and then assigning it to the `workerSrc`-option, something that obviously doesn't make sense and will cause fake-workers to be used (with poor performance as a result).
2024-01-12 17:13:32 +01:00
calixteman
0d011472a4
Merge pull request #17501 from calixteman/editor_highlight_serialization
[Editor] Correctly serialize highlight data (regression from #17499)
2024-01-12 16:42:59 +01:00
Calixte Denizet
fc7c320bd8 [Editor] Correctly serialize highlight data (regression from #17499) 2024-01-12 15:37:01 +01:00
calixteman
61e5dae7fd
Merge pull request #17499 from calixteman/editor_outliner
[Editor] Move the code to generate the SVG path from draw_layer.js to outliner.js
2024-01-12 13:59:26 +01:00
Calixte Denizet
94ad3afab6 [Editor] Move the code to generate the SVG path from draw_layer.js to outliner.js
It'll be useful to avoid too much duplicated code when adding the free highlighting tool.
2024-01-11 19:10:33 +01:00
calixteman
35daccf34b
Merge pull request #17498 from calixteman/editor_dont_throw_highlight_color
[Editor] Don't throw when changing the color of an invisible highlight
2024-01-11 18:34:01 +01:00
Calixte Denizet
b4a7007397 [Editor] Don't throw when changing the color of an invisible highlight 2024-01-11 17:48:06 +01:00
Jonas Jenwald
12875359c3
Merge pull request #17494 from mozilla/dependabot/npm_and_yarn/follow-redirects-1.15.4
Bump follow-redirects from 1.15.3 to 1.15.4
2024-01-11 09:59:21 +01:00
dependabot[bot]
7d15d23147
Bump follow-redirects from 1.15.3 to 1.15.4
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.3 to 1.15.4.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.3...v1.15.4)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-11 04:54:43 +00:00
Nicolò Ribaudo
4197f6a284
Add note about running npm install on MacOS 2024-01-10 15:21:15 +01:00
Nicolò Ribaudo
d2a5210475
Update gulp-cli to 2.3.0 and explicitly add it as a dependency 2024-01-10 14:59:32 +01:00
calixteman
903af4ee00
Merge pull request #17487 from calixteman/fix_final_spaces
Remove terminal white spaces when extracting text from annotation appearances
2024-01-10 10:03:52 +01:00
Calixte Denizet
0392feaee4 Remove terminal white spaces when extracting text from annotation appearances 2024-01-09 10:42:53 +01:00
Tim van der Meij
29faa38dd7
Merge pull request #17482 from Snuffleupagus/update-packages
Update packages and translations
2024-01-06 14:16:56 +01:00
Jonas Jenwald
2cb93cc344 Update l10n files 2024-01-06 10:10:22 +01:00
Jonas Jenwald
c5a69544af Update npm packages 2024-01-06 10:09:12 +01:00
calixteman
6c5e237a40
Merge pull request #17481 from calixteman/editor_default_init
[Editor] Init the default highlight color before creating the first editor instance
2024-01-05 22:00:08 +01:00
Calixte Denizet
17e1519410 [Editor] Init the default highlight color before creating the first editor instance
We want to be able to draw an highlight with the default color but without having an
instance of the HighlightEditor.
2024-01-05 17:52:54 +01:00
calixteman
130a0fef3d
Merge pull request #17458 from calixteman/bug1871353
Preserve the whitespaces when getting text from FreeText annotations (bug 1871353)
2024-01-05 14:21:27 +01:00
Calixte Denizet
7839e7b495 Preserve the whitespaces when getting text from FreeText annotations (bug 1871353)
When the text of an annotation is extracted in using getTextContent, consecutive white spaces
are just replaced by one space and. So this patch add an option to make sure that white
spaces are preserved when appearance is parsed.
For the case where there's no appearance, we can have a fast path to get the correct string
from the Content entry.
When an existing FreeText is edited, space (0x20) are replaced by non-breakable (0xa0) ones
to make to see all of them on screen.
2024-01-05 10:20:32 +01:00
calixteman
1019b9f821
Merge pull request #17476 from calixteman/bug1869001
Avoid to have the text layer mismatching the rendered text with mismatching locales (bug 1869001)
2024-01-04 22:03:35 +01:00
Calixte Denizet
f84f48b5d0 Avoid to have the text layer mismatching the rendered text with mismatching locales (bug 1869001)
The system locale (used in OffscreenCanvas) can be different from the one guessed by Fluent,
consequently, in order to avoid any mismatch, we just use an attached canvas element.
The original issue can easily be reproduced locally in adding a lang="ja" in viewer.html
(or with an other language for Japanese users).
2024-01-04 19:20:20 +01:00
calixteman
7873ad98bb
Merge pull request #17477 from calixteman/puppeteer21.7.0
Update Puppeteer to version 21.7.0
2024-01-04 19:00:30 +01:00
Calixte Denizet
e5ccb70efb Update Puppeteer to version 21.7.0 2024-01-04 16:11:09 +01:00
calixteman
dc01782633
Merge pull request #17475 from calixteman/bug1872721
[Editor] Take into account the crop box when saving/printing some highlighted text (bug 1872721)
2024-01-03 13:43:31 +01:00
Calixte Denizet
35863cd54b [Editor] Take into account the crop box when saving/printing some highlighted text (bug 1872721) 2024-01-02 18:53:33 +01:00
Tim van der Meij
231c79800b
Merge pull request #17474 from timvandermeij/bump
Bump the stable version in `pdfjs.config`
2023-12-31 15:34:28 +01:00
Tim van der Meij
fea192fbf9
Bump the stable version in pdfjs.config 2023-12-31 15:31:03 +01:00
233 changed files with 19840 additions and 12964 deletions

View File

@ -8,4 +8,5 @@ external/builder/fixtures_esprima/
external/quickjs/ external/quickjs/
test/tmp/ test/tmp/
test/pdfs/ test/pdfs/
web/locale/
*~/ *~/

View File

@ -142,9 +142,10 @@
"no-lone-blocks": "error", "no-lone-blocks": "error",
"no-lonely-if": "error", "no-lonely-if": "error",
"no-multi-str": "error", "no-multi-str": "error",
"no-new-func": "error",
"no-new-wrappers": "error",
"no-new": "error", "no-new": "error",
"no-new-func": "error",
"no-new-symbol": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error", "no-octal-escape": "error",
"no-octal": "error", "no-octal": "error",
"no-redeclare": "error", "no-redeclare": "error",
@ -242,9 +243,9 @@
}], }],
// ECMAScript 6 // ECMAScript 6
"arrow-body-style": ["error", "as-needed"],
"constructor-super": "error", "constructor-super": "error",
"no-class-assign": "error", "no-class-assign": "error",
"no-confusing-arrow": "error",
"no-const-assign": "error", "no-const-assign": "error",
"no-dupe-class-members": "error", "no-dupe-class-members": "error",
"no-duplicate-imports": "error", "no-duplicate-imports": "error",
@ -257,6 +258,7 @@
"avoidQuotes": true, "avoidQuotes": true,
}], }],
"prefer-const": "error", "prefer-const": "error",
"require-yield": "error",
"sort-imports": ["error", { "sort-imports": ["error", {
"ignoreCase": true, "ignoreCase": true,
}], }],

6
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,6 @@
# Auto-format `.js` files with ESLint/Prettier
de36b2aabab2b7fd647d9591f959c4540129541d
# Auto-format `.css` files with Stylelint/Prettier
8aa2718d225ad701a5b8a2788b42d221f1e4327d
# Auto-format `.json` files with Prettier
29de9bdce6c9785574994fda0e51533d796a9bb4

12
.prettierignore Normal file
View File

@ -0,0 +1,12 @@
build/
l10n/
docs/
node_modules/
external/bcmaps/
external/builder/fixtures/
external/builder/fixtures_esprima/
external/quickjs/
test/tmp/
test/pdfs/
web/locale/
*~/

View File

@ -5,5 +5,14 @@
"semi": true, "semi": true,
"tabWidth": 2, "tabWidth": 2,
"trailingComma": "es5", "trailingComma": "es5",
"useTabs": false "useTabs": false,
"overrides": [
{
files: ["tsconfig.json"],
options: {
parser: "json",
},
},
]
} }

View File

@ -8,4 +8,5 @@ external/builder/fixtures_esprima/
external/quickjs/ external/quickjs/
test/tmp/ test/tmp/
test/pdfs/ test/pdfs/
web/locale/
*~/ *~/

View File

@ -55,12 +55,17 @@ Next, install Node.js via the [official package](https://nodejs.org) or via
[nvm](https://github.com/creationix/nvm). You need to install the gulp package [nvm](https://github.com/creationix/nvm). You need to install the gulp package
globally (see also [gulp's getting started](https://github.com/gulpjs/gulp/tree/master/docs/getting-started)): globally (see also [gulp's getting started](https://github.com/gulpjs/gulp/tree/master/docs/getting-started)):
$ npm install -g gulp-cli $ npm install -g gulp-cli@^2.3.0
If you prefer to not install `gulp-cli` globally, you have to prefix all the `gulp` commands with `npx` (for example, `npx gulp server` instead of `gulp server`).
If everything worked out, install all dependencies for PDF.js: If everything worked out, install all dependencies for PDF.js:
$ npm install $ npm install
> [!NOTE]
> On MacOS M1/M2 you may see some `node-gyp`-related errors when running `npm install`. This is because one of our dependencies, `"canvas"`, does not provide pre-built binaries for this platform and instead `npm` will try to build it from source. Please make sure to first install the necessary native dependencies using `brew`: https://github.com/Automattic/node-canvas#compiling.
Finally, you need to start a local web server as some browsers do not allow opening Finally, you need to start a local web server as some browsers do not allow opening
PDF files using a `file://` URL. Run: PDF files using a `file://` URL. Run:

View File

@ -272,7 +272,7 @@ const PDFViewerApplication = {
}); });
this.pdfLinkService = linkService; this.pdfLinkService = linkService;
this.l10n = pdfjsViewer.NullL10n; this.l10n = new pdfjsViewer.GenericL10n();
const container = document.getElementById("viewerContainer"); const container = document.getElementById("viewerContainer");
const pdfViewer = new pdfjsViewer.PDFViewer({ const pdfViewer = new pdfjsViewer.PDFViewer({

View File

@ -47,7 +47,7 @@ limitations under the License.
} }
var scheme = url.slice(0, schemeIndex).toLowerCase(); var scheme = url.slice(0, schemeIndex).toLowerCase();
if (schemes.includes(scheme)) { if (schemes.includes(scheme)) {
url = url.split("#")[0]; url = url.split("#", 1)[0];
if (url.charAt(schemeIndex) === ":") { if (url.charAt(schemeIndex) === ":") {
url = encodeURIComponent(url); url = encodeURIComponent(url);
} }

View File

@ -11,32 +11,30 @@
}, },
"permissions": [ "permissions": [
"fileBrowserHandler", "fileBrowserHandler",
"webRequest", "webRequestBlocking", "webRequest",
"webRequestBlocking",
"<all_urls>", "<all_urls>",
"tabs", "tabs",
"webNavigation", "webNavigation",
"storage" "storage"
], ],
"content_scripts": [{ "content_scripts": [
"matches": [ {
"http://*/*", "matches": ["http://*/*", "https://*/*", "ftp://*/*", "file://*/*"],
"https://*/*", "run_at": "document_start",
"ftp://*/*", "all_frames": true,
"file://*/*" "css": ["contentstyle.css"],
], "js": ["contentscript.js"]
"run_at": "document_start", }
"all_frames": true, ],
"css": ["contentstyle.css"],
"js": ["contentscript.js"]
}],
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"file_browser_handlers": [{ "file_browser_handlers": [
"id": "open-as-pdf", {
"default_title": "Open with PDF Viewer", "id": "open-as-pdf",
"file_filters": [ "default_title": "Open with PDF Viewer",
"filesystem:*.pdf" "file_filters": ["filesystem:*.pdf"]
] }
}], ],
"storage": { "storage": {
"managed_schema": "preferences_schema.json" "managed_schema": "preferences_schema.json"
}, },

View File

@ -5,11 +5,7 @@
"title": "Theme", "title": "Theme",
"description": "The theme to use.\n0 = Use system theme.\n1 = Light theme.\n2 = Dark theme.", "description": "The theme to use.\n0 = Use system theme.\n1 = Light theme.\n2 = Dark theme.",
"type": "integer", "type": "integer",
"enum": [ "enum": [0, 1, 2],
0,
1,
2
],
"default": 2 "default": 2
}, },
"showPreviousViewOnLoad": { "showPreviousViewOnLoad": {
@ -21,11 +17,7 @@
"title": "View position on load", "title": "View position on load",
"description": "The position in the document upon load.\n -1 = Default (uses OpenAction if available, otherwise equal to `viewOnLoad = 0`).\n 0 = The last viewed page/position.\n 1 = The initial page/position.", "description": "The position in the document upon load.\n -1 = Default (uses OpenAction if available, otherwise equal to `viewOnLoad = 0`).\n 0 = The last viewed page/position.\n 1 = The initial page/position.",
"type": "integer", "type": "integer",
"enum": [ "enum": [-1, 0, 1],
-1,
0,
1
],
"default": 0 "default": 0
}, },
"defaultZoomDelay": { "defaultZoomDelay": {
@ -45,13 +37,7 @@
"title": "Sidebar state on load", "title": "Sidebar state on load",
"description": "Controls the state of the sidebar upon load.\n -1 = Default (uses PageMode if available, otherwise the last position if available/enabled).\n 0 = Do not show sidebar.\n 1 = Show thumbnails in sidebar.\n 2 = Show document outline in sidebar.\n 3 = Show attachments in sidebar.", "description": "Controls the state of the sidebar upon load.\n -1 = Default (uses PageMode if available, otherwise the last position if available/enabled).\n 0 = Do not show sidebar.\n 1 = Show thumbnails in sidebar.\n 2 = Show document outline in sidebar.\n 3 = Show attachments in sidebar.",
"type": "integer", "type": "integer",
"enum": [ "enum": [-1, 0, 1, 2, 3],
-1,
0,
1,
2,
3
],
"default": -1 "default": -1
}, },
"enableHandToolOnLoad": { "enableHandToolOnLoad": {
@ -59,14 +45,15 @@
"type": "boolean", "type": "boolean",
"default": false "default": false
}, },
"enableML": {
"type": "boolean",
"default": false
},
"cursorToolOnLoad": { "cursorToolOnLoad": {
"title": "Cursor tool on load", "title": "Cursor tool on load",
"description": "The cursor tool that is enabled upon load.\n 0 = Text selection tool.\n 1 = Hand tool.", "description": "The cursor tool that is enabled upon load.\n 0 = Text selection tool.\n 1 = Hand tool.",
"type": "integer", "type": "integer",
"enum": [ "enum": [0, 1],
0,
1
],
"default": 0 "default": 0
}, },
"pdfBugEnabled": { "pdfBugEnabled": {
@ -85,10 +72,18 @@
"type": "boolean", "type": "boolean",
"default": false "default": false
}, },
"enableHighlightFloatingButton": {
"type": "boolean",
"default": false
},
"highlightEditorColors": { "highlightEditorColors": {
"type": "string", "type": "string",
"default": "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F" "default": "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F"
}, },
"enableStampEditor": {
"type": "boolean",
"default": true
},
"disableRange": { "disableRange": {
"title": "Disable range requests", "title": "Disable range requests",
"description": "Whether to disable range requests (not recommended).", "description": "Whether to disable range requests (not recommended).",
@ -120,23 +115,14 @@
"title": "Text layer mode", "title": "Text layer mode",
"description": "Controls if the text layer is enabled, and the selection mode that is used.\n 0 = Disabled.\n 1 = Enabled.", "description": "Controls if the text layer is enabled, and the selection mode that is used.\n 0 = Disabled.\n 1 = Enabled.",
"type": "integer", "type": "integer",
"enum": [ "enum": [0, 1],
0,
1
],
"default": 1 "default": 1
}, },
"externalLinkTarget": { "externalLinkTarget": {
"title": "External links target window", "title": "External links target window",
"description": "Controls how external links will be opened.\n 0 = default.\n 1 = replaces current window.\n 2 = new window/tab.\n 3 = parent.\n 4 = in top window.", "description": "Controls how external links will be opened.\n 0 = default.\n 1 = replaces current window.\n 2 = new window/tab.\n 3 = parent.\n 4 = in top window.",
"type": "integer", "type": "integer",
"enum": [ "enum": [0, 1, 2, 3, 4],
0,
1,
2,
3,
4
],
"default": 0 "default": 0
}, },
"disablePageLabels": { "disablePageLabels": {
@ -156,22 +142,12 @@
}, },
"annotationMode": { "annotationMode": {
"type": "integer", "type": "integer",
"enum": [ "enum": [0, 1, 2, 3],
0,
1,
2,
3
],
"default": 2 "default": 2
}, },
"annotationEditorMode": { "annotationEditorMode": {
"type": "integer", "type": "integer",
"enum": [ "enum": [-1, 0, 3, 15],
-1,
0,
3,
15
],
"default": 0 "default": 0
}, },
"enablePermissions": { "enablePermissions": {
@ -202,25 +178,14 @@
"title": "Scroll mode on load", "title": "Scroll mode on load",
"description": "Controls how the viewer scrolls upon load.\n -1 = Default (uses the last position if available/enabled).\n 3 = Page scrolling.\n 0 = Vertical scrolling.\n 1 = Horizontal scrolling.\n 2 = Wrapped scrolling.", "description": "Controls how the viewer scrolls upon load.\n -1 = Default (uses the last position if available/enabled).\n 3 = Page scrolling.\n 0 = Vertical scrolling.\n 1 = Horizontal scrolling.\n 2 = Wrapped scrolling.",
"type": "integer", "type": "integer",
"enum": [ "enum": [-1, 0, 1, 2, 3],
-1,
0,
1,
2,
3
],
"default": -1 "default": -1
}, },
"spreadModeOnLoad": { "spreadModeOnLoad": {
"title": "Spread mode on load", "title": "Spread mode on load",
"description": "Whether the viewer should join pages into spreads upon load.\n -1 = Default (uses the last position if available/enabled).\n 0 = No spreads.\n 1 = Odd spreads.\n 2 = Even spreads.", "description": "Whether the viewer should join pages into spreads upon load.\n -1 = Default (uses the last position if available/enabled).\n 0 = No spreads.\n 1 = Odd spreads.\n 2 = Even spreads.",
"type": "integer", "type": "integer",
"enum": [ "enum": [-1, 0, 1, 2],
-1,
0,
1,
2
],
"default": -1 "default": -1
}, },
"forcePageColors": { "forcePageColors": {

View File

@ -0,0 +1,253 @@
import { types as t, transformSync } from "@babel/core";
import fs from "fs";
import { join as joinPaths } from "path";
import vm from "vm";
const PDFJS_PREPROCESSOR_NAME = "PDFJSDev";
const ROOT_PREFIX = "$ROOT/";
function isPDFJSPreprocessor(obj) {
return obj.type === "Identifier" && obj.name === PDFJS_PREPROCESSOR_NAME;
}
function evalWithDefines(code, defines) {
if (!code || !code.trim()) {
throw new Error("No JavaScript expression given");
}
return vm.runInNewContext(code, defines, { displayErrors: false });
}
function handlePreprocessorAction(ctx, actionName, args, path) {
try {
const arg = args[0];
switch (actionName) {
case "test":
if (!t.isStringLiteral(arg)) {
throw new Error("No code for testing is given");
}
return !!evalWithDefines(arg.value, ctx.defines);
case "eval":
if (!t.isStringLiteral(arg)) {
throw new Error("No code for eval is given");
}
const result = evalWithDefines(arg.value, ctx.defines);
if (
typeof result === "boolean" ||
typeof result === "string" ||
typeof result === "number" ||
typeof result === "object"
) {
return result;
}
break;
case "json":
if (!t.isStringLiteral(arg)) {
throw new Error("Path to JSON is not provided");
}
let jsonPath = arg.value;
if (jsonPath.startsWith(ROOT_PREFIX)) {
jsonPath = joinPaths(
ctx.rootPath,
jsonPath.substring(ROOT_PREFIX.length)
);
}
return JSON.parse(fs.readFileSync(jsonPath, "utf8"));
}
throw new Error("Unsupported action");
} catch (e) {
throw path.buildCodeFrameError(
"Could not process " +
PDFJS_PREPROCESSOR_NAME +
"." +
actionName +
": " +
e.message
);
}
}
function babelPluginPDFJSPreprocessor(babel, ctx) {
return {
name: "babel-plugin-pdfjs-preprocessor",
manipulateOptions({ parserOpts }) {
parserOpts.attachComment = false;
},
visitor: {
"ExportNamedDeclaration|ImportDeclaration": ({ node }) => {
if (node.source && ctx.map?.[node.source.value]) {
node.source.value = ctx.map[node.source.value];
}
},
"IfStatement|ConditionalExpression": {
exit(path) {
const { node } = path;
if (t.isBooleanLiteral(node.test)) {
// if (true) stmt1; => stmt1
// if (false) stmt1; else stmt2; => stmt2
if (node.test.value === true) {
path.replaceWith(node.consequent);
} else if (node.alternate) {
path.replaceWith(node.alternate);
} else {
path.remove(node);
}
}
},
},
UnaryExpression: {
exit(path) {
const { node } = path;
if (
node.operator === "typeof" &&
isPDFJSPreprocessor(node.argument)
) {
// typeof PDFJSDev => 'object'
path.replaceWith(t.stringLiteral("object"));
return;
}
if (node.operator === "!" && t.isBooleanLiteral(node.argument)) {
// !true => false, !false => true
path.replaceWith(t.booleanLiteral(!node.argument.value));
}
},
},
LogicalExpression: {
exit(path) {
const { node } = path;
if (!t.isBooleanLiteral(node.left)) {
return;
}
switch (node.operator) {
case "&&":
// true && expr => expr
// false && expr => false
path.replaceWith(
node.left.value === true ? node.right : node.left
);
break;
case "||":
// true || expr => true
// false || expr => expr
path.replaceWith(
node.left.value === true ? node.left : node.right
);
break;
}
},
},
BinaryExpression: {
exit(path) {
const { node } = path;
switch (node.operator) {
case "==":
case "===":
case "!=":
case "!==":
if (t.isLiteral(node.left) && t.isLiteral(node.right)) {
// folding == and != check that can be statically evaluated
const { confident, value } = path.evaluate();
if (confident) {
path.replaceWith(t.booleanLiteral(value));
}
}
}
},
},
CallExpression(path) {
const { node } = path;
if (
t.isMemberExpression(node.callee) &&
isPDFJSPreprocessor(node.callee.object) &&
t.isIdentifier(node.callee.property) &&
!node.callee.computed
) {
// PDFJSDev.xxxx(arg1, arg2, ...) => transform
const action = node.callee.property.name;
const result = handlePreprocessorAction(
ctx,
action,
node.arguments,
path
);
path.replaceWith(t.inherits(t.valueToNode(result), path.node));
}
if (t.isIdentifier(node.callee, { name: "__non_webpack_import__" })) {
if (node.arguments.length !== 1) {
throw new Error("Invalid `__non_webpack_import__` usage.");
}
// Replace it with a standard `import`-call and
// ensure that Webpack will leave it alone.
const source = node.arguments[0];
source.leadingComments = [
{
type: "CommentBlock",
value: "webpackIgnore: true",
},
];
path.replaceWith(t.importExpression(source));
}
},
BlockStatement: {
// Visit node in post-order so that recursive flattening
// of blocks works correctly.
exit(path) {
const { node } = path;
let subExpressionIndex = 0;
while (subExpressionIndex < node.body.length) {
switch (node.body[subExpressionIndex].type) {
case "EmptyStatement":
// Removing empty statements from the blocks.
node.body.splice(subExpressionIndex, 1);
continue;
case "BlockStatement":
// Block statements inside a block are flattened
// into the parent one.
const subChildren = node.body[subExpressionIndex].body;
node.body.splice(subExpressionIndex, 1, ...subChildren);
subExpressionIndex += Math.max(subChildren.length - 1, 0);
continue;
case "ReturnStatement":
case "ThrowStatement":
// Removing dead code after return or throw.
node.body.splice(
subExpressionIndex + 1,
node.body.length - subExpressionIndex - 1
);
break;
}
subExpressionIndex++;
}
},
},
Function: {
exit(path) {
if (!t.isBlockStatement(path.node.body)) {
// Arrow function with expression body
return;
}
const { body } = path.node.body;
if (
body.length > 0 &&
t.isReturnStatement(body.at(-1), { argument: null })
) {
// Function body ends with return without arg -- removing it.
body.pop();
}
},
},
},
};
}
function preprocessPDFJSCode(ctx, content) {
return transformSync(content, {
configFile: false,
plugins: [[babelPluginPDFJSPreprocessor, ctx]],
}).code;
}
export { babelPluginPDFJSPreprocessor, preprocessPDFJSCode };

View File

@ -1,10 +1,10 @@
function test() { function test() {
"test"; "test";
"1"; "1";
"2"; "2";
"3"; "3";
if ("test") { if ("test") {
"5"; "5";
} }
"4"; "4";
} }

View File

@ -1,17 +1,17 @@
function f1() { function f1() {
"1"; "1";
"2"; "2";
} }
function f2() { function f2() {
"1"; "1";
"2"; "2";
} }
function f3() { function f3() {
if ("1") { if ("1") {
"1"; "1";
} }
"2"; "2";
if ("3") { if ("3") {
"4"; "4";
} }
} }

View File

@ -10,6 +10,6 @@ var i = true;
var j = false; var j = false;
var k = false; var k = false;
var l = true; var l = true;
var m = '1' === true; var m = false;
var n = false; var n = false;
var o = true; var o = true;

View File

@ -1,13 +1,21 @@
function f1() { function f1() {}
}
function f2() { function f2() {
return 1; return 1;
} }
function f3() { function f3() {
var i = 0; var i = 0;
throw "test"; throw "test";
} }
function f4() { function f4() {
var i = 0; var i = 0;
} }
var obj = {
method1() {},
method2() {}
};
class C {
method1() {}
method2() {}
}
var arrow1 = () => {};
var arrow2 = () => {};

View File

@ -23,3 +23,15 @@ function f4() {
var j = 0; var j = 0;
} }
var obj = {
method1() { return; var i = 0; },
method2() { return; },
};
class C {
method1() { return; var i = 0; }
method2() { return; }
}
var arrow1 = () => { return; var i = 0; };
var arrow2 = () => { return; };

View File

@ -3,11 +3,19 @@ var b = true;
var c = true; var c = true;
var d = false; var d = false;
var e = true; var e = true;
var f = 'text'; var f = "text";
var g = { var g = {
"obj": { "i": 1 }, obj: {
"j": 2 i: 1
},
j: 2
};
var h = {
test: "test"
}; };
var h = { 'test': 'test' };
var i = '0'; var i = '0';
var j = { "i": 1 }; var j = {
i: 1
};
var k = false;
var l = true;

View File

@ -8,3 +8,5 @@ var g = PDFJSDev.eval('OBJ');
var h = PDFJSDev.json('$ROOT/external/builder/fixtures_esprima/evals.json'); var h = PDFJSDev.json('$ROOT/external/builder/fixtures_esprima/evals.json');
var i = typeof PDFJSDev === 'undefined' ? PDFJSDev.eval('FALSE') : '0'; var i = typeof PDFJSDev === 'undefined' ? PDFJSDev.eval('FALSE') : '0';
var j = typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('OBJ.obj') : '0'; var j = typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('OBJ.obj') : '0';
var k = !PDFJSDev.test('TRUE');
var l = !PDFJSDev.test('FALSE');

View File

@ -1 +1 @@
{ 'test': 'test' } { "test": "test" }

View File

@ -1,17 +1,18 @@
if ('test') { if ('test') {
"1"; "1";
} }
{ {
"1"; "1";
} }
{ {
"1"; "1";
} }
;
{ {
"2"; "2";
} }
;
if ('1') { if ('1') {
"1"; "1";
}
function f1() {
"1";
} }

View File

@ -23,3 +23,12 @@ if (true && false) {
if (true && false || '1') { if (true && false || '1') {
"1"; "1";
} }
function f1() {
if (true) {
"1";
}
if (false) {
"2";
}
}

View File

@ -1,7 +1,4 @@
import { Test } from 'import-name'; import { Test } from "import-name";
import { Test2 } from './non-alias'; import { Test2 } from './non-alias';
export { export { Test3 } from "import-name";
Test3 await import( /*webpackIgnore: true*/"./non-alias");
} from 'import-name';
var Imp = require('import-name');
var Imp2 = require('./non-alias');

View File

@ -1,5 +1,4 @@
import { Test } from 'import-alias'; import { Test } from 'import-alias';
import { Test2 } from './non-alias'; import { Test2 } from './non-alias';
export { Test3 } from 'import-alias'; export { Test3 } from 'import-alias';
var Imp = require('import-alias'); await __non_webpack_import__("./non-alias");
var Imp2 = require('./non-alias');

View File

@ -1,347 +0,0 @@
import * as acorn from "acorn";
import escodegen from "@javascript-obfuscator/escodegen";
import fs from "fs";
import path from "path";
import vm from "vm";
const PDFJS_PREPROCESSOR_NAME = "PDFJSDev";
const ROOT_PREFIX = "$ROOT/";
const ACORN_ECMA_VERSION = 2022;
function isLiteral(obj, value) {
return obj.type === "Literal" && obj.value === value;
}
function isPDFJSPreprocessor(obj) {
return obj.type === "Identifier" && obj.name === PDFJS_PREPROCESSOR_NAME;
}
function evalWithDefines(code, defines, loc) {
if (!code || !code.trim()) {
throw new Error("No JavaScript expression given");
}
return vm.runInNewContext(code, defines, { displayErrors: false });
}
function handlePreprocessorAction(ctx, actionName, args, loc) {
try {
let arg;
switch (actionName) {
case "test":
arg = args[0];
if (!arg || arg.type !== "Literal" || typeof arg.value !== "string") {
throw new Error("No code for testing is given");
}
const isTrue = !!evalWithDefines(arg.value, ctx.defines);
return { type: "Literal", value: isTrue, loc };
case "eval":
arg = args[0];
if (!arg || arg.type !== "Literal" || typeof arg.value !== "string") {
throw new Error("No code for eval is given");
}
const result = evalWithDefines(arg.value, ctx.defines);
if (
typeof result === "boolean" ||
typeof result === "string" ||
typeof result === "number"
) {
return { type: "Literal", value: result, loc };
}
if (typeof result === "object") {
const parsedObj = acorn.parse("(" + JSON.stringify(result) + ")", {
ecmaVersion: ACORN_ECMA_VERSION,
});
parsedObj.body[0].expression.loc = loc;
return parsedObj.body[0].expression;
}
break;
case "json":
arg = args[0];
if (!arg || arg.type !== "Literal" || typeof arg.value !== "string") {
throw new Error("Path to JSON is not provided");
}
let jsonPath = arg.value;
if (jsonPath.indexOf(ROOT_PREFIX) === 0) {
jsonPath = path.join(
ctx.rootPath,
jsonPath.substring(ROOT_PREFIX.length)
);
}
const jsonContent = fs.readFileSync(jsonPath).toString();
const parsedJSON = acorn.parse("(" + jsonContent + ")", {
ecmaVersion: ACORN_ECMA_VERSION,
});
parsedJSON.body[0].expression.loc = loc;
return parsedJSON.body[0].expression;
}
throw new Error("Unsupported action");
} catch (e) {
throw new Error(
"Could not process " +
PDFJS_PREPROCESSOR_NAME +
"." +
actionName +
" at " +
JSON.stringify(loc) +
"\n" +
e.name +
": " +
e.message
);
}
}
function postprocessNode(ctx, node) {
switch (node.type) {
case "ExportNamedDeclaration":
case "ImportDeclaration":
if (
node.source &&
node.source.type === "Literal" &&
ctx.map &&
ctx.map[node.source.value]
) {
const newValue = ctx.map[node.source.value];
node.source.value = node.source.raw = newValue;
}
break;
case "IfStatement":
if (isLiteral(node.test, true)) {
// if (true) stmt1; => stmt1
return node.consequent;
} else if (isLiteral(node.test, false)) {
// if (false) stmt1; else stmt2; => stmt2
return node.alternate || { type: "EmptyStatement", loc: node.loc };
}
break;
case "ConditionalExpression":
if (isLiteral(node.test, true)) {
// true ? stmt1 : stmt2 => stmt1
return node.consequent;
} else if (isLiteral(node.test, false)) {
// false ? stmt1 : stmt2 => stmt2
return node.alternate;
}
break;
case "UnaryExpression":
if (node.operator === "typeof" && isPDFJSPreprocessor(node.argument)) {
// typeof PDFJSDev => 'object'
return { type: "Literal", value: "object", loc: node.loc };
}
if (
node.operator === "!" &&
node.argument.type === "Literal" &&
typeof node.argument.value === "boolean"
) {
// !true => false, !false => true
return { type: "Literal", value: !node.argument.value, loc: node.loc };
}
break;
case "LogicalExpression":
switch (node.operator) {
case "&&":
if (isLiteral(node.left, true)) {
return node.right;
}
if (isLiteral(node.left, false)) {
return node.left;
}
break;
case "||":
if (isLiteral(node.left, true)) {
return node.left;
}
if (isLiteral(node.left, false)) {
return node.right;
}
break;
}
break;
case "BinaryExpression":
switch (node.operator) {
case "==":
case "===":
case "!=":
case "!==":
if (
node.left.type === "Literal" &&
node.right.type === "Literal" &&
typeof node.left.value === typeof node.right.value
) {
// folding two literals == and != check
switch (typeof node.left.value) {
case "string":
case "boolean":
case "number":
const equal = node.left.value === node.right.value;
return {
type: "Literal",
value: (node.operator[0] === "=") === equal,
loc: node.loc,
};
}
}
break;
}
break;
case "CallExpression":
if (
node.callee.type === "MemberExpression" &&
isPDFJSPreprocessor(node.callee.object) &&
node.callee.property.type === "Identifier"
) {
// PDFJSDev.xxxx(arg1, arg2, ...) => transform
const action = node.callee.property.name;
return handlePreprocessorAction(ctx, action, node.arguments, node.loc);
}
// require('string')
if (
node.callee.type === "Identifier" &&
node.callee.name === "require" &&
node.arguments.length === 1 &&
node.arguments[0].type === "Literal" &&
ctx.map &&
ctx.map[node.arguments[0].value]
) {
const requireName = node.arguments[0];
requireName.value = requireName.raw = ctx.map[requireName.value];
}
break;
case "BlockStatement":
let subExpressionIndex = 0;
while (subExpressionIndex < node.body.length) {
switch (node.body[subExpressionIndex].type) {
case "EmptyStatement":
// Removing empty statements from the blocks.
node.body.splice(subExpressionIndex, 1);
continue;
case "BlockStatement":
// Block statements inside a block are moved to the parent one.
const subChildren = node.body[subExpressionIndex].body;
Array.prototype.splice.apply(node.body, [
subExpressionIndex,
1,
...subChildren,
]);
subExpressionIndex += Math.max(subChildren.length - 1, 0);
continue;
case "ReturnStatement":
case "ThrowStatement":
// Removing dead code after return or throw.
node.body.splice(
subExpressionIndex + 1,
node.body.length - subExpressionIndex - 1
);
break;
}
subExpressionIndex++;
}
break;
case "FunctionDeclaration":
case "FunctionExpression":
const block = node.body;
if (
block.body.length > 0 &&
block.body.at(-1).type === "ReturnStatement" &&
!block.body.at(-1).argument
) {
// Function body ends with return without arg -- removing it.
block.body.pop();
}
break;
}
return node;
}
function fixComments(ctx, node) {
if (!ctx.saveComments) {
return;
}
// Fixes double comments in the escodegen output.
delete node.trailingComments;
// Removes ESLint and other service comments.
if (node.leadingComments) {
const CopyrightRegExp = /\bcopyright\b/i;
const BlockCommentRegExp = /^\s*(globals|eslint|falls through)\b/;
const LineCommentRegExp = /^\s*eslint\b/;
let i = 0;
while (i < node.leadingComments.length) {
const type = node.leadingComments[i].type;
const value = node.leadingComments[i].value;
if (ctx.saveComments === "copyright") {
// Remove all comments, except Copyright notices and License headers.
if (!(type === "Block" && CopyrightRegExp.test(value))) {
node.leadingComments.splice(i, 1);
continue;
}
} else if (
(type === "Block" && BlockCommentRegExp.test(value)) ||
(type === "Line" && LineCommentRegExp.test(value))
) {
node.leadingComments.splice(i, 1);
continue;
}
i++;
}
}
}
function traverseTree(ctx, node) {
// generic node processing
for (const i in node) {
const child = node[i];
if (typeof child === "object" && child !== null && child.type) {
const result = traverseTree(ctx, child);
if (result !== child) {
node[i] = result;
}
} else if (Array.isArray(child)) {
child.forEach(function (childItem, index) {
if (
typeof childItem === "object" &&
childItem !== null &&
childItem.type
) {
const result = traverseTree(ctx, childItem);
if (result !== childItem) {
child[index] = result;
}
}
});
}
}
node = postprocessNode(ctx, node) || node;
fixComments(ctx, node);
return node;
}
function preprocessPDFJSCode(ctx, code) {
const format = ctx.format || {
indent: {
style: " ",
},
};
const parseOptions = {
ecmaVersion: ACORN_ECMA_VERSION,
locations: true,
sourceFile: ctx.sourceFile,
sourceType: "module",
};
const codegenOptions = {
format,
parse(input) {
return acorn.parse(input, { ecmaVersion: ACORN_ECMA_VERSION });
},
sourceMap: ctx.sourceMap,
sourceMapWithCode: ctx.sourceMap,
};
const syntax = acorn.parse(code, parseOptions);
traverseTree(ctx, syntax);
return escodegen.generate(syntax, codegenOptions);
}
export { preprocessPDFJSCode };

View File

@ -42,6 +42,12 @@ files.forEach(function (expectationFilename) {
if (out !== expectation) { if (out !== expectation) {
errors++; errors++;
// Allow regenerating the expected output using
// OVERWRITE=true node ./external/builder/test-fixtures.mjs
if (process.env.OVERWRITE) {
fs.writeFileSync(expectationFilename, out + "\n");
}
console.log("Assertion failed for " + inFilename); console.log("Assertion failed for " + inFilename);
console.log("--------------------------------------------------"); console.log("--------------------------------------------------");
console.log("EXPECTED:"); console.log("EXPECTED:");

View File

@ -1,7 +1,7 @@
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
import { preprocessPDFJSCode } from "./preprocessor2.mjs"; import { preprocessPDFJSCode } from "./babel-plugin-pdfjs-preprocessor.mjs";
const __dirname = path.dirname(fileURLToPath(import.meta.url)); const __dirname = path.dirname(fileURLToPath(import.meta.url));
@ -48,6 +48,12 @@ files.forEach(function (expectationFilename) {
if (out !== expectation) { if (out !== expectation) {
errors++; errors++;
// Allow regenerating the expected output using
// OVERWRITE=true node ./external/builder/test-fixtures_esprima.mjs
if (process.env.OVERWRITE) {
fs.writeFileSync(expectationFilename, out + "\n");
}
console.log("Assertion failed for " + inFilename); console.log("Assertion failed for " + inFilename);
console.log("--------------------------------------------------"); console.log("--------------------------------------------------");
console.log("EXPECTED:"); console.log("EXPECTED:");

View File

@ -14,7 +14,6 @@
*/ */
import fs from "fs"; import fs from "fs";
import https from "https";
import path from "path"; import path from "path";
// Fetches all languages that have an *active* translation in mozilla-central. // Fetches all languages that have an *active* translation in mozilla-central.
@ -22,47 +21,34 @@ import path from "path";
const DEFAULT_LOCALE = "en-US"; const DEFAULT_LOCALE = "en-US";
const EXCLUDE_LANG_CODES = ["ca-valencia", "ja-JP-mac"]; const EXCLUDE_LANG_CODES = new Set(["ca-valencia", "ja-JP-mac"]);
function normalizeText(s) { function normalizeText(s) {
return s.replaceAll(/\r\n?/g, "\n").replaceAll("\uFEFF", ""); return s.replaceAll(/\r\n?/g, "\n").replaceAll("\uFEFF", "");
} }
function downloadLanguageCodes() { async function downloadLanguageCodes() {
console.log("Downloading language codes...\n"); console.log("Downloading language codes...\n");
const ALL_LOCALES = const ALL_LOCALES =
"https://hg.mozilla.org/mozilla-central/raw-file/tip/browser/locales/all-locales"; "https://hg.mozilla.org/mozilla-central/raw-file/tip/browser/locales/all-locales";
return new Promise(function (resolve) { const response = await fetch(ALL_LOCALES);
https.get(ALL_LOCALES, function (response) { if (!response.ok) {
if (response.statusCode === 200) { throw new Error(response.statusText);
let content = ""; }
response.setEncoding("utf8"); const content = await response.text();
response.on("data", function (chunk) {
content += chunk; // Remove any leading/trailing white-space.
}); const langCodes = normalizeText(content.trim()).split("\n");
response.on("end", function () { // Remove all locales that we don't want to download below.
content = content.trim(); // Remove any leading/trailing white-space. return langCodes.filter(
const langCodes = normalizeText(content).split("\n"); langCode => langCode !== DEFAULT_LOCALE && !EXCLUDE_LANG_CODES.has(langCode)
// Remove all locales that we don't want to download below. );
for (const langCode of [DEFAULT_LOCALE, ...EXCLUDE_LANG_CODES]) {
const i = langCodes.indexOf(langCode);
if (i > -1) {
langCodes.splice(i, 1);
}
}
resolve(langCodes);
});
} else {
resolve([]);
}
});
});
} }
function downloadLanguageFiles(root, langCode) { async function downloadLanguageFiles(root, langCode) {
console.log("Downloading " + langCode + "..."); console.log(`Downloading ${langCode}...`);
// Constants for constructing the URLs. Translations are taken from the // Constants for constructing the URLs. Translations are taken from the
// Nightly channel as those are the most recent ones. // Nightly channel as those are the most recent ones.
@ -71,41 +57,27 @@ function downloadLanguageFiles(root, langCode) {
// Defines which files to download for each language. // Defines which files to download for each language.
const files = ["viewer.ftl"]; const files = ["viewer.ftl"];
let downloadsLeft = files.length;
const outputDir = path.join(root, langCode); const outputDir = path.join(root, langCode);
if (!fs.existsSync(outputDir)) { if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir); fs.mkdirSync(outputDir);
} }
return new Promise(function (resolve) { // Download the necessary files for this language.
// Download the necessary files for this language. for (const fileName of files) {
files.forEach(function (fileName) { const outputPath = path.join(outputDir, fileName);
const outputPath = path.join(outputDir, fileName); const url = MOZ_CENTRAL_ROOT + langCode + MOZ_CENTRAL_PDFJS_DIR + fileName;
const url =
MOZ_CENTRAL_ROOT + langCode + MOZ_CENTRAL_PDFJS_DIR + fileName;
https.get(url, function (response) { const response = await fetch(url);
// Not all files exist for each language. Files without translations if (!response.ok) {
// have been removed (https://bugzilla.mozilla.org/show_bug.cgi?id=1443175). // Not all files exist for each language. Files without translations
if (response.statusCode === 200) { // have been removed (https://bugzilla.mozilla.org/show_bug.cgi?id=1443175).
let content = ""; continue;
response.setEncoding("utf8"); }
response.on("data", function (chunk) { const content = await response.text();
content += chunk;
}); fs.writeFileSync(outputPath, normalizeText(content), "utf8");
response.on("end", function () { }
fs.writeFileSync(outputPath, normalizeText(content), "utf8");
if (--downloadsLeft === 0) {
resolve();
}
});
} else if (--downloadsLeft === 0) {
resolve();
}
});
});
});
} }
async function downloadL10n(root) { async function downloadL10n(root) {

File diff suppressed because one or more lines are too long

View File

@ -1,41 +0,0 @@
/* Copyright 2017 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import path from "path";
import { preprocessPDFJSCode } from "../builder/preprocessor2.mjs";
export default function (source) {
// Options must be specified, ignoring request if not.
if (!this.query || typeof this.query !== "object") {
return source;
}
this.cacheable();
const filePath = this.resourcePath;
const context = this.rootContext;
const sourcePath = path.relative(context, filePath).split(path.sep).join("/");
const ctx = Object.create(this.query);
ctx.sourceMap = true;
ctx.sourceFile = sourcePath;
const callback = this.callback;
const sourceAndMap = preprocessPDFJSCode(ctx, source);
const map = sourceAndMap.map.toJSON();
// escodegen does not embed source -- setting map's sourcesContent.
map.sourcesContent = [source];
callback(null, sourceAndMap.code, map);
return undefined;
}

View File

@ -14,6 +14,10 @@
*/ */
/* eslint-env node */ /* eslint-env node */
import {
babelPluginPDFJSPreprocessor,
preprocessPDFJSCode,
} from "./external/builder/babel-plugin-pdfjs-preprocessor.mjs";
import { exec, spawn, spawnSync } from "child_process"; import { exec, spawn, spawnSync } from "child_process";
import autoprefixer from "autoprefixer"; import autoprefixer from "autoprefixer";
import babel from "@babel/core"; import babel from "@babel/core";
@ -30,12 +34,12 @@ import postcssDirPseudoClass from "postcss-dir-pseudo-class";
import postcssDiscardComments from "postcss-discard-comments"; import postcssDiscardComments from "postcss-discard-comments";
import postcssNesting from "postcss-nesting"; import postcssNesting from "postcss-nesting";
import { preprocess } from "./external/builder/builder.mjs"; import { preprocess } from "./external/builder/builder.mjs";
import { preprocessPDFJSCode } from "./external/builder/preprocessor2.mjs";
import rename from "gulp-rename"; import rename from "gulp-rename";
import replace from "gulp-replace"; import replace from "gulp-replace";
import rimraf from "rimraf"; import rimraf from "rimraf";
import stream from "stream"; import stream from "stream";
import streamqueue from "streamqueue"; import streamqueue from "streamqueue";
import TerserPlugin from "terser-webpack-plugin";
import through from "through2"; import through from "through2";
import Vinyl from "vinyl"; import Vinyl from "vinyl";
import webpack2 from "webpack"; import webpack2 from "webpack";
@ -204,15 +208,18 @@ function createWebpackConfig(
!bundleDefines.MOZCENTRAL && !bundleDefines.MOZCENTRAL &&
!bundleDefines.CHROME && !bundleDefines.CHROME &&
!bundleDefines.LIB && !bundleDefines.LIB &&
!bundleDefines.MINIFIED &&
!bundleDefines.TESTING && !bundleDefines.TESTING &&
!disableSourceMaps; !disableSourceMaps;
const isModule = output.library?.type === "module"; const isModule = output.library?.type === "module";
const isMinified = bundleDefines.MINIFIED;
const skipBabel = bundleDefines.SKIP_BABEL; const skipBabel = bundleDefines.SKIP_BABEL;
// `core-js`, see https://github.com/zloirock/core-js/issues/514, const babelExcludeRegExp = [
// should be excluded from processing. // `core-js`, see https://github.com/zloirock/core-js/issues/514,
const babelExcludes = ["node_modules[\\\\\\/]core-js"]; // should be excluded from processing.
const babelExcludeRegExp = new RegExp(`(${babelExcludes.join("|")})`); /node_modules[\\/]core-js/,
];
const babelPresets = skipBabel const babelPresets = skipBabel
? undefined ? undefined
@ -220,14 +227,22 @@ function createWebpackConfig(
[ [
"@babel/preset-env", "@babel/preset-env",
{ {
corejs: "3.34.0", corejs: "3.36.0",
exclude: ["web.structured-clone"], exclude: ["web.structured-clone"],
shippedProposals: true, shippedProposals: true,
useBuiltIns: "usage", useBuiltIns: "usage",
}, },
], ],
]; ];
const babelPlugins = []; const babelPlugins = [
[
babelPluginPDFJSPreprocessor,
{
rootPath: __dirname,
defines: bundleDefines,
},
],
];
const plugins = []; const plugins = [];
if (!disableLicenseHeader) { if (!disableLicenseHeader) {
@ -257,8 +272,9 @@ function createWebpackConfig(
const viewerAlias = { const viewerAlias = {
"web-alt_text_manager": "web/alt_text_manager.js", "web-alt_text_manager": "web/alt_text_manager.js",
"web-annotation_editor_params": "web/annotation_editor_params.js", "web-annotation_editor_params": "web/annotation_editor_params.js",
"web-com": "", "web-download_manager": "",
"web-l10n_utils": "web/stubs.js", "web-external_services": "",
"web-null_l10n": "",
"web-pdf_attachment_viewer": "web/pdf_attachment_viewer.js", "web-pdf_attachment_viewer": "web/pdf_attachment_viewer.js",
"web-pdf_cursor_tools": "web/pdf_cursor_tools.js", "web-pdf_cursor_tools": "web/pdf_cursor_tools.js",
"web-pdf_document_properties": "web/pdf_document_properties.js", "web-pdf_document_properties": "web/pdf_document_properties.js",
@ -268,6 +284,7 @@ function createWebpackConfig(
"web-pdf_presentation_mode": "web/pdf_presentation_mode.js", "web-pdf_presentation_mode": "web/pdf_presentation_mode.js",
"web-pdf_sidebar": "web/pdf_sidebar.js", "web-pdf_sidebar": "web/pdf_sidebar.js",
"web-pdf_thumbnail_viewer": "web/pdf_thumbnail_viewer.js", "web-pdf_thumbnail_viewer": "web/pdf_thumbnail_viewer.js",
"web-preferences": "",
"web-print_service": "", "web-print_service": "",
"web-secondary_toolbar": "web/secondary_toolbar.js", "web-secondary_toolbar": "web/secondary_toolbar.js",
"web-toolbar": "web/toolbar.js", "web-toolbar": "web/toolbar.js",
@ -276,7 +293,10 @@ function createWebpackConfig(
libraryAlias["display-fetch_stream"] = "src/display/fetch_stream.js"; libraryAlias["display-fetch_stream"] = "src/display/fetch_stream.js";
libraryAlias["display-network"] = "src/display/network.js"; libraryAlias["display-network"] = "src/display/network.js";
viewerAlias["web-com"] = "web/chromecom.js"; viewerAlias["web-download_manager"] = "web/download_manager.js";
viewerAlias["web-external_services"] = "web/chromecom.js";
viewerAlias["web-null_l10n"] = "web/l10n.js";
viewerAlias["web-preferences"] = "web/chromecom.js";
viewerAlias["web-print_service"] = "web/pdf_print_service.js"; viewerAlias["web-print_service"] = "web/pdf_print_service.js";
} else if (bundleDefines.GENERIC) { } else if (bundleDefines.GENERIC) {
// Aliases defined here must also be replicated in the paths section of // Aliases defined here must also be replicated in the paths section of
@ -287,20 +307,24 @@ function createWebpackConfig(
libraryAlias["display-node_stream"] = "src/display/node_stream.js"; libraryAlias["display-node_stream"] = "src/display/node_stream.js";
libraryAlias["display-node_utils"] = "src/display/node_utils.js"; libraryAlias["display-node_utils"] = "src/display/node_utils.js";
viewerAlias["web-com"] = "web/genericcom.js"; viewerAlias["web-download_manager"] = "web/download_manager.js";
viewerAlias["web-l10n_utils"] = "web/l10n_utils.js"; viewerAlias["web-external_services"] = "web/genericcom.js";
viewerAlias["web-null_l10n"] = "web/genericl10n.js";
viewerAlias["web-preferences"] = "web/genericcom.js";
viewerAlias["web-print_service"] = "web/pdf_print_service.js"; viewerAlias["web-print_service"] = "web/pdf_print_service.js";
} else if (bundleDefines.MOZCENTRAL) { } else if (bundleDefines.MOZCENTRAL) {
if (bundleDefines.GECKOVIEW) { if (bundleDefines.GECKOVIEW) {
const gvAlias = { const gvAlias = {
"web-l10n_utils": "web/stubs.js",
"web-toolbar": "web/toolbar-geckoview.js", "web-toolbar": "web/toolbar-geckoview.js",
}; };
for (const key in viewerAlias) { for (const key in viewerAlias) {
viewerAlias[key] = gvAlias[key] || "web/stubs-geckoview.js"; viewerAlias[key] = gvAlias[key] || "web/stubs-geckoview.js";
} }
} }
viewerAlias["web-com"] = "web/firefoxcom.js"; viewerAlias["web-download_manager"] = "web/firefoxcom.js";
viewerAlias["web-external_services"] = "web/firefoxcom.js";
viewerAlias["web-null_l10n"] = "web/l10n.js";
viewerAlias["web-preferences"] = "web/firefoxcom.js";
viewerAlias["web-print_service"] = "web/firefox_print_service.js"; viewerAlias["web-print_service"] = "web/firefox_print_service.js";
} }
const alias = { ...basicAlias, ...libraryAlias, ...viewerAlias }; const alias = { ...basicAlias, ...libraryAlias, ...viewerAlias };
@ -312,7 +336,28 @@ function createWebpackConfig(
mode: "production", mode: "production",
optimization: { optimization: {
mangleExports: false, mangleExports: false,
minimize: false, minimize: isMinified,
minimizer: !isMinified
? undefined
: [
new TerserPlugin({
extractComments: false,
parallel: false,
terserOptions: {
compress: {
// V8 chokes on very long sequences, work around that.
sequences: false,
},
mangle: {
// Ensure that the `tweakWebpackOutput` function works.
reserved: ["__webpack_exports__"],
},
keep_classnames: true,
keep_fnames: true,
module: isModule,
},
}),
],
}, },
experiments, experiments,
output, output,
@ -335,14 +380,6 @@ function createWebpackConfig(
targets: BABEL_TARGETS, targets: BABEL_TARGETS,
}, },
}, },
{
loader: path.join(__dirname, "external/webpack/pdfjsdev-loader.mjs"),
options: {
rootPath: __dirname,
saveComments: false,
defines: bundleDefines,
},
},
], ],
}, },
// Avoid shadowing actual Node.js variables with polyfills, by disabling // Avoid shadowing actual Node.js variables with polyfills, by disabling
@ -406,24 +443,24 @@ function checkChromePreferencesFile(chromePrefsPath, webPrefs) {
} }
function tweakWebpackOutput(jsName) { function tweakWebpackOutput(jsName) {
const replacer = ["__non_webpack_import__\\("]; const replacer = [
" __webpack_exports__ = {};",
if (jsName) { ",__webpack_exports__={};",
replacer.push( " __webpack_exports__ = await __webpack_exports__;",
" __webpack_exports__ = {};", "\\(__webpack_exports__=await __webpack_exports__\\)",
" __webpack_exports__ = await __webpack_exports__;" ];
);
}
const regex = new RegExp(`(${replacer.join("|")})`, "gm"); const regex = new RegExp(`(${replacer.join("|")})`, "gm");
return replace(regex, match => { return replace(regex, match => {
switch (match) { switch (match) {
case "__non_webpack_import__(":
return "import(/* webpackIgnore: true */ ";
case " __webpack_exports__ = {};": case " __webpack_exports__ = {};":
return ` __webpack_exports__ = globalThis.${jsName} = {};`; return ` __webpack_exports__ = globalThis.${jsName} = {};`;
case ",__webpack_exports__={};":
return `,__webpack_exports__=globalThis.${jsName}={};`;
case " __webpack_exports__ = await __webpack_exports__;": case " __webpack_exports__ = await __webpack_exports__;":
return ` __webpack_exports__ = globalThis.${jsName} = await (globalThis.${jsName}Promise = __webpack_exports__);`; return ` __webpack_exports__ = globalThis.${jsName} = await (globalThis.${jsName}Promise = __webpack_exports__);`;
case "(__webpack_exports__=await __webpack_exports__)":
return `(__webpack_exports__=globalThis.${jsName}=await (globalThis.${jsName}Promise=__webpack_exports__))`;
} }
return match; return match;
}); });
@ -431,7 +468,7 @@ function tweakWebpackOutput(jsName) {
function createMainBundle(defines) { function createMainBundle(defines) {
const mainFileConfig = createWebpackConfig(defines, { const mainFileConfig = createWebpackConfig(defines, {
filename: "pdf.mjs", filename: defines.MINIFIED ? "pdf.min.mjs" : "pdf.mjs",
library: { library: {
type: "module", type: "module",
}, },
@ -455,15 +492,13 @@ function createScriptingBundle(defines, extraOptions = undefined) {
); );
return gulp return gulp
.src("./src/pdf.scripting.js") .src("./src/pdf.scripting.js")
.pipe(webpack2Stream(scriptingFileConfig)) .pipe(webpack2Stream(scriptingFileConfig));
.pipe(tweakWebpackOutput());
} }
function createSandboxExternal(defines) { function createSandboxExternal(defines) {
const licenseHeader = fs.readFileSync("./src/license_header.js").toString(); const licenseHeader = fs.readFileSync("./src/license_header.js").toString();
const ctx = { const ctx = {
saveComments: false,
defines, defines,
}; };
return gulp return gulp
@ -497,7 +532,9 @@ function createSandboxBundle(defines, extraOptions = undefined) {
const sandboxFileConfig = createWebpackConfig( const sandboxFileConfig = createWebpackConfig(
sandboxDefines, sandboxDefines,
{ {
filename: "pdf.sandbox.mjs", filename: sandboxDefines.MINIFIED
? "pdf.sandbox.min.mjs"
: "pdf.sandbox.mjs",
library: { library: {
type: "module", type: "module",
}, },
@ -513,7 +550,7 @@ function createSandboxBundle(defines, extraOptions = undefined) {
function createWorkerBundle(defines) { function createWorkerBundle(defines) {
const workerFileConfig = createWebpackConfig(defines, { const workerFileConfig = createWebpackConfig(defines, {
filename: "pdf.worker.mjs", filename: defines.MINIFIED ? "pdf.worker.min.mjs" : "pdf.worker.mjs",
library: { library: {
type: "module", type: "module",
}, },
@ -537,10 +574,7 @@ function createWebBundle(defines, options) {
defaultPreferencesDir: options.defaultPreferencesDir, defaultPreferencesDir: options.defaultPreferencesDir,
} }
); );
return gulp return gulp.src("./web/viewer.js").pipe(webpack2Stream(viewerFileConfig));
.src("./web/viewer.js")
.pipe(webpack2Stream(viewerFileConfig))
.pipe(tweakWebpackOutput());
} }
function createGVWebBundle(defines, options) { function createGVWebBundle(defines, options) {
@ -558,8 +592,7 @@ function createGVWebBundle(defines, options) {
); );
return gulp return gulp
.src("./web/viewer-geckoview.js") .src("./web/viewer-geckoview.js")
.pipe(webpack2Stream(viewerFileConfig)) .pipe(webpack2Stream(viewerFileConfig));
.pipe(tweakWebpackOutput());
} }
function createComponentsBundle(defines) { function createComponentsBundle(defines) {
@ -577,7 +610,9 @@ function createComponentsBundle(defines) {
function createImageDecodersBundle(defines) { function createImageDecodersBundle(defines) {
const componentsFileConfig = createWebpackConfig(defines, { const componentsFileConfig = createWebpackConfig(defines, {
filename: "pdf.image_decoders.mjs", filename: defines.MINIFIED
? "pdf.image_decoders.min.mjs"
: "pdf.image_decoders.mjs",
library: { library: {
type: "module", type: "module",
}, },
@ -691,6 +726,9 @@ function createTestSource(testsName, { bot = false, xfaOnly = false } = {}) {
const testProcess = startNode(args, { cwd: TEST_DIR, stdio: "inherit" }); const testProcess = startNode(args, { cwd: TEST_DIR, stdio: "inherit" });
testProcess.on("close", function (code) { testProcess.on("close", function (code) {
if (code !== 0) {
throw new Error(`Running ${testsName} tests failed.`);
}
source.push(null); source.push(null);
}); });
return undefined; return undefined;
@ -722,6 +760,10 @@ function makeRef(done, bot) {
const testProcess = startNode(args, { cwd: TEST_DIR, stdio: "inherit" }); const testProcess = startNode(args, { cwd: TEST_DIR, stdio: "inherit" });
testProcess.on("close", function (code) { testProcess.on("close", function (code) {
if (code !== 0) {
done(new Error("Creating reference images failed."));
return;
}
done(); done();
}); });
} }
@ -821,11 +863,17 @@ async function parseDefaultPreferences(dir) {
"./" + DEFAULT_PREFERENCES_DIR + dir + "app_options.mjs" "./" + DEFAULT_PREFERENCES_DIR + dir + "app_options.mjs"
); );
const browserPrefs = AppOptions.getAll(OptionKind.BROWSER); const browserPrefs = AppOptions.getAll(
OptionKind.BROWSER,
/* defaultOnly = */ true
);
if (Object.keys(browserPrefs).length === 0) { if (Object.keys(browserPrefs).length === 0) {
throw new Error("No browser preferences found."); throw new Error("No browser preferences found.");
} }
const prefs = AppOptions.getAll(OptionKind.PREFERENCE); const prefs = AppOptions.getAll(
OptionKind.PREFERENCE,
/* defaultOnly = */ true
);
if (Object.keys(prefs).length === 0) { if (Object.keys(prefs).length === 0) {
throw new Error("No default preferences found."); throw new Error("No default preferences found.");
} }
@ -1079,7 +1127,8 @@ function buildComponents(defines, dir) {
"web/images/loading-icon.gif", "web/images/loading-icon.gif",
"web/images/altText_*.svg", "web/images/altText_*.svg",
"web/images/editor-toolbar-*.svg", "web/images/editor-toolbar-*.svg",
"web/images/toolbarButton-menuArrow.svg", "web/images/toolbarButton-{editorHighlight,menuArrow}.svg",
"web/images/cursor-*.svg",
]; ];
return merge([ return merge([
@ -1169,68 +1218,6 @@ function buildMinified(defines, dir) {
]); ]);
} }
async function parseMinified(dir) {
const pdfFile = fs.readFileSync(dir + "build/pdf.mjs").toString();
const pdfWorkerFile = fs
.readFileSync(dir + "build/pdf.worker.mjs")
.toString();
const pdfSandboxFile = fs
.readFileSync(dir + "build/pdf.sandbox.mjs")
.toString();
const pdfImageDecodersFile = fs
.readFileSync(dir + "image_decoders/pdf.image_decoders.mjs")
.toString();
console.log();
console.log("### Minifying js files");
const { minify } = await import("terser");
const options = {
compress: {
// V8 chokes on very long sequences, work around that.
sequences: false,
},
keep_classnames: true,
keep_fnames: true,
module: true,
};
fs.writeFileSync(
dir + "build/pdf.min.mjs",
(await minify(pdfFile, options)).code
);
fs.writeFileSync(
dir + "build/pdf.worker.min.mjs",
(await minify(pdfWorkerFile, options)).code
);
fs.writeFileSync(
dir + "build/pdf.sandbox.min.mjs",
(await minify(pdfSandboxFile, options)).code
);
fs.writeFileSync(
dir + "image_decoders/pdf.image_decoders.min.mjs",
(await minify(pdfImageDecodersFile, options)).code
);
console.log();
console.log("### Cleaning js files");
fs.unlinkSync(dir + "build/pdf.mjs");
fs.unlinkSync(dir + "build/pdf.worker.mjs");
fs.unlinkSync(dir + "build/pdf.sandbox.mjs");
fs.renameSync(dir + "build/pdf.min.mjs", dir + "build/pdf.mjs");
fs.renameSync(dir + "build/pdf.worker.min.mjs", dir + "build/pdf.worker.mjs");
fs.renameSync(
dir + "build/pdf.sandbox.min.mjs",
dir + "build/pdf.sandbox.mjs"
);
fs.renameSync(
dir + "image_decoders/pdf.image_decoders.min.mjs",
dir + "image_decoders/pdf.image_decoders.mjs"
);
}
gulp.task( gulp.task(
"minified", "minified",
gulp.series( gulp.series(
@ -1252,10 +1239,6 @@ gulp.task(
const defines = { ...DEFINES, MINIFIED: true, GENERIC: true }; const defines = { ...DEFINES, MINIFIED: true, GENERIC: true };
return buildMinified(defines, MINIFIED_DIR); return buildMinified(defines, MINIFIED_DIR);
},
async function compressMinified(done) {
await parseMinified(MINIFIED_DIR);
done();
} }
) )
); );
@ -1291,10 +1274,6 @@ gulp.task(
}; };
return buildMinified(defines, MINIFIED_LEGACY_DIR); return buildMinified(defines, MINIFIED_LEGACY_DIR);
},
async function compressMinifiedLegacy(done) {
await parseMinified(MINIFIED_LEGACY_DIR);
done();
} }
) )
); );
@ -1552,26 +1531,14 @@ gulp.task("types", function (done) {
}); });
function buildLibHelper(bundleDefines, inputStream, outputDir) { function buildLibHelper(bundleDefines, inputStream, outputDir) {
function babelPluginReplaceNonWebpackImport(b) {
return {
visitor: {
Identifier(curPath, state) {
if (curPath.node.name === "__non_webpack_import__") {
curPath.replaceWith(b.types.identifier("import"));
}
},
},
};
}
function preprocessLib(content) { function preprocessLib(content) {
const skipBabel = bundleDefines.SKIP_BABEL; const skipBabel = bundleDefines.SKIP_BABEL;
content = preprocessPDFJSCode(ctx, content);
content = babel.transform(content, { content = babel.transform(content, {
sourceType: "module", sourceType: "module",
presets: skipBabel presets: skipBabel
? undefined ? undefined
: [["@babel/preset-env", { loose: false, modules: false }]], : [["@babel/preset-env", { loose: false, modules: false }]],
plugins: [babelPluginReplaceNonWebpackImport], plugins: [[babelPluginPDFJSPreprocessor, ctx]],
targets: BABEL_TARGETS, targets: BABEL_TARGETS,
}).code; }).code;
content = content.replaceAll( content = content.replaceAll(
@ -1582,7 +1549,6 @@ function buildLibHelper(bundleDefines, inputStream, outputDir) {
} }
const ctx = { const ctx = {
rootPath: __dirname, rootPath: __dirname,
saveComments: false,
defines: bundleDefines, defines: bundleDefines,
map: { map: {
"pdfjs-lib": "../pdf.js", "pdfjs-lib": "../pdf.js",
@ -1592,7 +1558,7 @@ function buildLibHelper(bundleDefines, inputStream, outputDir) {
"display-node_utils": "./node_utils.js", "display-node_utils": "./node_utils.js",
"fluent-bundle": "../../../node_modules/@fluent/bundle/esm/index.js", "fluent-bundle": "../../../node_modules/@fluent/bundle/esm/index.js",
"fluent-dom": "../../../node_modules/@fluent/dom/esm/index.js", "fluent-dom": "../../../node_modules/@fluent/dom/esm/index.js",
"web-l10n_utils": "../web/l10n_utils.js", "web-null_l10n": "../web/genericl10n.js",
}, },
}; };
const licenseHeaderLibre = fs const licenseHeaderLibre = fs
@ -1936,7 +1902,7 @@ gulp.task(
gulp.task("lint", function (done) { gulp.task("lint", function (done) {
console.log(); console.log();
console.log("### Linting JS/CSS files"); console.log("### Linting JS/CSS/JSON files");
// Ensure that we lint the Firefox specific *.jsm files too. // Ensure that we lint the Firefox specific *.jsm files too.
const esLintOptions = [ const esLintOptions = [
@ -1959,6 +1925,16 @@ gulp.task("lint", function (done) {
styleLintOptions.push("--fix"); styleLintOptions.push("--fix");
} }
const prettierOptions = [
"node_modules/prettier/bin/prettier.cjs",
"**/*.json",
];
if (process.argv.includes("--fix")) {
prettierOptions.push("--log-level", "silent", "--write");
} else {
prettierOptions.push("--log-level", "warn", "--check");
}
const esLintProcess = startNode(esLintOptions, { stdio: "inherit" }); const esLintProcess = startNode(esLintOptions, { stdio: "inherit" });
esLintProcess.on("close", function (esLintCode) { esLintProcess.on("close", function (esLintCode) {
if (esLintCode !== 0) { if (esLintCode !== 0) {
@ -1972,8 +1948,16 @@ gulp.task("lint", function (done) {
done(new Error("Stylelint failed.")); done(new Error("Stylelint failed."));
return; return;
} }
console.log("files checked, no errors found");
done(); const prettierProcess = startNode(prettierOptions, { stdio: "inherit" });
prettierProcess.on("close", function (prettierCode) {
if (prettierCode !== 0) {
done(new Error("Prettier failed."));
return;
}
console.log("files checked, no errors found");
done();
});
}); });
}); });
}); });
@ -2063,8 +2047,7 @@ gulp.task(
console.log("### Starting local server"); console.log("### Starting local server");
const { WebServer } = await import("./test/webserver.mjs"); const { WebServer } = await import("./test/webserver.mjs");
const server = new WebServer(); const server = new WebServer({ port: 8888 });
server.port = 8888;
server.start(); server.start();
} }
) )
@ -2245,36 +2228,20 @@ gulp.task(
]) ])
.pipe(gulp.dest(DIST_DIR + "legacy/build/")), .pipe(gulp.dest(DIST_DIR + "legacy/build/")),
gulp gulp
.src(MINIFIED_DIR + "build/pdf.mjs") .src(MINIFIED_DIR + "build/{pdf,pdf.worker,pdf.sandbox}.min.mjs")
.pipe(rename("pdf.min.mjs"))
.pipe(gulp.dest(DIST_DIR + "build/")), .pipe(gulp.dest(DIST_DIR + "build/")),
gulp gulp
.src(MINIFIED_DIR + "build/pdf.worker.mjs") .src(MINIFIED_DIR + "image_decoders/pdf.image_decoders.min.mjs")
.pipe(rename("pdf.worker.min.mjs"))
.pipe(gulp.dest(DIST_DIR + "build/")),
gulp
.src(MINIFIED_DIR + "build/pdf.sandbox.mjs")
.pipe(rename("pdf.sandbox.min.mjs"))
.pipe(gulp.dest(DIST_DIR + "build/")),
gulp
.src(MINIFIED_DIR + "image_decoders/pdf.image_decoders.mjs")
.pipe(rename("pdf.image_decoders.min.mjs"))
.pipe(gulp.dest(DIST_DIR + "image_decoders/")), .pipe(gulp.dest(DIST_DIR + "image_decoders/")),
gulp gulp
.src(MINIFIED_LEGACY_DIR + "build/pdf.mjs") .src(
.pipe(rename("pdf.min.mjs")) MINIFIED_LEGACY_DIR + "build/{pdf,pdf.worker,pdf.sandbox}.min.mjs"
)
.pipe(gulp.dest(DIST_DIR + "legacy/build/")), .pipe(gulp.dest(DIST_DIR + "legacy/build/")),
gulp gulp
.src(MINIFIED_LEGACY_DIR + "build/pdf.worker.mjs") .src(
.pipe(rename("pdf.worker.min.mjs")) MINIFIED_LEGACY_DIR + "image_decoders/pdf.image_decoders.min.mjs"
.pipe(gulp.dest(DIST_DIR + "legacy/build/")), )
gulp
.src(MINIFIED_LEGACY_DIR + "build/pdf.sandbox.mjs")
.pipe(rename("pdf.sandbox.min.mjs"))
.pipe(gulp.dest(DIST_DIR + "legacy/build/")),
gulp
.src(MINIFIED_LEGACY_DIR + "image_decoders/pdf.image_decoders.mjs")
.pipe(rename("pdf.image_decoders.min.mjs"))
.pipe(gulp.dest(DIST_DIR + "legacy/image_decoders/")), .pipe(gulp.dest(DIST_DIR + "legacy/image_decoders/")),
gulp gulp
.src(COMPONENTS_DIR + "**/*", { base: COMPONENTS_DIR }) .src(COMPONENTS_DIR + "**/*", { base: COMPONENTS_DIR })

View File

@ -39,9 +39,24 @@ pdfjs-open-file-button-label = افتح
pdfjs-print-button = pdfjs-print-button =
.title = اطبع .title = اطبع
pdfjs-print-button-label = اطبع 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 = pdfjs-bookmark-button =
.title = الصفحة الحالية (عرض URL من الصفحة الحالية) .title = الصفحة الحالية (عرض URL من الصفحة الحالية)
pdfjs-bookmark-button-label = الصفحة الحالية pdfjs-bookmark-button-label = الصفحة الحالية
# Used in Firefox for Android.
pdfjs-open-in-app-button =
.title = افتح في تطبيق
# Used in Firefox for Android.
# Length of the translation matters since we are in a mobile context, with limited screen estate.
pdfjs-open-in-app-button-label = افتح في تطبيق
## Secondary toolbar and context menu ## Secondary toolbar and context menu
@ -201,6 +216,7 @@ pdfjs-find-next-button =
pdfjs-find-next-button-label = التالي pdfjs-find-next-button-label = التالي
pdfjs-find-highlight-checkbox = أبرِز الكل pdfjs-find-highlight-checkbox = أبرِز الكل
pdfjs-find-match-case-checkbox-label = طابق حالة الأحرف pdfjs-find-match-case-checkbox-label = طابق حالة الأحرف
pdfjs-find-match-diacritics-checkbox-label = طابِق الحركات
pdfjs-find-entire-word-checkbox-label = كلمات كاملة pdfjs-find-entire-word-checkbox-label = كلمات كاملة
pdfjs-find-reached-top = تابعت من الأسفل بعدما وصلت إلى بداية المستند pdfjs-find-reached-top = تابعت من الأسفل بعدما وصلت إلى بداية المستند
pdfjs-find-reached-bottom = تابعت من الأعلى بعدما وصلت إلى نهاية المستند pdfjs-find-reached-bottom = تابعت من الأعلى بعدما وصلت إلى نهاية المستند
@ -256,9 +272,18 @@ pdfjs-web-fonts-disabled = خطوط الوب مُعطّلة: تعذّر استخ
## Editing ## Editing
## Remove button for the various kind of editor.
##
## Alt-text dialog ## Alt-text dialog
## Editor resizers ## Editor resizers
## This is used in an aria label to help to understand the role of the resizer. ## This is used in an aria label to help to understand the role of the resizer.
## Color picker

View File

@ -303,8 +303,9 @@ pdfjs-editor-ink-button-label = Маляваць
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Дадаць або змяніць выявы .title = Дадаць або змяніць выявы
pdfjs-editor-stamp-button-label = Дадаць або змяніць выявы pdfjs-editor-stamp-button-label = Дадаць або змяніць выявы
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Выдаліць .title = Вылучэнне
pdfjs-editor-highlight-button-label = Вылучэнне
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -328,6 +329,10 @@ pdfjs-editor-ink-opacity-input = Непразрыстасць
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Дадаць выяву .title = Дадаць выяву
pdfjs-editor-stamp-add-image-button-label = Дадаць выяву pdfjs-editor-stamp-add-image-button-label = Дадаць выяву
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Таўшчыня
pdfjs-editor-free-highlight-thickness-title =
.title = Змяняць таўшчыню пры вылучэнні іншых элементаў, акрамя тэксту
pdfjs-free-text = pdfjs-free-text =
.aria-label = Тэкставы рэдактар .aria-label = Тэкставы рэдактар
pdfjs-free-text-default-content = Пачніце набор тэксту… pdfjs-free-text-default-content = Пачніце набор тэксту…

View File

@ -39,6 +39,24 @@ pdfjs-open-file-button-label = Отваряне
pdfjs-print-button = pdfjs-print-button =
.title = Отпечатване .title = Отпечатване
pdfjs-print-button-label = Отпечатване 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 =
.title = Текуща страница (преглед на адреса на страницата)
pdfjs-bookmark-button-label = Текуща страница
# Used in Firefox for Android.
pdfjs-open-in-app-button =
.title = Отваряне в приложение
# Used in Firefox for Android.
# Length of the translation matters since we are in a mobile context, with limited screen estate.
pdfjs-open-in-app-button-label = Отваряне в приложение
## Secondary toolbar and context menu ## Secondary toolbar and context menu
@ -63,6 +81,9 @@ pdfjs-cursor-text-select-tool-button-label = Инструмент за избо
pdfjs-cursor-hand-tool-button = pdfjs-cursor-hand-tool-button =
.title = Включване на инструмента ръка .title = Включване на инструмента ръка
pdfjs-cursor-hand-tool-button-label = Инструмент ръка pdfjs-cursor-hand-tool-button-label = Инструмент ръка
pdfjs-scroll-page-button =
.title = Използване на плъзгане на страници
pdfjs-scroll-page-button-label = Плъзгане на страници
pdfjs-scroll-vertical-button = pdfjs-scroll-vertical-button =
.title = Използване на вертикално плъзгане .title = Използване на вертикално плъзгане
pdfjs-scroll-vertical-button-label = Вертикално плъзгане pdfjs-scroll-vertical-button-label = Вертикално плъзгане
@ -154,6 +175,8 @@ pdfjs-printing-not-ready = Внимание: Този PDF файл не е на
pdfjs-toggle-sidebar-button = pdfjs-toggle-sidebar-button =
.title = Превключване на страничната лента .title = Превключване на страничната лента
pdfjs-toggle-sidebar-notification-button =
.title = Превключване на страничната лента (документът има структура/прикачени файлове/слоеве)
pdfjs-toggle-sidebar-button-label = Превключване на страничната лента pdfjs-toggle-sidebar-button-label = Превключване на страничната лента
pdfjs-document-outline-button = pdfjs-document-outline-button =
.title = Показване на структурата на документа (двукратно щракване за свиване/разгъване на всичко) .title = Показване на структурата на документа (двукратно щракване за свиване/разгъване на всичко)
@ -161,12 +184,19 @@ pdfjs-document-outline-button-label = Структура на документа
pdfjs-attachments-button = pdfjs-attachments-button =
.title = Показване на притурките .title = Показване на притурките
pdfjs-attachments-button-label = Притурки pdfjs-attachments-button-label = Притурки
pdfjs-layers-button =
.title = Показване на слоевете (двукратно щракване за възстановяване на всички слоеве към състоянието по подразбиране)
pdfjs-layers-button-label = Слоеве
pdfjs-thumbs-button = pdfjs-thumbs-button =
.title = Показване на миниатюрите .title = Показване на миниатюрите
pdfjs-thumbs-button-label = Миниатюри pdfjs-thumbs-button-label = Миниатюри
pdfjs-current-outline-item-button =
.title = Намиране на текущия елемент от структурата
pdfjs-current-outline-item-button-label = Текущ елемент от структурата
pdfjs-findbar-button = pdfjs-findbar-button =
.title = Намиране в документа .title = Намиране в документа
pdfjs-findbar-button-label = Търсене pdfjs-findbar-button-label = Търсене
pdfjs-additional-layers = Допълнителни слоеве
## Thumbnails panel item (tooltip and alt text for images) ## Thumbnails panel item (tooltip and alt text for images)
@ -192,9 +222,25 @@ pdfjs-find-next-button =
pdfjs-find-next-button-label = Следваща pdfjs-find-next-button-label = Следваща
pdfjs-find-highlight-checkbox = Открояване на всички pdfjs-find-highlight-checkbox = Открояване на всички
pdfjs-find-match-case-checkbox-label = Съвпадение на регистъра pdfjs-find-match-case-checkbox-label = Съвпадение на регистъра
pdfjs-find-match-diacritics-checkbox-label = Без производни букви
pdfjs-find-entire-word-checkbox-label = Цели думи pdfjs-find-entire-word-checkbox-label = Цели думи
pdfjs-find-reached-top = Достигнато е началото на документа, продължаване от края pdfjs-find-reached-top = Достигнато е началото на документа, продължаване от края
pdfjs-find-reached-bottom = Достигнат е краят на документа, продължаване от началото pdfjs-find-reached-bottom = Достигнат е краят на документа, продължаване от началото
# 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 } от { $total } съвпадение
*[other] { $current } от { $total } съвпадения
}
# Variables:
# $limit (Number) - the maximum number of matches
pdfjs-find-match-count-limit =
{ $limit ->
[one] Повече от { $limit } съвпадение
*[other] Повече от { $limit } съвпадения
}
pdfjs-find-not-found = Фразата не е намерена pdfjs-find-not-found = Фразата не е намерена
## Predefined zoom values ## Predefined zoom values
@ -209,6 +255,10 @@ pdfjs-page-scale-percent = { $scale }%
## PDF page ## PDF page
# Variables:
# $page (Number) - the page number
pdfjs-page-landmark =
.aria-label = Страница { $page }
## Loading indicator messages ## Loading indicator messages
@ -220,6 +270,10 @@ pdfjs-rendering-error = Грешка при изчертаване на стра
## Annotations ## Annotations
# Variables:
# $date (Date) - the modification date of the annotation
# $time (Time) - the modification time of the annotation
pdfjs-annotation-date-string = { $date }, { $time }
# .alt: This is used as a tooltip. # .alt: This is used as a tooltip.
# Variables: # Variables:
# $type (String) - an annotation type from a list defined in the PDF spec # $type (String) - an annotation type from a list defined in the PDF spec
@ -238,10 +292,93 @@ pdfjs-web-fonts-disabled = Уеб-шрифтовете са забранени:
## Editing ## 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 = Добавяне или променяне на изображения
pdfjs-editor-remove-button =
.title = Премахване
## Remove button for the various kind of editor.
pdfjs-editor-remove-ink-button =
.title = Премахване на рисунката
pdfjs-editor-remove-freetext-button =
.title = Премахване на текста
pdfjs-editor-remove-stamp-button =
.title = Пермахване на изображението
pdfjs-editor-remove-highlight-button =
.title = Премахване на открояването
##
# 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 = Прозрачност
pdfjs-editor-stamp-add-image-button =
.title = Добавяне на изображение
pdfjs-editor-stamp-add-image-button-label = Добавяне на изображение
pdfjs-free-text =
.aria-label = Текстов редактор
pdfjs-free-text-default-content = Започнете да пишете…
pdfjs-ink =
.aria-label = Промяна на рисунка
pdfjs-ink-canvas =
.aria-label = Изображение, създадено от потребител
## Alt-text dialog ## Alt-text dialog
# Alternative text (alt text) helps when people can't see the image.
pdfjs-editor-alt-text-button-label = Алтернативен текст
pdfjs-editor-alt-text-edit-button-label = Промяна на алтернативния текст
pdfjs-editor-alt-text-dialog-label = Изберете от възможностите
pdfjs-editor-alt-text-dialog-description = Алтернативният текст помага на потребителите, когато не могат да видят изображението или то не се зарежда.
pdfjs-editor-alt-text-add-description-label = Добавяне на описание
pdfjs-editor-alt-text-add-description-description = Стремете се към 1-2 изречения, описващи предмета, настройката или действията.
pdfjs-editor-alt-text-mark-decorative-label = Отбелязване като декоративно
pdfjs-editor-alt-text-mark-decorative-description = Използва се за орнаменти или декоративни изображения, като контури и водни знаци.
pdfjs-editor-alt-text-cancel-button = Отказ
pdfjs-editor-alt-text-save-button = Запазване
pdfjs-editor-alt-text-decorative-tooltip = Отбелязване като декоративно
# .placeholder: This is a placeholder for the alt text input area
pdfjs-editor-alt-text-textarea =
.placeholder = Например, „Млад мъж седи на маса и се храни“
## Editor resizers ## Editor resizers
## This is used in an aria label to help to understand the role of the resizer. ## This is used in an aria label to help to understand the role of the resizer.
pdfjs-editor-resizer-label-top-left = Горен ляв ъгъл — преоразмеряване
pdfjs-editor-resizer-label-top-middle = Горе в средата — преоразмеряване
pdfjs-editor-resizer-label-top-right = Горен десен ъгъл — преоразмеряване
pdfjs-editor-resizer-label-middle-right = Дясно в средата — преоразмеряване
pdfjs-editor-resizer-label-bottom-right = Долен десен ъгъл — преоразмеряване
pdfjs-editor-resizer-label-bottom-middle = Долу в средата — преоразмеряване
pdfjs-editor-resizer-label-bottom-left = Долен ляв ъгъл — преоразмеряване
pdfjs-editor-resizer-label-middle-left = Ляво в средата — преоразмеряване
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = Цвят на открояване
pdfjs-editor-colorpicker-button =
.title = Промяна на цвят
pdfjs-editor-colorpicker-dropdown =
.aria-label = Избор на цвят
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 = Червено

View File

@ -48,6 +48,13 @@ pdfjs-download-button =
# Used in Firefox for Android as a label for the download button (“download” is a verb). # 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. # Length of the translation matters since we are in a mobile context, with limited screen estate.
pdfjs-download-button-label = Pellgargañ pdfjs-download-button-label = Pellgargañ
pdfjs-bookmark-button-label = Pajenn a-vremañ
# Used in Firefox for Android.
pdfjs-open-in-app-button =
.title = Digeriñ en arload
# Used in Firefox for Android.
# Length of the translation matters since we are in a mobile context, with limited screen estate.
pdfjs-open-in-app-button-label = Digeriñ en arload
## Secondary toolbar and context menu ## Secondary toolbar and context menu
@ -267,6 +274,9 @@ pdfjs-editor-free-text-button-label = Testenn
pdfjs-editor-ink-button = pdfjs-editor-ink-button =
.title = Tresañ .title = Tresañ
pdfjs-editor-ink-button-label = Tresañ pdfjs-editor-ink-button-label = Tresañ
pdfjs-editor-stamp-button =
.title = Ouzhpennañ pe aozañ skeudennoù
pdfjs-editor-stamp-button-label = Ouzhpennañ pe aozañ skeudennoù
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -277,9 +287,21 @@ pdfjs-editor-ink-button-label = Tresañ
pdfjs-editor-free-text-color-input = Liv pdfjs-editor-free-text-color-input = Liv
pdfjs-editor-free-text-size-input = Ment pdfjs-editor-free-text-size-input = Ment
pdfjs-editor-ink-color-input = Liv pdfjs-editor-ink-color-input = Liv
pdfjs-editor-ink-thickness-input = Tevder
pdfjs-editor-ink-opacity-input = Boullder
pdfjs-editor-stamp-add-image-button =
.title = Ouzhpennañ ur skeudenn
pdfjs-editor-stamp-add-image-button-label = Ouzhpennañ ur skeudenn
pdfjs-free-text =
.aria-label = Aozer testennoù
pdfjs-ink =
.aria-label = Aozer tresoù
pdfjs-ink-canvas =
.aria-label = Skeudenn bet krouet gant an implijer·ez
## Alt-text dialog ## Alt-text dialog
pdfjs-editor-alt-text-add-description-label = Ouzhpennañ un deskrivadur
pdfjs-editor-alt-text-cancel-button = Nullañ pdfjs-editor-alt-text-cancel-button = Nullañ
pdfjs-editor-alt-text-save-button = Enrollañ pdfjs-editor-alt-text-save-button = Enrollañ

View File

@ -305,8 +305,9 @@ pdfjs-editor-ink-button-label = Kreslení
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Přidání či úprava obrázků .title = Přidání či úprava obrázků
pdfjs-editor-stamp-button-label = Přidání či úprava obrázků pdfjs-editor-stamp-button-label = Přidání či úprava obrázků
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Odebrat .title = Zvýraznění
pdfjs-editor-highlight-button-label = Zvýraznění
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -330,6 +331,10 @@ pdfjs-editor-ink-opacity-input = Průhlednost
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Přidat obrázek .title = Přidat obrázek
pdfjs-editor-stamp-add-image-button-label = Přidat obrázek pdfjs-editor-stamp-add-image-button-label = Přidat obrázek
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Tloušťka
pdfjs-editor-free-highlight-thickness-title =
.title = Změna tloušťky při zvýrazňování jiných položek než textu
pdfjs-free-text = pdfjs-free-text =
.aria-label = Textový editor .aria-label = Textový editor
pdfjs-free-text-default-content = Začněte psát… pdfjs-free-text-default-content = Začněte psát…

View File

@ -23,11 +23,11 @@ pdfjs-of-pages = o { $pagesCount }
# $pagesCount (Number) - the total number of pages in the document # $pagesCount (Number) - the total number of pages in the document
pdfjs-page-of-pages = ({ $pageNumber } o { $pagesCount }) pdfjs-page-of-pages = ({ $pageNumber } o { $pagesCount })
pdfjs-zoom-out-button = pdfjs-zoom-out-button =
.title = Chwyddo Allan .title = Lleihau
pdfjs-zoom-out-button-label = Chwyddo Allan pdfjs-zoom-out-button-label = Lleihau
pdfjs-zoom-in-button = pdfjs-zoom-in-button =
.title = Chwyddo Mewn .title = Cynyddu
pdfjs-zoom-in-button-label = Chwyddo Mewn pdfjs-zoom-in-button-label = Cynyddu
pdfjs-zoom-select = pdfjs-zoom-select =
.title = Chwyddo .title = Chwyddo
pdfjs-presentation-mode-button = pdfjs-presentation-mode-button =
@ -44,10 +44,10 @@ pdfjs-save-button =
pdfjs-save-button-label = Cadw pdfjs-save-button-label = Cadw
# Used in Firefox for Android as a tooltip for the download button (“download” is a verb). # Used in Firefox for Android as a tooltip for the download button (“download” is a verb).
pdfjs-download-button = pdfjs-download-button =
.title = Llwytho i Lawr .title = Llwytho i lawr
# Used in Firefox for Android as a label for the download button (“download” is a verb). # 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. # Length of the translation matters since we are in a mobile context, with limited screen estate.
pdfjs-download-button-label = Llwytho i Lawr pdfjs-download-button-label = Llwytho i lawr
pdfjs-bookmark-button = pdfjs-bookmark-button =
.title = Tudalen Gyfredol (Gweld URL o'r Dudalen Gyfredol) .title = Tudalen Gyfredol (Gweld URL o'r Dudalen Gyfredol)
pdfjs-bookmark-button-label = Tudalen Gyfredol pdfjs-bookmark-button-label = Tudalen Gyfredol
@ -309,8 +309,9 @@ pdfjs-editor-ink-button-label = Lluniadu
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Ychwanegu neu olygu delweddau .title = Ychwanegu neu olygu delweddau
pdfjs-editor-stamp-button-label = Ychwanegu neu olygu delweddau pdfjs-editor-stamp-button-label = Ychwanegu neu olygu delweddau
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Tynnu .title = Amlygu
pdfjs-editor-highlight-button-label = Amlygu
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -334,6 +335,10 @@ pdfjs-editor-ink-opacity-input = Didreiddedd
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Ychwanegu delwedd .title = Ychwanegu delwedd
pdfjs-editor-stamp-add-image-button-label = Ychwanegu delwedd pdfjs-editor-stamp-add-image-button-label = Ychwanegu delwedd
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Trwch
pdfjs-editor-free-highlight-thickness-title =
.title = Newid trwch wrth amlygu eitemau heblaw testun
pdfjs-free-text = pdfjs-free-text =
.aria-label = Golygydd Testun .aria-label = Golygydd Testun
pdfjs-free-text-default-content = Cychwyn teipio… pdfjs-free-text-default-content = Cychwyn teipio…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Tegn
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Tilføj eller rediger billeder .title = Tilføj eller rediger billeder
pdfjs-editor-stamp-button-label = Tilføj eller rediger billeder pdfjs-editor-stamp-button-label = Tilføj eller rediger billeder
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Fjern .title = Fremhæv
pdfjs-editor-highlight-button-label = Fremhæv
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -312,6 +313,8 @@ pdfjs-editor-remove-freetext-button =
.title = Fjern tekst .title = Fjern tekst
pdfjs-editor-remove-stamp-button = pdfjs-editor-remove-stamp-button =
.title = Fjern billede .title = Fjern billede
pdfjs-editor-remove-highlight-button =
.title = Fjern fremhævning
## ##
@ -324,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Uigennemsigtighed
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Tilføj billede .title = Tilføj billede
pdfjs-editor-stamp-add-image-button-label = Tilføj billede pdfjs-editor-stamp-add-image-button-label = Tilføj billede
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Tykkelse
pdfjs-editor-free-highlight-thickness-title =
.title = Ændr tykkelse, når andre elementer end tekst fremhæves
pdfjs-free-text = pdfjs-free-text =
.aria-label = Teksteditor .aria-label = Teksteditor
pdfjs-free-text-default-content = Begynd at skrive… pdfjs-free-text-default-content = Begynd at skrive…
@ -361,3 +368,22 @@ pdfjs-editor-resizer-label-bottom-right = Nederste højre hjørne - tilpas stør
pdfjs-editor-resizer-label-bottom-middle = Nederst i midten - tilpas størrelse pdfjs-editor-resizer-label-bottom-middle = Nederst i midten - tilpas størrelse
pdfjs-editor-resizer-label-bottom-left = Nederste venstre hjørne - tilpas størrelse pdfjs-editor-resizer-label-bottom-left = Nederste venstre hjørne - tilpas størrelse
pdfjs-editor-resizer-label-middle-left = Midten til venstre — tilpas størrelse pdfjs-editor-resizer-label-middle-left = Midten til venstre — tilpas størrelse
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = Fremhævningsfarve
pdfjs-editor-colorpicker-button =
.title = Skift farve
pdfjs-editor-colorpicker-dropdown =
.aria-label = Farvevalg
pdfjs-editor-colorpicker-yellow =
.title = Gul
pdfjs-editor-colorpicker-green =
.title = Grøn
pdfjs-editor-colorpicker-blue =
.title = Blå
pdfjs-editor-colorpicker-pink =
.title = Lyserød
pdfjs-editor-colorpicker-red =
.title = Rød

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Zeichnen
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Grafiken hinzufügen oder bearbeiten .title = Grafiken hinzufügen oder bearbeiten
pdfjs-editor-stamp-button-label = Grafiken hinzufügen oder bearbeiten pdfjs-editor-stamp-button-label = Grafiken hinzufügen oder bearbeiten
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Entfernen .title = Hervorheben
pdfjs-editor-highlight-button-label = Hervorheben
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -321,11 +322,15 @@ pdfjs-editor-remove-highlight-button =
pdfjs-editor-free-text-color-input = Farbe pdfjs-editor-free-text-color-input = Farbe
pdfjs-editor-free-text-size-input = Größe pdfjs-editor-free-text-size-input = Größe
pdfjs-editor-ink-color-input = Farbe pdfjs-editor-ink-color-input = Farbe
pdfjs-editor-ink-thickness-input = Dicke pdfjs-editor-ink-thickness-input = Linienstärke
pdfjs-editor-ink-opacity-input = Deckkraft pdfjs-editor-ink-opacity-input = Deckkraft
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Grafik hinzufügen .title = Grafik hinzufügen
pdfjs-editor-stamp-add-image-button-label = Grafik hinzufügen pdfjs-editor-stamp-add-image-button-label = Grafik hinzufügen
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Linienstärke
pdfjs-editor-free-highlight-thickness-title =
.title = Linienstärke beim Hervorheben anderer Elemente als Text ändern
pdfjs-free-text = pdfjs-free-text =
.aria-label = Texteditor .aria-label = Texteditor
pdfjs-free-text-default-content = Schreiben beginnen… pdfjs-free-text-default-content = Schreiben beginnen…

View File

@ -305,8 +305,9 @@ pdfjs-editor-ink-button-label = Kresliś
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Wobraze pśidaś abo wobźěłaś .title = Wobraze pśidaś abo wobźěłaś
pdfjs-editor-stamp-button-label = Wobraze pśidaś abo wobźěłaś pdfjs-editor-stamp-button-label = Wobraze pśidaś abo wobźěłaś
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Wótwónoźeś .title = Wuzwignuś
pdfjs-editor-highlight-button-label = Wuzwignuś
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -330,6 +331,10 @@ pdfjs-editor-ink-opacity-input = Opacita
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Wobraz pśidaś .title = Wobraz pśidaś
pdfjs-editor-stamp-add-image-button-label = Wobraz pśidaś pdfjs-editor-stamp-add-image-button-label = Wobraz pśidaś
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Tłustosć
pdfjs-editor-free-highlight-thickness-title =
.title = Tłustosć změniś, gaž se zapiski wuzwiguju, kótarež tekst njejsu
pdfjs-free-text = pdfjs-free-text =
.aria-label = Tekstowy editor .aria-label = Tekstowy editor
pdfjs-free-text-default-content = Zachopśo pisaś… pdfjs-free-text-default-content = Zachopśo pisaś…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Σχέδιο
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Προσθήκη ή επεξεργασία εικόνων .title = Προσθήκη ή επεξεργασία εικόνων
pdfjs-editor-stamp-button-label = Προσθήκη ή επεξεργασία εικόνων pdfjs-editor-stamp-button-label = Προσθήκη ή επεξεργασία εικόνων
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Αφαίρεση .title = Επισήμανση
pdfjs-editor-highlight-button-label = Επισήμανση
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Αδιαφάνεια
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Προσθήκη εικόνας .title = Προσθήκη εικόνας
pdfjs-editor-stamp-add-image-button-label = Προσθήκη εικόνας pdfjs-editor-stamp-add-image-button-label = Προσθήκη εικόνας
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Πάχος
pdfjs-editor-free-highlight-thickness-title =
.title = Αλλαγή πάχους κατά την επισήμανση στοιχείων εκτός κειμένου
pdfjs-free-text = pdfjs-free-text =
.aria-label = Επεξεργασία κειμένου .aria-label = Επεξεργασία κειμένου
pdfjs-free-text-default-content = Ξεκινήστε να πληκτρολογείτε… pdfjs-free-text-default-content = Ξεκινήστε να πληκτρολογείτε…

View File

@ -286,6 +286,12 @@ pdfjs-editor-ink-button-label = Draw
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Add or edit images .title = Add or edit images
pdfjs-editor-stamp-button-label = Add or edit images pdfjs-editor-stamp-button-label = Add or edit images
## Remove button for the various kind of editor.
##
# Editor Parameters # Editor Parameters
pdfjs-editor-free-text-color-input = Colour pdfjs-editor-free-text-color-input = Colour
pdfjs-editor-free-text-size-input = Size pdfjs-editor-free-text-size-input = Size
@ -309,3 +315,22 @@ pdfjs-ink-canvas =
## Editor resizers ## Editor resizers
## This is used in an aria label to help to understand the role of the resizer. ## This is used in an aria label to help to understand the role of the resizer.
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = Highlight colour
pdfjs-editor-colorpicker-button =
.title = Change colour
pdfjs-editor-colorpicker-dropdown =
.aria-label = Colour choices
pdfjs-editor-colorpicker-yellow =
.title = Yellow
pdfjs-editor-colorpicker-green =
.title = Green
pdfjs-editor-colorpicker-blue =
.title = Blue
pdfjs-editor-colorpicker-pink =
.title = Pink
pdfjs-editor-colorpicker-red =
.title = Red

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Draw
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Add or edit images .title = Add or edit images
pdfjs-editor-stamp-button-label = Add or edit images pdfjs-editor-stamp-button-label = Add or edit images
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Remove .title = Highlight
pdfjs-editor-highlight-button-label = Highlight
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opacity
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Add image .title = Add image
pdfjs-editor-stamp-add-image-button-label = Add image pdfjs-editor-stamp-add-image-button-label = Add image
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Thickness
pdfjs-editor-free-highlight-thickness-title =
.title = Change thickness when highlighting items other than text
pdfjs-free-text = pdfjs-free-text =
.aria-label = Text Editor .aria-label = Text Editor
pdfjs-free-text-default-content = Start typing… pdfjs-free-text-default-content = Start typing…

View File

@ -58,14 +58,6 @@ pdfjs-bookmark-button =
.title = Current Page (View URL from Current Page) .title = Current Page (View URL from Current Page)
pdfjs-bookmark-button-label = Current Page pdfjs-bookmark-button-label = Current Page
# Used in Firefox for Android.
pdfjs-open-in-app-button =
.title = Open in app
# Used in Firefox for Android.
# Length of the translation matters since we are in a mobile context, with limited screen estate.
pdfjs-open-in-app-button-label = Open in app
## Secondary toolbar and context menu ## Secondary toolbar and context menu
pdfjs-tools-button = pdfjs-tools-button =
@ -326,6 +318,8 @@ pdfjs-editor-stamp-button-label = Add or edit images
pdfjs-editor-highlight-button = pdfjs-editor-highlight-button =
.title = Highlight .title = Highlight
pdfjs-editor-highlight-button-label = Highlight pdfjs-editor-highlight-button-label = Highlight
pdfjs-highlight-floating-button =
.title = Highlight
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -349,6 +343,10 @@ pdfjs-editor-ink-opacity-input = Opacity
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Add image .title = Add image
pdfjs-editor-stamp-add-image-button-label = Add image pdfjs-editor-stamp-add-image-button-label = Add image
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Thickness
pdfjs-editor-free-highlight-thickness-title =
.title = Change thickness when highlighting items other than text
pdfjs-free-text = pdfjs-free-text =
.aria-label = Text Editor .aria-label = Text Editor
@ -409,3 +407,10 @@ pdfjs-editor-colorpicker-pink =
.title = Pink .title = Pink
pdfjs-editor-colorpicker-red = pdfjs-editor-colorpicker-red =
.title = Red .title = Red
## Show all highlights
## This is a toggle button to show/hide all the highlights.
pdfjs-editor-highlight-show-all-button-label = Show all
pdfjs-editor-highlight-show-all-button =
.title = Show all

View File

@ -301,6 +301,23 @@ pdfjs-editor-ink-button-label = Desegni
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Aldoni aŭ modifi bildojn .title = Aldoni aŭ modifi bildojn
pdfjs-editor-stamp-button-label = Aldoni aŭ modifi bildojn pdfjs-editor-stamp-button-label = Aldoni aŭ modifi bildojn
pdfjs-editor-highlight-button =
.title = Elstarigi
pdfjs-editor-highlight-button-label = Elstarigi
## Remove button for the various kind of editor.
pdfjs-editor-remove-ink-button =
.title = Forigi desegnon
pdfjs-editor-remove-freetext-button =
.title = Forigi tekston
pdfjs-editor-remove-stamp-button =
.title = Forigi bildon
pdfjs-editor-remove-highlight-button =
.title = Forigi elstaraĵon
##
# Editor Parameters # Editor Parameters
pdfjs-editor-free-text-color-input = Koloro pdfjs-editor-free-text-color-input = Koloro
pdfjs-editor-free-text-size-input = Grando pdfjs-editor-free-text-size-input = Grando
@ -310,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Maldiafaneco
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Aldoni bildon .title = Aldoni bildon
pdfjs-editor-stamp-add-image-button-label = Aldoni bildon pdfjs-editor-stamp-add-image-button-label = Aldoni bildon
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Dikeco
pdfjs-editor-free-highlight-thickness-title =
.title = Ŝanĝi dikecon dum elstarigo de netekstaj elementoj
pdfjs-free-text = pdfjs-free-text =
.aria-label = Tekstan redaktilon .aria-label = Tekstan redaktilon
pdfjs-free-text-default-content = Ektajpi… pdfjs-free-text-default-content = Ektajpi…
@ -347,3 +368,22 @@ pdfjs-editor-resizer-label-bottom-right = Malsupra deksta angulo — ŝanĝi gra
pdfjs-editor-resizer-label-bottom-middle = Malsupra mezo — ŝanĝi grandon pdfjs-editor-resizer-label-bottom-middle = Malsupra mezo — ŝanĝi grandon
pdfjs-editor-resizer-label-bottom-left = Malsupra maldekstra angulo — ŝanĝi grandon pdfjs-editor-resizer-label-bottom-left = Malsupra maldekstra angulo — ŝanĝi grandon
pdfjs-editor-resizer-label-middle-left = Maldekstra mezo — ŝanĝi grandon pdfjs-editor-resizer-label-middle-left = Maldekstra mezo — ŝanĝi grandon
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = Elstarigi koloron
pdfjs-editor-colorpicker-button =
.title = Ŝanĝi koloron
pdfjs-editor-colorpicker-dropdown =
.aria-label = Elekto de koloroj
pdfjs-editor-colorpicker-yellow =
.title = Flava
pdfjs-editor-colorpicker-green =
.title = Verda
pdfjs-editor-colorpicker-blue =
.title = Blua
pdfjs-editor-colorpicker-pink =
.title = Roza
pdfjs-editor-colorpicker-red =
.title = Ruĝa

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Dibujar
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Agregar o editar imágenes .title = Agregar o editar imágenes
pdfjs-editor-stamp-button-label = Agregar o editar imágenes pdfjs-editor-stamp-button-label = Agregar o editar imágenes
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Eliminar .title = Resaltar
pdfjs-editor-highlight-button-label = Resaltar
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opacidad
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Agregar una imagen .title = Agregar una imagen
pdfjs-editor-stamp-add-image-button-label = Agregar una imagen pdfjs-editor-stamp-add-image-button-label = Agregar una imagen
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Grosor
pdfjs-editor-free-highlight-thickness-title =
.title = Cambiar el grosor al resaltar elementos que no sean texto
pdfjs-free-text = pdfjs-free-text =
.aria-label = Editor de texto .aria-label = Editor de texto
pdfjs-free-text-default-content = Empezar a tipear… pdfjs-free-text-default-content = Empezar a tipear…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Dibujar
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Añadir o editar imágenes .title = Añadir o editar imágenes
pdfjs-editor-stamp-button-label = Añadir o editar imágenes pdfjs-editor-stamp-button-label = Añadir o editar imágenes
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Eliminar .title = Destacar
pdfjs-editor-highlight-button-label = Destacar
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opacidad
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Añadir imagen .title = Añadir imagen
pdfjs-editor-stamp-add-image-button-label = Añadir imagen pdfjs-editor-stamp-add-image-button-label = Añadir imagen
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Grosor
pdfjs-editor-free-highlight-thickness-title =
.title = Cambia el grosor al resaltar elementos que no sean texto
pdfjs-free-text = pdfjs-free-text =
.aria-label = Editor de texto .aria-label = Editor de texto
pdfjs-free-text-default-content = Empieza a escribir… pdfjs-free-text-default-content = Empieza a escribir…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Dibujar
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Añadir o editar imágenes .title = Añadir o editar imágenes
pdfjs-editor-stamp-button-label = Añadir o editar imágenes pdfjs-editor-stamp-button-label = Añadir o editar imágenes
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Eliminar .title = Resaltar
pdfjs-editor-highlight-button-label = Resaltar
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opacidad
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Añadir imagen .title = Añadir imagen
pdfjs-editor-stamp-add-image-button-label = Añadir imagen pdfjs-editor-stamp-add-image-button-label = Añadir imagen
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Grosor
pdfjs-editor-free-highlight-thickness-title =
.title = Cambiar el grosor al resaltar elementos que no sean texto
pdfjs-free-text = pdfjs-free-text =
.aria-label = Editor de texto .aria-label = Editor de texto
pdfjs-free-text-default-content = Empezar a escribir… pdfjs-free-text-default-content = Empezar a escribir…

View File

@ -301,6 +301,23 @@ pdfjs-editor-ink-button-label = Marrazkia
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Gehitu edo editatu irudiak .title = Gehitu edo editatu irudiak
pdfjs-editor-stamp-button-label = Gehitu edo editatu irudiak pdfjs-editor-stamp-button-label = Gehitu edo editatu irudiak
pdfjs-editor-highlight-button =
.title = Nabarmendu
pdfjs-editor-highlight-button-label = Nabarmendu
## Remove button for the various kind of editor.
pdfjs-editor-remove-ink-button =
.title = Kendu marrazkia
pdfjs-editor-remove-freetext-button =
.title = Kendu testua
pdfjs-editor-remove-stamp-button =
.title = Kendu irudia
pdfjs-editor-remove-highlight-button =
.title = Kendu nabarmentzea
##
# Editor Parameters # Editor Parameters
pdfjs-editor-free-text-color-input = Kolorea pdfjs-editor-free-text-color-input = Kolorea
pdfjs-editor-free-text-size-input = Tamaina pdfjs-editor-free-text-size-input = Tamaina
@ -310,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opakutasuna
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Gehitu irudia .title = Gehitu irudia
pdfjs-editor-stamp-add-image-button-label = Gehitu irudia pdfjs-editor-stamp-add-image-button-label = Gehitu irudia
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Loditasuna
pdfjs-editor-free-highlight-thickness-title =
.title = Aldatu loditasuna testua ez beste elementuak nabarmentzean
pdfjs-free-text = pdfjs-free-text =
.aria-label = Testu-editorea .aria-label = Testu-editorea
pdfjs-free-text-default-content = Hasi idazten… pdfjs-free-text-default-content = Hasi idazten…
@ -347,3 +368,22 @@ pdfjs-editor-resizer-label-bottom-right = Beheko eskuineko izkina — aldatu tam
pdfjs-editor-resizer-label-bottom-middle = Behean erdian — aldatu tamaina pdfjs-editor-resizer-label-bottom-middle = Behean erdian — aldatu tamaina
pdfjs-editor-resizer-label-bottom-left = Beheko ezkerreko izkina — aldatu tamaina pdfjs-editor-resizer-label-bottom-left = Beheko ezkerreko izkina — aldatu tamaina
pdfjs-editor-resizer-label-middle-left = Erdian ezkerrean — aldatu tamaina pdfjs-editor-resizer-label-middle-left = Erdian ezkerrean — aldatu tamaina
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = Nabarmentze kolorea
pdfjs-editor-colorpicker-button =
.title = Aldatu kolorea
pdfjs-editor-colorpicker-dropdown =
.aria-label = Kolore-aukerak
pdfjs-editor-colorpicker-yellow =
.title = Horia
pdfjs-editor-colorpicker-green =
.title = Berdea
pdfjs-editor-colorpicker-blue =
.title = Urdina
pdfjs-editor-colorpicker-pink =
.title = Arrosa
pdfjs-editor-colorpicker-red =
.title = Gorria

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Piirros
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Lisää tai muokkaa kuvia .title = Lisää tai muokkaa kuvia
pdfjs-editor-stamp-button-label = Lisää tai muokkaa kuvia pdfjs-editor-stamp-button-label = Lisää tai muokkaa kuvia
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Poista .title = Korostus
pdfjs-editor-highlight-button-label = Korostus
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Peittävyys
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Lisää kuva .title = Lisää kuva
pdfjs-editor-stamp-add-image-button-label = Lisää kuva pdfjs-editor-stamp-add-image-button-label = Lisää kuva
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Paksuus
pdfjs-editor-free-highlight-thickness-title =
.title = Muuta paksuutta korostaessasi muita kohteita kuin tekstiä
pdfjs-free-text = pdfjs-free-text =
.aria-label = Tekstimuokkain .aria-label = Tekstimuokkain
pdfjs-free-text-default-content = Aloita kirjoittaminen… pdfjs-free-text-default-content = Aloita kirjoittaminen…

View File

@ -297,8 +297,9 @@ pdfjs-editor-ink-button-label = Dessiner
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Ajouter ou modifier des images .title = Ajouter ou modifier des images
pdfjs-editor-stamp-button-label = Ajouter ou modifier des images pdfjs-editor-stamp-button-label = Ajouter ou modifier des images
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Supprimer .title = Surligner
pdfjs-editor-highlight-button-label = Surligner
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -322,6 +323,8 @@ pdfjs-editor-ink-opacity-input = Opacité
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Ajouter une image .title = Ajouter une image
pdfjs-editor-stamp-add-image-button-label = Ajouter une image pdfjs-editor-stamp-add-image-button-label = Ajouter une image
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Épaisseur
pdfjs-free-text = pdfjs-free-text =
.aria-label = Éditeur de texte .aria-label = Éditeur de texte
pdfjs-free-text-default-content = Commencer à écrire… pdfjs-free-text-default-content = Commencer à écrire…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Dissen
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Zonte o modifiche imagjins .title = Zonte o modifiche imagjins
pdfjs-editor-stamp-button-label = Zonte o modifiche imagjins pdfjs-editor-stamp-button-label = Zonte o modifiche imagjins
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Gjave .title = Evidenzie
pdfjs-editor-highlight-button-label = Evidenzie
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -312,6 +313,8 @@ pdfjs-editor-remove-freetext-button =
.title = Gjave test .title = Gjave test
pdfjs-editor-remove-stamp-button = pdfjs-editor-remove-stamp-button =
.title = Gjave imagjin .title = Gjave imagjin
pdfjs-editor-remove-highlight-button =
.title = Gjave evidenziazion
## ##
@ -324,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opacitât
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Zonte imagjin .title = Zonte imagjin
pdfjs-editor-stamp-add-image-button-label = Zonte imagjin pdfjs-editor-stamp-add-image-button-label = Zonte imagjin
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Spessôr
pdfjs-editor-free-highlight-thickness-title =
.title = Modifiche il spessôr de selezion pai elements che no son testuâi
pdfjs-free-text = pdfjs-free-text =
.aria-label = Editôr di test .aria-label = Editôr di test
pdfjs-free-text-default-content = Scomence a scrivi… pdfjs-free-text-default-content = Scomence a scrivi…
@ -361,3 +368,22 @@ pdfjs-editor-resizer-label-bottom-right = Cjanton in bas a diestre — ridimensi
pdfjs-editor-resizer-label-bottom-middle = Bande inferiôr tal mieç — ridimensione pdfjs-editor-resizer-label-bottom-middle = Bande inferiôr tal mieç — ridimensione
pdfjs-editor-resizer-label-bottom-left = Cjanton in bas a çampe — ridimensione pdfjs-editor-resizer-label-bottom-left = Cjanton in bas a çampe — ridimensione
pdfjs-editor-resizer-label-middle-left = Bande di çampe tal mieç — ridimensione pdfjs-editor-resizer-label-middle-left = Bande di çampe tal mieç — ridimensione
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = Colôr par evidenziâ
pdfjs-editor-colorpicker-button =
.title = Cambie colôr
pdfjs-editor-colorpicker-dropdown =
.aria-label = Sieltis di colôr
pdfjs-editor-colorpicker-yellow =
.title = Zâl
pdfjs-editor-colorpicker-green =
.title = Vert
pdfjs-editor-colorpicker-blue =
.title = Blu
pdfjs-editor-colorpicker-pink =
.title = Rose
pdfjs-editor-colorpicker-red =
.title = Ros

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Tekenje
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Ofbyldingen tafoegje of bewurkje .title = Ofbyldingen tafoegje of bewurkje
pdfjs-editor-stamp-button-label = Ofbyldingen tafoegje of bewurkje pdfjs-editor-stamp-button-label = Ofbyldingen tafoegje of bewurkje
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Fuortsmite .title = Markearje
pdfjs-editor-highlight-button-label = Markearje
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Transparânsje
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Ofbylding tafoegje .title = Ofbylding tafoegje
pdfjs-editor-stamp-add-image-button-label = Ofbylding tafoegje pdfjs-editor-stamp-add-image-button-label = Ofbylding tafoegje
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Tsjokte
pdfjs-editor-free-highlight-thickness-title =
.title = Tsjokte wizigje by aksintuearring fan oare items as tekst
pdfjs-free-text = pdfjs-free-text =
.aria-label = Tekstbewurker .aria-label = Tekstbewurker
pdfjs-free-text-default-content = Begjin mei typen… pdfjs-free-text-default-content = Begjin mei typen…

View File

@ -301,6 +301,18 @@ pdfjs-editor-ink-button-label = Debuxo
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Engadir ou editar imaxes .title = Engadir ou editar imaxes
pdfjs-editor-stamp-button-label = Engadir ou editar imaxes pdfjs-editor-stamp-button-label = Engadir ou editar imaxes
## Remove button for the various kind of editor.
pdfjs-editor-remove-freetext-button =
.title = Eliminar o texto
pdfjs-editor-remove-stamp-button =
.title = Eliminar a imaxe
pdfjs-editor-remove-highlight-button =
.title = Eliminar o resaltado
##
# Editor Parameters # Editor Parameters
pdfjs-editor-free-text-color-input = Cor pdfjs-editor-free-text-color-input = Cor
pdfjs-editor-free-text-size-input = Tamaño pdfjs-editor-free-text-size-input = Tamaño
@ -310,6 +322,8 @@ pdfjs-editor-ink-opacity-input = Opacidade
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Engadir imaxe .title = Engadir imaxe
pdfjs-editor-stamp-add-image-button-label = Engadir imaxe pdfjs-editor-stamp-add-image-button-label = Engadir imaxe
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Grosor
pdfjs-free-text = pdfjs-free-text =
.aria-label = Editor de texto .aria-label = Editor de texto
pdfjs-free-text-default-content = Comezar a teclear… pdfjs-free-text-default-content = Comezar a teclear…
@ -345,3 +359,6 @@ pdfjs-editor-resizer-label-bottom-right = Esquina inferior dereita: cambia o tam
pdfjs-editor-resizer-label-bottom-middle = Abaixo medio: cambia o tamaño pdfjs-editor-resizer-label-bottom-middle = Abaixo medio: cambia o tamaño
pdfjs-editor-resizer-label-bottom-left = Esquina inferior esquerda: cambia o tamaño pdfjs-editor-resizer-label-bottom-left = Esquina inferior esquerda: cambia o tamaño
pdfjs-editor-resizer-label-middle-left = Medio esquerdo: cambia o tamaño pdfjs-editor-resizer-label-middle-left = Medio esquerdo: cambia o tamaño
## Color picker

View File

@ -303,6 +303,9 @@ pdfjs-editor-stamp-button =
pdfjs-editor-stamp-button-label = Embojuaju térã embosakoi taãnga pdfjs-editor-stamp-button-label = Embojuaju térã embosakoi taãnga
pdfjs-editor-remove-button = pdfjs-editor-remove-button =
.title = Mboguete .title = Mboguete
pdfjs-editor-highlight-button =
.title = Mbosay
pdfjs-editor-highlight-button-label = Mbosay
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = ציור
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = הוספה או עריכת תמונות .title = הוספה או עריכת תמונות
pdfjs-editor-stamp-button-label = הוספה או עריכת תמונות pdfjs-editor-stamp-button-label = הוספה או עריכת תמונות
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = הסרה .title = סימון
pdfjs-editor-highlight-button-label = סימון
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = אטימות
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = הוספת תמונה .title = הוספת תמונה
pdfjs-editor-stamp-add-image-button-label = הוספת תמונה pdfjs-editor-stamp-add-image-button-label = הוספת תמונה
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = עובי
pdfjs-editor-free-highlight-thickness-title =
.title = שינוי עובי בעת הדגשת פריטים שאינם טקסט
pdfjs-free-text = pdfjs-free-text =
.aria-label = עורך טקסט .aria-label = עורך טקסט
pdfjs-free-text-default-content = להתחיל להקליד… pdfjs-free-text-default-content = להתחיל להקליד…

View File

@ -305,8 +305,9 @@ pdfjs-editor-ink-button-label = Rysować
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Wobrazy přidać abo wobdźěłać .title = Wobrazy přidać abo wobdźěłać
pdfjs-editor-stamp-button-label = Wobrazy přidać abo wobdźěłać pdfjs-editor-stamp-button-label = Wobrazy přidać abo wobdźěłać
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Wotstronić .title = Wuzběhnyć
pdfjs-editor-highlight-button-label = Wuzběhnyć
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -330,6 +331,10 @@ pdfjs-editor-ink-opacity-input = Opacita
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Wobraz přidać .title = Wobraz přidać
pdfjs-editor-stamp-add-image-button-label = Wobraz přidać pdfjs-editor-stamp-add-image-button-label = Wobraz přidać
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Tołstosć
pdfjs-editor-free-highlight-thickness-title =
.title = Tołstosć změnić, hdyž so zapiski wuzběhuja, kotrež tekst njejsu
pdfjs-free-text = pdfjs-free-text =
.aria-label = Tekstowy editor .aria-label = Tekstowy editor
pdfjs-free-text-default-content = Započńće pisać… pdfjs-free-text-default-content = Započńće pisać…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Rajzolás
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Képek hozzáadása vagy szerkesztése .title = Képek hozzáadása vagy szerkesztése
pdfjs-editor-stamp-button-label = Képek hozzáadása vagy szerkesztése pdfjs-editor-stamp-button-label = Képek hozzáadása vagy szerkesztése
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Eltávolítás .title = Kiemelés
pdfjs-editor-highlight-button-label = Kiemelés
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Átlátszatlanság
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Kép hozzáadása .title = Kép hozzáadása
pdfjs-editor-stamp-add-image-button-label = Kép hozzáadása pdfjs-editor-stamp-add-image-button-label = Kép hozzáadása
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Vastagság
pdfjs-editor-free-highlight-thickness-title =
.title = Vastagság módosítása, ha nem szöveges elemeket emel ki
pdfjs-free-text = pdfjs-free-text =
.aria-label = Szövegszerkesztő .aria-label = Szövegszerkesztő
pdfjs-free-text-default-content = Kezdjen el gépelni… pdfjs-free-text-default-content = Kezdjen el gépelni…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Designar
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Adder o rediger imagines .title = Adder o rediger imagines
pdfjs-editor-stamp-button-label = Adder o rediger imagines pdfjs-editor-stamp-button-label = Adder o rediger imagines
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Remover .title = Evidentia
pdfjs-editor-highlight-button-label = Evidentia
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opacitate
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Adder imagine .title = Adder imagine
pdfjs-editor-stamp-add-image-button-label = Adder imagine pdfjs-editor-stamp-add-image-button-label = Adder imagine
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Spissor
pdfjs-editor-free-highlight-thickness-title =
.title = Cambiar spissor evidentiante elementos differente de texto
pdfjs-free-text = pdfjs-free-text =
.aria-label = Editor de texto .aria-label = Editor de texto
pdfjs-free-text-default-content = Comenciar a scriber… pdfjs-free-text-default-content = Comenciar a scriber…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Teikna
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Bæta við eða breyta myndum .title = Bæta við eða breyta myndum
pdfjs-editor-stamp-button-label = Bæta við eða breyta myndum pdfjs-editor-stamp-button-label = Bæta við eða breyta myndum
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Fjarlægja .title = Áherslulita
pdfjs-editor-highlight-button-label = Áherslulita
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Ógegnsæi
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Bæta við mynd .title = Bæta við mynd
pdfjs-editor-stamp-add-image-button-label = Bæta við mynd pdfjs-editor-stamp-add-image-button-label = Bæta við mynd
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Þykkt
pdfjs-editor-free-highlight-thickness-title =
.title = Breyta þykkt við áherslulitun annarra atriða en texta
pdfjs-free-text = pdfjs-free-text =
.aria-label = Textaritill .aria-label = Textaritill
pdfjs-free-text-default-content = Byrjaðu að skrifa… pdfjs-free-text-default-content = Byrjaðu að skrifa…

View File

@ -304,6 +304,9 @@ pdfjs-editor-ink-button-label = Disegno
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Aggiungi o rimuovi immagine .title = Aggiungi o rimuovi immagine
pdfjs-editor-stamp-button-label = Aggiungi o rimuovi immagine pdfjs-editor-stamp-button-label = Aggiungi o rimuovi immagine
pdfjs-editor-highlight-button =
.title = Evidenzia
pdfjs-editor-highlight-button-label = Evidenzia
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -318,8 +321,6 @@ pdfjs-editor-remove-highlight-button =
## ##
pdfjs-editor-remove-button =
.title = Rimuovi
# Editor Parameters # Editor Parameters
pdfjs-editor-free-text-color-input = Colore pdfjs-editor-free-text-color-input = Colore
pdfjs-editor-free-text-size-input = Dimensione pdfjs-editor-free-text-size-input = Dimensione
@ -329,6 +330,11 @@ pdfjs-editor-ink-opacity-input = Opacità
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Aggiungi immagine .title = Aggiungi immagine
pdfjs-editor-stamp-add-image-button-label = Aggiungi immagine pdfjs-editor-stamp-add-image-button-label = Aggiungi immagine
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Spessore
pdfjs-editor-free-highlight-thickness-title =
.title = Modifica lo spessore della selezione per elementi non testuali
pdfjs-free-text = pdfjs-free-text =
.aria-label = Editor di testo .aria-label = Editor di testo
pdfjs-free-text-default-content = Inizia a digitare… pdfjs-free-text-default-content = Inizia a digitare…
@ -386,4 +392,3 @@ pdfjs-editor-colorpicker-pink =
.title = Rosa .title = Rosa
pdfjs-editor-colorpicker-red = pdfjs-editor-colorpicker-red =
.title = Rosso .title = Rosso

View File

@ -293,16 +293,17 @@ pdfjs-web-fonts-disabled = ウェブフォントが無効になっています:
## Editing ## Editing
pdfjs-editor-free-text-button = pdfjs-editor-free-text-button =
.title = フリーテキスト注釈 .title = フリーテキスト注釈を追加します
pdfjs-editor-free-text-button-label = フリーテキスト注釈 pdfjs-editor-free-text-button-label = フリーテキスト注釈
pdfjs-editor-ink-button = pdfjs-editor-ink-button =
.title = インク注釈 .title = インク注釈を追加します
pdfjs-editor-ink-button-label = インク注釈 pdfjs-editor-ink-button-label = インク注釈
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = 画像を追加または編集します .title = 画像を追加または編集します
pdfjs-editor-stamp-button-label = 画像を追加または編集 pdfjs-editor-stamp-button-label = 画像を追加または編集
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = 削除 .title = 強調します
pdfjs-editor-highlight-button-label = 強調
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -312,6 +313,8 @@ pdfjs-editor-remove-freetext-button =
.title = テキストを削除します .title = テキストを削除します
pdfjs-editor-remove-stamp-button = pdfjs-editor-remove-stamp-button =
.title = 画像を削除します .title = 画像を削除します
pdfjs-editor-remove-highlight-button =
.title = 強調を削除します
## ##
@ -324,6 +327,10 @@ pdfjs-editor-ink-opacity-input = 不透明度
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = 画像を追加します .title = 画像を追加します
pdfjs-editor-stamp-add-image-button-label = 画像を追加 pdfjs-editor-stamp-add-image-button-label = 画像を追加
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = 太さ
pdfjs-editor-free-highlight-thickness-title =
.title = テキスト以外のアイテムを強調する時の太さを変更します
pdfjs-free-text = pdfjs-free-text =
.aria-label = フリーテキスト注釈エディター .aria-label = フリーテキスト注釈エディター
pdfjs-free-text-default-content = テキストを入力してください... pdfjs-free-text-default-content = テキストを入力してください...
@ -361,3 +368,22 @@ pdfjs-editor-resizer-label-bottom-right = 右下隅 — サイズ変更
pdfjs-editor-resizer-label-bottom-middle = 下中央 — サイズ変更 pdfjs-editor-resizer-label-bottom-middle = 下中央 — サイズ変更
pdfjs-editor-resizer-label-bottom-left = 左下隅 — サイズ変更 pdfjs-editor-resizer-label-bottom-left = 左下隅 — サイズ変更
pdfjs-editor-resizer-label-middle-left = 左中央 — サイズ変更 pdfjs-editor-resizer-label-middle-left = 左中央 — サイズ変更
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = 強調色
pdfjs-editor-colorpicker-button =
.title = 色を変更します
pdfjs-editor-colorpicker-dropdown =
.aria-label = 色の選択
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 = 赤色

View File

@ -220,7 +220,7 @@ pdfjs-find-previous-button-label = წინა
pdfjs-find-next-button = pdfjs-find-next-button =
.title = ფრაზის შემდეგი კონტექსტის პოვნა .title = ფრაზის შემდეგი კონტექსტის პოვნა
pdfjs-find-next-button-label = შემდეგი pdfjs-find-next-button-label = შემდეგი
pdfjs-find-highlight-checkbox = ყველას მონიშვნა pdfjs-find-highlight-checkbox = ყველაფრის მონიშვნა
pdfjs-find-match-case-checkbox-label = მთავრულით pdfjs-find-match-case-checkbox-label = მთავრულით
pdfjs-find-match-diacritics-checkbox-label = ნიშნებით pdfjs-find-match-diacritics-checkbox-label = ნიშნებით
pdfjs-find-entire-word-checkbox-label = მთლიანი სიტყვები pdfjs-find-entire-word-checkbox-label = მთლიანი სიტყვები
@ -303,6 +303,23 @@ pdfjs-editor-stamp-button =
pdfjs-editor-stamp-button-label = სურათების დართვა ან ჩასწორება pdfjs-editor-stamp-button-label = სურათების დართვა ან ჩასწორება
pdfjs-editor-remove-button = pdfjs-editor-remove-button =
.title = მოცილება .title = მოცილება
pdfjs-editor-highlight-button =
.title = მონიშვნა
pdfjs-editor-highlight-button-label = მონიშვნა
## Remove button for the various kind of editor.
pdfjs-editor-remove-ink-button =
.title = დახაზულის მოცილება
pdfjs-editor-remove-freetext-button =
.title = წარწერის მოცილება
pdfjs-editor-remove-stamp-button =
.title = სურათის მოცილება
pdfjs-editor-remove-highlight-button =
.title = მონიშვნის მოცილება
##
# Editor Parameters # Editor Parameters
pdfjs-editor-free-text-color-input = ფერი pdfjs-editor-free-text-color-input = ფერი
pdfjs-editor-free-text-size-input = ზომა pdfjs-editor-free-text-size-input = ზომა
@ -316,24 +333,24 @@ pdfjs-free-text =
.aria-label = ნაწერის ჩასწორება .aria-label = ნაწერის ჩასწორება
pdfjs-free-text-default-content = აკრიფეთ… pdfjs-free-text-default-content = აკრიფეთ…
pdfjs-ink = pdfjs-ink =
.aria-label = ნახატის ჩასწორება .aria-label = დახაზულის შესწორება
pdfjs-ink-canvas = pdfjs-ink-canvas =
.aria-label = მომხმარებლის შექმნილი სურათი .aria-label = მომხმარებლის შექმნილი სურათი
## Alt-text dialog ## Alt-text dialog
# Alternative text (alt text) helps when people can't see the image. # Alternative text (alt text) helps when people can't see the image.
pdfjs-editor-alt-text-button-label = დართული წარწერა pdfjs-editor-alt-text-button-label = თანდართული წარწერა
pdfjs-editor-alt-text-edit-button-label = დართული წარწერის ჩასწორება pdfjs-editor-alt-text-edit-button-label = თანდართული წარწერის ჩასწორება
pdfjs-editor-alt-text-dialog-label = არჩევა pdfjs-editor-alt-text-dialog-label = არჩევა
pdfjs-editor-alt-text-dialog-description = დართული წარწერა (შემნაცვლებელი ტექსტი) გამოსადეგია მათთვის, ვინც ვერ ხედავს სურათებს ან როცა სურათი ვერ იტვირთება. pdfjs-editor-alt-text-dialog-description = თანდართული (შემნაცვლებელი) წარწერა გამოსადეგია მათთვის, ვინც ვერ ხედავს სურათებს ან გამოისახება მაშინ, როცა სურათი ვერ ჩაიტვირთება.
pdfjs-editor-alt-text-add-description-label = აღწერილობის დამატება pdfjs-editor-alt-text-add-description-label = აღწერილობის მითითება
pdfjs-editor-alt-text-add-description-description = განკუთვნილია 1-2 წინადადებით საგნის, მახასიათებლის ან მოქმედების აღსაწერად. pdfjs-editor-alt-text-add-description-description = განკუთვნილია 1-2 წინადადებით საგნის, მახასიათებლის ან მოქმედების აღსაწერად.
pdfjs-editor-alt-text-mark-decorative-label = მოინიშნოს მოსართავად pdfjs-editor-alt-text-mark-decorative-label = მოინიშნოს მორთულობად
pdfjs-editor-alt-text-mark-decorative-description = გამოიყენება შესამკობი სურათებისთვის, გარსშემოსავლები ჩარჩოებისა და ჭვირნიშნებისთვის. pdfjs-editor-alt-text-mark-decorative-description = განკუთვნილია შესამკობი სურათებისთვის, გარსშემოსავლები ჩარჩოებისა და ჭვირნიშნებისთვის.
pdfjs-editor-alt-text-cancel-button = გაუქმება pdfjs-editor-alt-text-cancel-button = გაუქმება
pdfjs-editor-alt-text-save-button = შენახვა pdfjs-editor-alt-text-save-button = შენახვა
pdfjs-editor-alt-text-decorative-tooltip = მოინიშნოს მოსართავად pdfjs-editor-alt-text-decorative-tooltip = მოინიშნოს მორთულობად
# .placeholder: This is a placeholder for the alt text input area # .placeholder: This is a placeholder for the alt text input area
pdfjs-editor-alt-text-textarea = pdfjs-editor-alt-text-textarea =
.placeholder = მაგალითად, „ახალგაზრდა მამაკაცი მაგიდასთან ზის და სადილობს“ .placeholder = მაგალითად, „ახალგაზრდა მამაკაცი მაგიდასთან ზის და სადილობს“
@ -349,3 +366,22 @@ pdfjs-editor-resizer-label-bottom-right = ქვევით მარჯვნ
pdfjs-editor-resizer-label-bottom-middle = ქვევით შუაში — ზომაცვლა pdfjs-editor-resizer-label-bottom-middle = ქვევით შუაში — ზომაცვლა
pdfjs-editor-resizer-label-bottom-left = ზვევით მარცხნივ — ზომაცვლა pdfjs-editor-resizer-label-bottom-left = ზვევით მარცხნივ — ზომაცვლა
pdfjs-editor-resizer-label-middle-left = შუაში მარცხნივ — ზომაცვლა pdfjs-editor-resizer-label-middle-left = შუაში მარცხნივ — ზომაცვლა
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = მოსანიშნი ფერი
pdfjs-editor-colorpicker-button =
.title = ფერის შეცვლა
pdfjs-editor-colorpicker-dropdown =
.aria-label = ფერის არჩევა
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 = წითელი

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Сурет салу
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Суреттерді қосу немесе түзету .title = Суреттерді қосу немесе түзету
pdfjs-editor-stamp-button-label = Суреттерді қосу немесе түзету pdfjs-editor-stamp-button-label = Суреттерді қосу немесе түзету
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Өшіру .title = Ерекшелеу
pdfjs-editor-highlight-button-label = Ерекшелеу
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Мөлдірсіздігі
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Суретті қосу .title = Суретті қосу
pdfjs-editor-stamp-add-image-button-label = Суретті қосу pdfjs-editor-stamp-add-image-button-label = Суретті қосу
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Қалыңдығы
pdfjs-editor-free-highlight-thickness-title =
.title = Мәтіннен басқа элементтерді ерекшелеу кезінде қалыңдықты өзгерту
pdfjs-free-text = pdfjs-free-text =
.aria-label = Мәтін түзеткіші .aria-label = Мәтін түзеткіші
pdfjs-free-text-default-content = Теруді бастау… pdfjs-free-text-default-content = Теруді бастау…

View File

@ -293,8 +293,9 @@ pdfjs-editor-ink-button-label = 그리기
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = 이미지 추가 또는 편집 .title = 이미지 추가 또는 편집
pdfjs-editor-stamp-button-label = 이미지 추가 또는 편집 pdfjs-editor-stamp-button-label = 이미지 추가 또는 편집
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = 제거 .title = 강조
pdfjs-editor-highlight-button-label = 강조
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -318,6 +319,10 @@ pdfjs-editor-ink-opacity-input = 불투명도
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = 이미지 추가 .title = 이미지 추가
pdfjs-editor-stamp-add-image-button-label = 이미지 추가 pdfjs-editor-stamp-add-image-button-label = 이미지 추가
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = 두께
pdfjs-editor-free-highlight-thickness-title =
.title = 텍스트 이외의 항목을 강조 표시할 때 두께 변경
pdfjs-free-text = pdfjs-free-text =
.aria-label = 텍스트 편집기 .aria-label = 텍스트 편집기
pdfjs-free-text-default-content = 입력하세요… pdfjs-free-text-default-content = 입력하세요…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Tegn
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Legg til eller rediger bilder .title = Legg til eller rediger bilder
pdfjs-editor-stamp-button-label = Legg til eller rediger bilder pdfjs-editor-stamp-button-label = Legg til eller rediger bilder
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Fjern .title = Markere
pdfjs-editor-highlight-button-label = Markere
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Ugjennomsiktighet
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Legg til bilde .title = Legg til bilde
pdfjs-editor-stamp-add-image-button-label = Legg til bilde pdfjs-editor-stamp-add-image-button-label = Legg til bilde
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Tykkelse
pdfjs-editor-free-highlight-thickness-title =
.title = Endre tykkelse når du markerer andre elementer enn tekst
pdfjs-free-text = pdfjs-free-text =
.aria-label = Tekstredigering .aria-label = Tekstredigering
pdfjs-free-text-default-content = Begynn å skrive… pdfjs-free-text-default-content = Begynn å skrive…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Tekenen
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Afbeeldingen toevoegen of bewerken .title = Afbeeldingen toevoegen of bewerken
pdfjs-editor-stamp-button-label = Afbeeldingen toevoegen of bewerken pdfjs-editor-stamp-button-label = Afbeeldingen toevoegen of bewerken
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Verwijderen .title = Markeren
pdfjs-editor-highlight-button-label = Markeren
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opaciteit
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Afbeelding toevoegen .title = Afbeelding toevoegen
pdfjs-editor-stamp-add-image-button-label = Afbeelding toevoegen pdfjs-editor-stamp-add-image-button-label = Afbeelding toevoegen
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Dikte
pdfjs-editor-free-highlight-thickness-title =
.title = Dikte wijzigen bij accentuering van andere items dan tekst
pdfjs-free-text = pdfjs-free-text =
.aria-label = Tekstbewerker .aria-label = Tekstbewerker
pdfjs-free-text-default-content = Begin met typen… pdfjs-free-text-default-content = Begin met typen…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = ਵਾਹੋ
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = ਚਿੱਤਰ ਜੋੜੋ ਜਾਂ ਸੋਧੋ .title = ਚਿੱਤਰ ਜੋੜੋ ਜਾਂ ਸੋਧੋ
pdfjs-editor-stamp-button-label = ਚਿੱਤਰ ਜੋੜੋ ਜਾਂ ਸੋਧੋ pdfjs-editor-stamp-button-label = ਚਿੱਤਰ ਜੋੜੋ ਜਾਂ ਸੋਧੋ
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = ਹਟਾਓ .title = ਹਾਈਲਾਈਟ
pdfjs-editor-highlight-button-label = ਹਾਈਲਾਈਟ
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -312,6 +313,8 @@ pdfjs-editor-remove-freetext-button =
.title = ਲਿਖਤ ਨੂੰ ਹਟਾਓ .title = ਲਿਖਤ ਨੂੰ ਹਟਾਓ
pdfjs-editor-remove-stamp-button = pdfjs-editor-remove-stamp-button =
.title = ਚਿੱਤਰ ਨੂੰ ਹਟਾਓ .title = ਚਿੱਤਰ ਨੂੰ ਹਟਾਓ
pdfjs-editor-remove-highlight-button =
.title = ਹਾਈਲਾਈਟ ਨੂੰ ਹਟਾਓ
## ##
@ -324,6 +327,8 @@ pdfjs-editor-ink-opacity-input = ਧੁੰਦਲਾਪਨ
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = ਚਿੱਤਰ ਜੋੜੋ .title = ਚਿੱਤਰ ਜੋੜੋ
pdfjs-editor-stamp-add-image-button-label = ਚਿੱਤਰ ਜੋੜੋ pdfjs-editor-stamp-add-image-button-label = ਚਿੱਤਰ ਜੋੜੋ
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = ਮੋਟਾਈ
pdfjs-free-text = pdfjs-free-text =
.aria-label = ਲਿਖਤ ਐਡੀਟਰ .aria-label = ਲਿਖਤ ਐਡੀਟਰ
pdfjs-free-text-default-content = …ਲਿਖਣਾ ਸ਼ੁਰੂ ਕਰੋ pdfjs-free-text-default-content = …ਲਿਖਣਾ ਸ਼ੁਰੂ ਕਰੋ
@ -361,3 +366,22 @@ pdfjs-editor-resizer-label-bottom-right = ਹੇਠਾਂ ਸੱਜਾ ਕੋਨ
pdfjs-editor-resizer-label-bottom-middle = ਹੇਠਾਂ ਮੱਧ — ਮੁੜ-ਆਕਾਰ ਕਰੋ pdfjs-editor-resizer-label-bottom-middle = ਹੇਠਾਂ ਮੱਧ — ਮੁੜ-ਆਕਾਰ ਕਰੋ
pdfjs-editor-resizer-label-bottom-left = ਹੇਠਾਂ ਖੱਬਾ ਕੋਨਾ — ਮੁੜ-ਆਕਾਰ ਕਰੋ pdfjs-editor-resizer-label-bottom-left = ਹੇਠਾਂ ਖੱਬਾ ਕੋਨਾ — ਮੁੜ-ਆਕਾਰ ਕਰੋ
pdfjs-editor-resizer-label-middle-left = ਮੱਧ ਖੱਬਾ — ਮੁੜ-ਆਕਾਰ ਕਰੋ pdfjs-editor-resizer-label-middle-left = ਮੱਧ ਖੱਬਾ — ਮੁੜ-ਆਕਾਰ ਕਰੋ
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = ਹਾਈਟਲਾਈਟ ਦਾ ਰੰਗ
pdfjs-editor-colorpicker-button =
.title = ਰੰਗ ਨੂੰ ਬਦਲੋ
pdfjs-editor-colorpicker-dropdown =
.aria-label = ਰੰਗ ਚੋਣਾਂ
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 = ਲਾਲ

View File

@ -303,8 +303,9 @@ pdfjs-editor-ink-button-label = Rysunek
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Dodaj lub edytuj obrazy .title = Dodaj lub edytuj obrazy
pdfjs-editor-stamp-button-label = Dodaj lub edytuj obrazy pdfjs-editor-stamp-button-label = Dodaj lub edytuj obrazy
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Usuń .title = Wyróżnij
pdfjs-editor-highlight-button-label = Wyróżnij
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -328,6 +329,10 @@ pdfjs-editor-ink-opacity-input = Nieprzezroczystość
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Dodaj obraz .title = Dodaj obraz
pdfjs-editor-stamp-add-image-button-label = Dodaj obraz pdfjs-editor-stamp-add-image-button-label = Dodaj obraz
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Grubość
pdfjs-editor-free-highlight-thickness-title =
.title = Zmień grubość podczas wyróżniania elementów innych niż tekst
pdfjs-free-text = pdfjs-free-text =
.aria-label = Edytor tekstu .aria-label = Edytor tekstu
pdfjs-free-text-default-content = Zacznij pisać… pdfjs-free-text-default-content = Zacznij pisać…

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Desenho
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Adicionar ou editar imagens .title = Adicionar ou editar imagens
pdfjs-editor-stamp-button-label = Adicionar ou editar imagens pdfjs-editor-stamp-button-label = Adicionar ou editar imagens
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Remover .title = Destaque
pdfjs-editor-highlight-button-label = Destaque
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opacidade
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Adicionar imagem .title = Adicionar imagem
pdfjs-editor-stamp-add-image-button-label = Adicionar imagem pdfjs-editor-stamp-add-image-button-label = Adicionar imagem
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Espessura
pdfjs-editor-free-highlight-thickness-title =
.title = Mudar espessura ao destacar itens que não são texto
pdfjs-free-text = pdfjs-free-text =
.aria-label = Editor de texto .aria-label = Editor de texto
pdfjs-free-text-default-content = Comece digitando… pdfjs-free-text-default-content = Comece digitando…

View File

@ -301,6 +301,23 @@ pdfjs-editor-ink-button-label = Desenhar
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Adicionar ou editar imagens .title = Adicionar ou editar imagens
pdfjs-editor-stamp-button-label = Adicionar ou editar imagens pdfjs-editor-stamp-button-label = Adicionar ou editar imagens
pdfjs-editor-highlight-button =
.title = Destaque
pdfjs-editor-highlight-button-label = Destaque
## Remove button for the various kind of editor.
pdfjs-editor-remove-ink-button =
.title = Remover desenho
pdfjs-editor-remove-freetext-button =
.title = Remover texto
pdfjs-editor-remove-stamp-button =
.title = Remover imagem
pdfjs-editor-remove-highlight-button =
.title = Remover destaque
##
# Editor Parameters # Editor Parameters
pdfjs-editor-free-text-color-input = Cor pdfjs-editor-free-text-color-input = Cor
pdfjs-editor-free-text-size-input = Tamanho pdfjs-editor-free-text-size-input = Tamanho
@ -310,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opacidade
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Adicionar imagem .title = Adicionar imagem
pdfjs-editor-stamp-add-image-button-label = Adicionar imagem pdfjs-editor-stamp-add-image-button-label = Adicionar imagem
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Espessura
pdfjs-editor-free-highlight-thickness-title =
.title = Alterar espessura quando destacar itens que não sejam texto
pdfjs-free-text = pdfjs-free-text =
.aria-label = Editor de texto .aria-label = Editor de texto
pdfjs-free-text-default-content = Começar a digitar… pdfjs-free-text-default-content = Começar a digitar…
@ -347,3 +368,22 @@ pdfjs-editor-resizer-label-bottom-right = Canto inferior direito — redimension
pdfjs-editor-resizer-label-bottom-middle = Inferior ao centro — redimensionar pdfjs-editor-resizer-label-bottom-middle = Inferior ao centro — redimensionar
pdfjs-editor-resizer-label-bottom-left = Canto inferior esquerdo — redimensionar pdfjs-editor-resizer-label-bottom-left = Canto inferior esquerdo — redimensionar
pdfjs-editor-resizer-label-middle-left = Centro à esquerda — redimensionar pdfjs-editor-resizer-label-middle-left = Centro à esquerda — redimensionar
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = Cor de destaque
pdfjs-editor-colorpicker-button =
.title = Alterar cor
pdfjs-editor-colorpicker-dropdown =
.aria-label = Escolhas de cor
pdfjs-editor-colorpicker-yellow =
.title = Amarelo
pdfjs-editor-colorpicker-green =
.title = Verde
pdfjs-editor-colorpicker-blue =
.title = Azul
pdfjs-editor-colorpicker-pink =
.title = Rosa
pdfjs-editor-colorpicker-red =
.title = Vermelho

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Dissegnar
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Agiuntar u modifitgar maletgs .title = Agiuntar u modifitgar maletgs
pdfjs-editor-stamp-button-label = Agiuntar u modifitgar maletgs pdfjs-editor-stamp-button-label = Agiuntar u modifitgar maletgs
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Allontanar .title = Marcar
pdfjs-editor-highlight-button-label = Marcar
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opacitad
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Agiuntar in maletg .title = Agiuntar in maletg
pdfjs-editor-stamp-add-image-button-label = Agiuntar in maletg pdfjs-editor-stamp-add-image-button-label = Agiuntar in maletg
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Grossezza
pdfjs-editor-free-highlight-thickness-title =
.title = Midar la grossezza cun relevar elements betg textuals
pdfjs-free-text = pdfjs-free-text =
.aria-label = Editur da text .aria-label = Editur da text
pdfjs-free-text-default-content = Cumenzar a tippar… pdfjs-free-text-default-content = Cumenzar a tippar…

View File

@ -303,8 +303,9 @@ pdfjs-editor-ink-button-label = Рисовать
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Добавить или изменить изображения .title = Добавить или изменить изображения
pdfjs-editor-stamp-button-label = Добавить или изменить изображения pdfjs-editor-stamp-button-label = Добавить или изменить изображения
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Удалить .title = Выделение
pdfjs-editor-highlight-button-label = Выделение
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -328,6 +329,10 @@ pdfjs-editor-ink-opacity-input = Прозрачность
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Добавить изображение .title = Добавить изображение
pdfjs-editor-stamp-add-image-button-label = Добавить изображение pdfjs-editor-stamp-add-image-button-label = Добавить изображение
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Толщина
pdfjs-editor-free-highlight-thickness-title =
.title = Изменить толщину при выделении элементов, кроме текста
pdfjs-free-text = pdfjs-free-text =
.aria-label = Текстовый редактор .aria-label = Текстовый редактор
pdfjs-free-text-default-content = Начните вводить… pdfjs-free-text-default-content = Начните вводить…

View File

@ -128,7 +128,7 @@ pdfjs-document-properties-modification-date = Dátum úpravy:
# $date (Date) - the creation/modification date of the PDF file # $date (Date) - the creation/modification date of the PDF file
# $time (Time) - the creation/modification time of the PDF file # $time (Time) - the creation/modification time of the PDF file
pdfjs-document-properties-date-string = { $date }, { $time } pdfjs-document-properties-date-string = { $date }, { $time }
pdfjs-document-properties-creator = Vytvoril: pdfjs-document-properties-creator = Aplikácia:
pdfjs-document-properties-producer = Tvorca PDF: pdfjs-document-properties-producer = Tvorca PDF:
pdfjs-document-properties-version = Verzia PDF: pdfjs-document-properties-version = Verzia PDF:
pdfjs-document-properties-page-count = Počet strán: pdfjs-document-properties-page-count = Počet strán:
@ -156,7 +156,7 @@ pdfjs-document-properties-page-size-dimension-name-string = { $width } × { $hei
# The linearization status of the document; usually called "Fast Web View" in # The linearization status of the document; usually called "Fast Web View" in
# English locales of Adobe software. # English locales of Adobe software.
pdfjs-document-properties-linearized = Rýchle Web View: pdfjs-document-properties-linearized = Rýchle zobrazovanie z webu:
pdfjs-document-properties-linearized-yes = Áno pdfjs-document-properties-linearized-yes = Áno
pdfjs-document-properties-linearized-no = Nie pdfjs-document-properties-linearized-no = Nie
pdfjs-document-properties-close-button = Zavrieť pdfjs-document-properties-close-button = Zavrieť
@ -300,13 +300,14 @@ pdfjs-editor-free-text-button =
.title = Text .title = Text
pdfjs-editor-free-text-button-label = Text pdfjs-editor-free-text-button-label = Text
pdfjs-editor-ink-button = pdfjs-editor-ink-button =
.title = Kreslenie .title = Kresl
pdfjs-editor-ink-button-label = Kresliť pdfjs-editor-ink-button-label = Kresliť
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Pridať alebo upraviť obrázky .title = Pridať alebo upraviť obrázky
pdfjs-editor-stamp-button-label = Pridať alebo upraviť obrázky pdfjs-editor-stamp-button-label = Pridať alebo upraviť obrázky
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Odstrániť .title = Zvýrazniť
pdfjs-editor-highlight-button-label = Zvýrazniť
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -330,6 +331,10 @@ pdfjs-editor-ink-opacity-input = Priehľadnosť
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Pridať obrázok .title = Pridať obrázok
pdfjs-editor-stamp-add-image-button-label = Pridať obrázok pdfjs-editor-stamp-add-image-button-label = Pridať obrázok
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Hrúbka
pdfjs-editor-free-highlight-thickness-title =
.title = Zmeňte hrúbku pre zvýrazňovanie iných položiek ako textu
pdfjs-free-text = pdfjs-free-text =
.aria-label = Textový editor .aria-label = Textový editor
pdfjs-free-text-default-content = Začnite písať… pdfjs-free-text-default-content = Začnite písať…

View File

@ -283,12 +283,21 @@ pdfjs-editor-free-text-button-label = متن
pdfjs-editor-ink-button = pdfjs-editor-ink-button =
.title = چھکو .title = چھکو
pdfjs-editor-ink-button-label = چھکو pdfjs-editor-ink-button-label = چھکو
## Remove button for the various kind of editor.
##
# Editor Parameters # Editor Parameters
pdfjs-editor-free-text-color-input = رنگ pdfjs-editor-free-text-color-input = رنگ
pdfjs-editor-free-text-size-input = سائز pdfjs-editor-free-text-size-input = سائز
pdfjs-editor-ink-color-input = رنگ pdfjs-editor-ink-color-input = رنگ
pdfjs-editor-ink-thickness-input = ٹھولھ pdfjs-editor-ink-thickness-input = ٹھولھ
pdfjs-editor-ink-opacity-input = دھندلاپن pdfjs-editor-ink-opacity-input = دھندلاپن
pdfjs-editor-stamp-add-image-button =
.title = تصویر شامل کرو
pdfjs-editor-stamp-add-image-button-label = تصویر شامل کرو
pdfjs-free-text = pdfjs-free-text =
.aria-label = ٹیکسٹ ایڈیٹر .aria-label = ٹیکسٹ ایڈیٹر
pdfjs-free-text-default-content = ٹائپنگ شروع کرو … pdfjs-free-text-default-content = ٹائپنگ شروع کرو …
@ -303,3 +312,16 @@ pdfjs-ink-canvas =
## Editor resizers ## Editor resizers
## This is used in an aria label to help to understand the role of the resizer. ## This is used in an aria label to help to understand the role of the resizer.
## 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 = لال

View File

@ -305,8 +305,9 @@ pdfjs-editor-ink-button-label = Riši
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Dodajanje ali urejanje slik .title = Dodajanje ali urejanje slik
pdfjs-editor-stamp-button-label = Dodajanje ali urejanje slik pdfjs-editor-stamp-button-label = Dodajanje ali urejanje slik
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Odstrani .title = Poudarek
pdfjs-editor-highlight-button-label = Poudarek
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -330,6 +331,10 @@ pdfjs-editor-ink-opacity-input = Neprosojnost
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Dodaj sliko .title = Dodaj sliko
pdfjs-editor-stamp-add-image-button-label = Dodaj sliko pdfjs-editor-stamp-add-image-button-label = Dodaj sliko
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Debelina
pdfjs-editor-free-highlight-thickness-title =
.title = Spremeni debelino pri označevanju nebesedilnih elementov
pdfjs-free-text = pdfjs-free-text =
.aria-label = Urejevalnik besedila .aria-label = Urejevalnik besedila
pdfjs-free-text-default-content = Začnite tipkati … pdfjs-free-text-default-content = Začnite tipkati …

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Rita
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Lägg till eller redigera bilder .title = Lägg till eller redigera bilder
pdfjs-editor-stamp-button-label = Lägg till eller redigera bilder pdfjs-editor-stamp-button-label = Lägg till eller redigera bilder
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Ta bort .title = Markera
pdfjs-editor-highlight-button-label = Markera
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Opacitet
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Lägg till bild .title = Lägg till bild
pdfjs-editor-stamp-add-image-button-label = Lägg till bild pdfjs-editor-stamp-add-image-button-label = Lägg till bild
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Tjocklek
pdfjs-editor-free-highlight-thickness-title =
.title = Ändra tjocklek när du markerar andra objekt än text
pdfjs-free-text = pdfjs-free-text =
.aria-label = Textredigerare .aria-label = Textredigerare
pdfjs-free-text-default-content = Börja skriva… pdfjs-free-text-default-content = Börja skriva…

View File

@ -293,6 +293,23 @@ pdfjs-editor-ink-button-label = รูปวาด
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = เพิ่มหรือแก้ไขภาพ .title = เพิ่มหรือแก้ไขภาพ
pdfjs-editor-stamp-button-label = เพิ่มหรือแก้ไขภาพ pdfjs-editor-stamp-button-label = เพิ่มหรือแก้ไขภาพ
pdfjs-editor-highlight-button =
.title = เน้น
pdfjs-editor-highlight-button-label = เน้น
## Remove button for the various kind of editor.
pdfjs-editor-remove-ink-button =
.title = เอาภาพวาดออก
pdfjs-editor-remove-freetext-button =
.title = เอาข้อความออก
pdfjs-editor-remove-stamp-button =
.title = เอาภาพออก
pdfjs-editor-remove-highlight-button =
.title = เอาการเน้นสีออก
##
# Editor Parameters # Editor Parameters
pdfjs-editor-free-text-color-input = สี pdfjs-editor-free-text-color-input = สี
pdfjs-editor-free-text-size-input = ขนาด pdfjs-editor-free-text-size-input = ขนาด
@ -302,6 +319,10 @@ pdfjs-editor-ink-opacity-input = ความทึบ
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = เพิ่มภาพ .title = เพิ่มภาพ
pdfjs-editor-stamp-add-image-button-label = เพิ่มภาพ pdfjs-editor-stamp-add-image-button-label = เพิ่มภาพ
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = ความหนา
pdfjs-editor-free-highlight-thickness-title =
.title = เปลี่ยนความหนาเมื่อเน้นรายการอื่นๆ ที่ไม่ใช่ข้อความ
pdfjs-free-text = pdfjs-free-text =
.aria-label = ตัวแก้ไขข้อความ .aria-label = ตัวแก้ไขข้อความ
pdfjs-free-text-default-content = เริ่มพิมพ์… pdfjs-free-text-default-content = เริ่มพิมพ์…
@ -339,3 +360,22 @@ pdfjs-editor-resizer-label-bottom-right = มุมขวาล่าง — ป
pdfjs-editor-resizer-label-bottom-middle = ตรงกลางด้านล่าง — ปรับขนาด pdfjs-editor-resizer-label-bottom-middle = ตรงกลางด้านล่าง — ปรับขนาด
pdfjs-editor-resizer-label-bottom-left = มุมซ้ายล่าง — ปรับขนาด pdfjs-editor-resizer-label-bottom-left = มุมซ้ายล่าง — ปรับขนาด
pdfjs-editor-resizer-label-middle-left = ตรงกลางด้านซ้าย — ปรับขนาด pdfjs-editor-resizer-label-middle-left = ตรงกลางด้านซ้าย — ปรับขนาด
## Color picker
# This means "Color used to highlight text"
pdfjs-editor-highlight-colorpicker-label = สีเน้น
pdfjs-editor-colorpicker-button =
.title = เปลี่ยนสี
pdfjs-editor-colorpicker-dropdown =
.aria-label = ทางเลือกสี
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 = แดง

View File

@ -301,8 +301,9 @@ pdfjs-editor-ink-button-label = Çiz
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Resim ekle veya düzenle .title = Resim ekle veya düzenle
pdfjs-editor-stamp-button-label = Resim ekle veya düzenle pdfjs-editor-stamp-button-label = Resim ekle veya düzenle
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Kaldır .title = Vurgula
pdfjs-editor-highlight-button-label = Vurgula
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -326,6 +327,10 @@ pdfjs-editor-ink-opacity-input = Saydamlık
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Resim ekle .title = Resim ekle
pdfjs-editor-stamp-add-image-button-label = Resim ekle pdfjs-editor-stamp-add-image-button-label = Resim ekle
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Kalınlık
pdfjs-editor-free-highlight-thickness-title =
.title = Metin dışındaki öğeleri vurgularken kalınlığı değiştir
pdfjs-free-text = pdfjs-free-text =
.aria-label = Metin düzenleyicisi .aria-label = Metin düzenleyicisi
pdfjs-free-text-default-content = Yazmaya başlayın… pdfjs-free-text-default-content = Yazmaya başlayın…

View File

@ -288,7 +288,7 @@ pdfjs-text-annotation-type =
pdfjs-password-label = Введіть пароль для відкриття цього PDF-файла. pdfjs-password-label = Введіть пароль для відкриття цього PDF-файла.
pdfjs-password-invalid = Невірний пароль. Спробуйте ще. pdfjs-password-invalid = Невірний пароль. Спробуйте ще.
pdfjs-password-ok-button = Гаразд pdfjs-password-ok-button = OK
pdfjs-password-cancel-button = Скасувати pdfjs-password-cancel-button = Скасувати
pdfjs-web-fonts-disabled = Веб-шрифти вимкнено: неможливо використати вбудовані у PDF шрифти. pdfjs-web-fonts-disabled = Веб-шрифти вимкнено: неможливо використати вбудовані у PDF шрифти.
@ -303,8 +303,9 @@ pdfjs-editor-ink-button-label = Малювати
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Додати чи редагувати зображення .title = Додати чи редагувати зображення
pdfjs-editor-stamp-button-label = Додати чи редагувати зображення pdfjs-editor-stamp-button-label = Додати чи редагувати зображення
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Вилучити .title = Підсвітити
pdfjs-editor-highlight-button-label = Підсвітити
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -328,6 +329,10 @@ pdfjs-editor-ink-opacity-input = Прозорість
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Додати зображення .title = Додати зображення
pdfjs-editor-stamp-add-image-button-label = Додати зображення pdfjs-editor-stamp-add-image-button-label = Додати зображення
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Товщина
pdfjs-editor-free-highlight-thickness-title =
.title = Змінюйте товщину під час підсвічування елементів, крім тексту
pdfjs-free-text = pdfjs-free-text =
.aria-label = Текстовий редактор .aria-label = Текстовий редактор
pdfjs-free-text-default-content = Почніть вводити… pdfjs-free-text-default-content = Почніть вводити…
@ -357,14 +362,14 @@ pdfjs-editor-alt-text-textarea =
## Editor resizers ## Editor resizers
## This is used in an aria label to help to understand the role of the resizer. ## This is used in an aria label to help to understand the role of the resizer.
pdfjs-editor-resizer-label-top-left = Верхній лівий кут зміна розміру pdfjs-editor-resizer-label-top-left = Верхній лівий кут зміна розміру
pdfjs-editor-resizer-label-top-middle = Вгорі посередині зміна розміру pdfjs-editor-resizer-label-top-middle = Вгорі посередині зміна розміру
pdfjs-editor-resizer-label-top-right = Верхній правий кут зміна розміру pdfjs-editor-resizer-label-top-right = Верхній правий кут зміна розміру
pdfjs-editor-resizer-label-middle-right = Праворуч посередині зміна розміру pdfjs-editor-resizer-label-middle-right = Праворуч посередині зміна розміру
pdfjs-editor-resizer-label-bottom-right = Нижній правий кут зміна розміру pdfjs-editor-resizer-label-bottom-right = Нижній правий кут зміна розміру
pdfjs-editor-resizer-label-bottom-middle = Внизу посередині зміна розміру pdfjs-editor-resizer-label-bottom-middle = Внизу посередині зміна розміру
pdfjs-editor-resizer-label-bottom-left = Нижній лівий кут зміна розміру pdfjs-editor-resizer-label-bottom-left = Нижній лівий кут зміна розміру
pdfjs-editor-resizer-label-middle-left = Ліворуч посередині зміна розміру pdfjs-editor-resizer-label-middle-left = Ліворуч посередині зміна розміру
## Color picker ## Color picker

View File

@ -220,7 +220,7 @@ pdfjs-find-previous-button-label = Trước
pdfjs-find-next-button = pdfjs-find-next-button =
.title = Tìm cụm từ ở phần sau .title = Tìm cụm từ ở phần sau
pdfjs-find-next-button-label = Tiếp pdfjs-find-next-button-label = Tiếp
pdfjs-find-highlight-checkbox = Tô sáng tất cả pdfjs-find-highlight-checkbox = Đánh dấu tất cả
pdfjs-find-match-case-checkbox-label = Phân biệt hoa, thường pdfjs-find-match-case-checkbox-label = Phân biệt hoa, thường
pdfjs-find-match-diacritics-checkbox-label = Khớp dấu phụ pdfjs-find-match-diacritics-checkbox-label = Khớp dấu phụ
pdfjs-find-entire-word-checkbox-label = Toàn bộ từ pdfjs-find-entire-word-checkbox-label = Toàn bộ từ
@ -293,8 +293,9 @@ pdfjs-editor-ink-button-label = Vẽ
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = Thêm hoặc chỉnh sửa hình ảnh .title = Thêm hoặc chỉnh sửa hình ảnh
pdfjs-editor-stamp-button-label = Thêm hoặc chỉnh sửa hình ảnh pdfjs-editor-stamp-button-label = Thêm hoặc chỉnh sửa hình ảnh
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = Xóa .title = Đánh dấu
pdfjs-editor-highlight-button-label = Đánh dấu
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -318,6 +319,10 @@ pdfjs-editor-ink-opacity-input = Độ mờ
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = Thêm hình ảnh .title = Thêm hình ảnh
pdfjs-editor-stamp-add-image-button-label = Thêm hình ảnh pdfjs-editor-stamp-add-image-button-label = Thêm hình ảnh
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = Độ dày
pdfjs-editor-free-highlight-thickness-title =
.title = Thay đổi độ dày khi đánh dấu các mục không phải là văn bản
pdfjs-free-text = pdfjs-free-text =
.aria-label = Trình sửa văn bản .aria-label = Trình sửa văn bản
pdfjs-free-text-default-content = Bắt đầu nhập… pdfjs-free-text-default-content = Bắt đầu nhập…

View File

@ -293,8 +293,9 @@ pdfjs-editor-ink-button-label = 绘图
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = 添加或编辑图像 .title = 添加或编辑图像
pdfjs-editor-stamp-button-label = 添加或编辑图像 pdfjs-editor-stamp-button-label = 添加或编辑图像
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = 移除 .title = 高亮
pdfjs-editor-highlight-button-label = 高亮
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -318,6 +319,10 @@ pdfjs-editor-ink-opacity-input = 不透明度
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = 添加图像 .title = 添加图像
pdfjs-editor-stamp-add-image-button-label = 添加图像 pdfjs-editor-stamp-add-image-button-label = 添加图像
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = 粗细
pdfjs-editor-free-highlight-thickness-title =
.title = 更改高亮粗细(用于文本以外项目)
pdfjs-free-text = pdfjs-free-text =
.aria-label = 文本编辑器 .aria-label = 文本编辑器
pdfjs-free-text-default-content = 开始输入… pdfjs-free-text-default-content = 开始输入…

View File

@ -293,8 +293,9 @@ pdfjs-editor-ink-button-label = 繪圖
pdfjs-editor-stamp-button = pdfjs-editor-stamp-button =
.title = 新增或編輯圖片 .title = 新增或編輯圖片
pdfjs-editor-stamp-button-label = 新增或編輯圖片 pdfjs-editor-stamp-button-label = 新增或編輯圖片
pdfjs-editor-remove-button = pdfjs-editor-highlight-button =
.title = 移除 .title = 強調
pdfjs-editor-highlight-button-label = 強調
## Remove button for the various kind of editor. ## Remove button for the various kind of editor.
@ -318,6 +319,10 @@ pdfjs-editor-ink-opacity-input = 透​明度
pdfjs-editor-stamp-add-image-button = pdfjs-editor-stamp-add-image-button =
.title = 新增圖片 .title = 新增圖片
pdfjs-editor-stamp-add-image-button-label = 新增圖片 pdfjs-editor-stamp-add-image-button-label = 新增圖片
# This refers to the thickness of the line used for free highlighting (not bound to text)
pdfjs-editor-free-highlight-thickness-input = 線條粗細
pdfjs-editor-free-highlight-thickness-title =
.title = 更改強調文字以外的項目時的線條粗細
pdfjs-free-text = pdfjs-free-text =
.aria-label = 文本編輯器 .aria-label = 文本編輯器
pdfjs-free-text-default-content = 開始打字… pdfjs-free-text-default-content = 開始打字…

2129
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,34 +2,34 @@
"name": "pdf.js", "name": "pdf.js",
"type": "module", "type": "module",
"devDependencies": { "devDependencies": {
"@babel/core": "^7.23.6", "@babel/core": "^7.23.9",
"@babel/preset-env": "^7.23.6", "@babel/preset-env": "^7.23.9",
"@babel/runtime": "^7.23.6", "@babel/runtime": "^7.23.9",
"@fluent/bundle": "^0.18.0", "@fluent/bundle": "^0.18.0",
"@fluent/dom": "^0.9.0", "@fluent/dom": "^0.9.0",
"@javascript-obfuscator/escodegen": "2.3.0",
"@jazzer.js/core": "^2.1.0", "@jazzer.js/core": "^2.1.0",
"acorn": "^8.11.2", "autoprefixer": "^10.4.17",
"autoprefixer": "^10.4.16",
"babel-loader": "^9.1.3", "babel-loader": "^9.1.3",
"caniuse-lite": "^1.0.30001571", "caniuse-lite": "^1.0.30001587",
"canvas": "^2.11.2", "canvas": "^2.11.2",
"core-js": "^3.34.0", "core-js": "^3.36.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-config-prettier": "^8.10.0", "eslint-config-prettier": "^8.10.0",
"eslint-plugin-fetch-options": "^0.0.5", "eslint-plugin-fetch-options": "^0.0.5",
"eslint-plugin-html": "^7.1.0", "eslint-plugin-html": "^7.1.0",
"eslint-plugin-import": "^2.29.1", "eslint-plugin-import": "^2.29.1",
"eslint-plugin-jasmine": "^4.1.3",
"eslint-plugin-json": "^3.1.0", "eslint-plugin-json": "^3.1.0",
"eslint-plugin-mozilla": "^3.3.2", "eslint-plugin-mozilla": "^3.3.2",
"eslint-plugin-no-unsanitized": "^4.0.2", "eslint-plugin-no-unsanitized": "^4.0.2",
"eslint-plugin-prettier": "^5.1.1", "eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-sort-exports": "^0.8.0", "eslint-plugin-sort-exports": "^0.9.1",
"eslint-plugin-unicorn": "^50.0.1", "eslint-plugin-unicorn": "^51.0.1",
"globals": "^13.24.0", "globals": "^14.0.0",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-postcss": "^9.0.1", "gulp-cli": "^2.3.0",
"gulp-postcss": "^10.0.0",
"gulp-rename": "^2.0.0", "gulp-rename": "^2.0.0",
"gulp-replace": "^1.1.4", "gulp-replace": "^1.1.4",
"gulp-zip": "^6.0.0", "gulp-zip": "^6.0.0",
@ -41,25 +41,25 @@
"needle": "^3.3.1", "needle": "^3.3.1",
"path2d-polyfill": "^2.0.1", "path2d-polyfill": "^2.0.1",
"pngjs": "^7.0.0", "pngjs": "^7.0.0",
"postcss": "^8.4.32", "postcss": "^8.4.35",
"postcss-dark-theme-class": "^1.1.0", "postcss-dark-theme-class": "^1.2.1",
"postcss-dir-pseudo-class": "^8.0.1", "postcss-dir-pseudo-class": "^8.0.1",
"postcss-discard-comments": "^6.0.1", "postcss-discard-comments": "^6.0.1",
"postcss-nesting": "^12.0.2", "postcss-nesting": "^12.0.2",
"prettier": "^3.1.1", "prettier": "^3.2.5",
"puppeteer": "^21.6.1", "puppeteer": "^22.3.0",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"streamqueue": "^1.1.2", "streamqueue": "^1.1.2",
"stylelint": "^16.0.2", "stylelint": "^16.2.1",
"stylelint-prettier": "^5.0.0", "stylelint-prettier": "^5.0.0",
"terser": "^5.26.0", "terser-webpack-plugin": "^5.3.10",
"through2": "^4.0.2", "through2": "^4.0.2",
"tsc-alias": "^1.8.8", "tsc-alias": "^1.8.8",
"ttest": "^4.0.0", "ttest": "^4.0.0",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"typogr": "^0.6.8", "typogr": "^0.6.8",
"vinyl": "^3.0.0", "vinyl": "^3.0.0",
"webpack": "^5.89.0", "webpack": "^5.90.2",
"webpack-stream": "^7.0.0", "webpack-stream": "^7.0.0",
"wintersmith": "^2.5.0", "wintersmith": "^2.5.0",
"yargs": "^17.7.2" "yargs": "^17.7.2"

View File

@ -1,5 +1,5 @@
{ {
"stableVersion": "4.0.269", "stableVersion": "4.0.379",
"baseVersion": "0edc490e1beeb9fea62162738d9effef30c70af7", "baseVersion": "56ca2fd65858bf0045734fae11c295e290728463",
"versionPrefix": "4.0." "versionPrefix": "4.1."
} }

View File

@ -79,6 +79,7 @@ class AnnotationFactory {
// with "GoToE" actions, from throwing and thus breaking parsing: // with "GoToE" actions, from throwing and thus breaking parsing:
pdfManager.ensureCatalog("attachments"), pdfManager.ensureCatalog("attachments"),
]).then( ]).then(
// eslint-disable-next-line arrow-body-style
([acroForm, xfaDatasets, structTreeRoot, baseUrl, attachments]) => { ([acroForm, xfaDatasets, structTreeRoot, baseUrl, attachments]) => {
return { return {
pdfManager, pdfManager,
@ -355,13 +356,19 @@ class AnnotationFactory {
); );
break; break;
case AnnotationEditorType.HIGHLIGHT: case AnnotationEditorType.HIGHLIGHT:
promises.push( if (annotation.quadPoints) {
HighlightAnnotation.createNewAnnotation( promises.push(
xref, HighlightAnnotation.createNewAnnotation(
annotation, xref,
dependencies annotation,
) dependencies
); )
);
} else {
promises.push(
InkAnnotation.createNewAnnotation(xref, annotation, dependencies)
);
}
break; break;
case AnnotationEditorType.INK: case AnnotationEditorType.INK:
promises.push( promises.push(
@ -439,16 +446,29 @@ class AnnotationFactory {
); );
break; break;
case AnnotationEditorType.HIGHLIGHT: case AnnotationEditorType.HIGHLIGHT:
promises.push( if (annotation.quadPoints) {
HighlightAnnotation.createNewPrintAnnotation( promises.push(
annotationGlobals, HighlightAnnotation.createNewPrintAnnotation(
xref, annotationGlobals,
annotation, xref,
{ annotation,
evaluatorOptions: options, {
} evaluatorOptions: options,
) }
); )
);
} else {
promises.push(
InkAnnotation.createNewPrintAnnotation(
annotationGlobals,
xref,
annotation,
{
evaluatorOptions: options,
}
)
);
}
break; break;
case AnnotationEditorType.INK: case AnnotationEditorType.INK:
promises.push( promises.push(
@ -1195,7 +1215,7 @@ class Annotation {
firstPosition ||= item.transform.slice(-2); firstPosition ||= item.transform.slice(-2);
buffer.push(item.str); buffer.push(item.str);
if (item.hasEOL) { if (item.hasEOL) {
text.push(buffer.join("")); text.push(buffer.join("").trimEnd());
buffer.length = 0; buffer.length = 0;
} }
} }
@ -1207,31 +1227,38 @@ class Annotation {
task, task,
resources, resources,
includeMarkedContent: true, includeMarkedContent: true,
keepWhiteSpace: true,
sink, sink,
viewBox, viewBox,
}); });
this.reset(); this.reset();
if (buffer.length) { if (buffer.length) {
text.push(buffer.join("")); text.push(buffer.join("").trimEnd());
} }
if (text.length > 1 || text[0]) { if (text.length > 1 || text[0]) {
const appearanceDict = this.appearance.dict; const appearanceDict = this.appearance.dict;
const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1]; this.data.textPosition = this._transformPoint(
const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0]; firstPosition,
const rect = this.data.rect; appearanceDict.getArray("BBox"),
const transform = getTransformMatrix(rect, bbox, matrix); appearanceDict.getArray("Matrix")
transform[4] -= rect[0]; );
transform[5] -= rect[1];
firstPosition = Util.applyTransform(firstPosition, transform);
firstPosition = Util.applyTransform(firstPosition, matrix);
this.data.textPosition = firstPosition;
this.data.textContent = text; this.data.textContent = text;
} }
} }
_transformPoint(coords, bbox, matrix) {
const { rect } = this.data;
bbox ||= [0, 0, 1, 1];
matrix ||= [1, 0, 0, 1, 0, 0];
const transform = getTransformMatrix(rect, bbox, matrix);
transform[4] -= rect[0];
transform[5] -= rect[1];
coords = Util.applyTransform(coords, transform);
return Util.applyTransform(coords, matrix);
}
/** /**
* Get field data for usage in JS sandbox. * Get field data for usage in JS sandbox.
* *
@ -2107,11 +2134,8 @@ class WidgetAnnotation extends Annotation {
value, value,
}; };
const encoder = val => { const encoder = val =>
return isAscii(val) isAscii(val) ? val : stringToUTF16String(val, /* bigEndian = */ true);
? val
: stringToUTF16String(val, /* bigEndian = */ true);
};
dict.set("V", Array.isArray(value) ? value.map(encoder) : encoder(value)); dict.set("V", Array.isArray(value) ? value.map(encoder) : encoder(value));
this.amendSavedDict(annotationStorage, dict); this.amendSavedDict(annotationStorage, dict);
@ -3660,6 +3684,10 @@ class LinkAnnotation extends Annotation {
const { dict, annotationGlobals } = params; const { dict, annotationGlobals } = params;
this.data.annotationType = AnnotationType.LINK; this.data.annotationType = AnnotationType.LINK;
// A link is never rendered on the main canvas so we must render its HTML
// version.
this.data.noHTML = false;
const quadPoints = getQuadPoints(dict, this.rectangle); const quadPoints = getQuadPoints(dict, this.rectangle);
if (quadPoints) { if (quadPoints) {
this.data.quadPoints = quadPoints; this.data.quadPoints = quadPoints;
@ -3767,7 +3795,9 @@ class FreeTextAnnotation extends MarkupAnnotation {
const { evaluatorOptions, xref } = params; const { evaluatorOptions, xref } = params;
this.data.annotationType = AnnotationType.FREETEXT; this.data.annotationType = AnnotationType.FREETEXT;
this.setDefaultAppearance(params); this.setDefaultAppearance(params);
if (this.appearance) { this._hasAppearance = !!this.appearance;
if (this._hasAppearance) {
const { fontColor, fontSize } = parseAppearanceStream( const { fontColor, fontSize } = parseAppearanceStream(
this.appearance, this.appearance,
evaluatorOptions, evaluatorOptions,
@ -3775,29 +3805,42 @@ class FreeTextAnnotation extends MarkupAnnotation {
); );
this.data.defaultAppearanceData.fontColor = fontColor; this.data.defaultAppearanceData.fontColor = fontColor;
this.data.defaultAppearanceData.fontSize = fontSize || 10; this.data.defaultAppearanceData.fontSize = fontSize || 10;
} else if (this._isOffscreenCanvasSupported) { } else {
const strokeAlpha = params.dict.get("CA");
const fakeUnicodeFont = new FakeUnicodeFont(xref, "sans-serif");
this.data.defaultAppearanceData.fontSize ||= 10; this.data.defaultAppearanceData.fontSize ||= 10;
const { fontColor, fontSize } = this.data.defaultAppearanceData; const { fontColor, fontSize } = this.data.defaultAppearanceData;
this.appearance = fakeUnicodeFont.createAppearance( if (this._contents.str) {
this._contents.str, this.data.textContent = this._contents.str
this.rectangle, .split(/\r\n?|\n/)
this.rotation, .map(line => line.trimEnd());
fontSize, const { coords, bbox, matrix } = FakeUnicodeFont.getFirstPositionInfo(
fontColor, this.rectangle,
strokeAlpha this.rotation,
); fontSize
this._streams.push(this.appearance, FakeUnicodeFont.toUnicodeStream); );
} else { this.data.textPosition = this._transformPoint(coords, bbox, matrix);
warn( }
"FreeTextAnnotation: OffscreenCanvas is not supported, annotation may not render correctly." if (this._isOffscreenCanvasSupported) {
); const strokeAlpha = params.dict.get("CA");
const fakeUnicodeFont = new FakeUnicodeFont(xref, "sans-serif");
this.appearance = fakeUnicodeFont.createAppearance(
this._contents.str,
this.rectangle,
this.rotation,
fontSize,
fontColor,
strokeAlpha
);
this._streams.push(this.appearance);
} else {
warn(
"FreeTextAnnotation: OffscreenCanvas is not supported, annotation may not render correctly."
);
}
} }
} }
get hasTextContent() { get hasTextContent() {
return !!this.appearance; return this._hasAppearance;
} }
static createNewDict(annotation, xref, { apRef, ap }) { static createNewDict(annotation, xref, { apRef, ap }) {
@ -4318,19 +4361,25 @@ class InkAnnotation extends MarkupAnnotation {
} }
static createNewDict(annotation, xref, { apRef, ap }) { static createNewDict(annotation, xref, { apRef, ap }) {
const { color, opacity, paths, rect, rotation, thickness } = annotation; const { color, opacity, paths, outlines, rect, rotation, thickness } =
annotation;
const ink = new Dict(xref); const ink = new Dict(xref);
ink.set("Type", Name.get("Annot")); ink.set("Type", Name.get("Annot"));
ink.set("Subtype", Name.get("Ink")); ink.set("Subtype", Name.get("Ink"));
ink.set("CreationDate", `D:${getModificationDate()}`); ink.set("CreationDate", `D:${getModificationDate()}`);
ink.set("Rect", rect); ink.set("Rect", rect);
ink.set( ink.set("InkList", outlines?.points || paths.map(p => p.points));
"InkList",
paths.map(p => p.points)
);
ink.set("F", 4); ink.set("F", 4);
ink.set("Rotate", rotation); ink.set("Rotate", rotation);
if (outlines) {
// Free highlight.
// There's nothing about this in the spec, but it's used when highlighting
// in Edge's viewer. Acrobat takes into account this parameter to indicate
// that the Ink is used for highlighting.
ink.set("IT", Name.get("InkHighlight"));
}
// Line thickness. // Line thickness.
const bs = new Dict(xref); const bs = new Dict(xref);
ink.set("BS", bs); ink.set("BS", bs);
@ -4358,6 +4407,13 @@ class InkAnnotation extends MarkupAnnotation {
} }
static async createNewAppearanceStream(annotation, xref, params) { static async createNewAppearanceStream(annotation, xref, params) {
if (annotation.outlines) {
return this.createNewAppearanceStreamForHighlight(
annotation,
xref,
params
);
}
const { color, rect, paths, thickness, opacity } = annotation; const { color, rect, paths, thickness, opacity } = annotation;
const appearanceBuffer = [ const appearanceBuffer = [
@ -4375,14 +4431,20 @@ class InkAnnotation extends MarkupAnnotation {
buffer.push( buffer.push(
`${numberToString(bezier[0])} ${numberToString(bezier[1])} m` `${numberToString(bezier[0])} ${numberToString(bezier[1])} m`
); );
for (let i = 2, ii = bezier.length; i < ii; i += 6) { if (bezier.length === 2) {
const curve = bezier buffer.push(
.slice(i, i + 6) `${numberToString(bezier[0])} ${numberToString(bezier[1])} l S`
.map(numberToString) );
.join(" "); } else {
buffer.push(`${curve} c`); for (let i = 2, ii = bezier.length; i < ii; i += 6) {
const curve = bezier
.slice(i, i + 6)
.map(numberToString)
.join(" ");
buffer.push(`${curve} c`);
}
buffer.push("S");
} }
buffer.push("S");
appearanceBuffer.push(buffer.join("\n")); appearanceBuffer.push(buffer.join("\n"));
} }
const appearance = appearanceBuffer.join("\n"); const appearance = appearanceBuffer.join("\n");
@ -4410,6 +4472,65 @@ class InkAnnotation extends MarkupAnnotation {
return ap; return ap;
} }
static async createNewAppearanceStreamForHighlight(annotation, xref, params) {
const {
color,
rect,
outlines: { outline },
opacity,
} = annotation;
const appearanceBuffer = [
`${getPdfColor(color, /* isFill */ true)}`,
"/R0 gs",
];
appearanceBuffer.push(
`${numberToString(outline[4])} ${numberToString(outline[5])} m`
);
for (let i = 6, ii = outline.length; i < ii; i += 6) {
if (isNaN(outline[i]) || outline[i] === null) {
appearanceBuffer.push(
`${numberToString(outline[i + 4])} ${numberToString(
outline[i + 5]
)} l`
);
} else {
const curve = outline
.slice(i, i + 6)
.map(numberToString)
.join(" ");
appearanceBuffer.push(`${curve} c`);
}
}
appearanceBuffer.push("h f");
const appearance = appearanceBuffer.join("\n");
const appearanceStreamDict = new Dict(xref);
appearanceStreamDict.set("FormType", 1);
appearanceStreamDict.set("Subtype", Name.get("Form"));
appearanceStreamDict.set("Type", Name.get("XObject"));
appearanceStreamDict.set("BBox", rect);
appearanceStreamDict.set("Length", appearance.length);
const resources = new Dict(xref);
const extGState = new Dict(xref);
resources.set("ExtGState", extGState);
appearanceStreamDict.set("Resources", resources);
const r0 = new Dict(xref);
extGState.set("R0", r0);
r0.set("BM", Name.get("Multiply"));
if (opacity !== 1) {
r0.set("ca", opacity);
r0.set("Type", Name.get("ExtGState"));
}
const ap = new StringStream(appearance);
ap.dict = appearanceStreamDict;
return ap;
}
} }
class HighlightAnnotation extends MarkupAnnotation { class HighlightAnnotation extends MarkupAnnotation {
@ -4705,9 +4826,7 @@ class StampAnnotation extends MarkupAnnotation {
const jpegBufferPromise = canvas const jpegBufferPromise = canvas
.convertToBlob({ type: "image/jpeg", quality: 1 }) .convertToBlob({ type: "image/jpeg", quality: 1 })
.then(blob => { .then(blob => blob.arrayBuffer());
return blob.arrayBuffer();
});
const xobjectName = Name.get("XObject"); const xobjectName = Name.get("XObject");
const imageName = Name.get("Image"); const imageName = Name.get("Image");
@ -4845,4 +4964,5 @@ export {
getQuadPoints, getQuadPoints,
MarkupAnnotation, MarkupAnnotation,
PopupAnnotation, PopupAnnotation,
WidgetAnnotation,
}; };

View File

@ -445,20 +445,10 @@ class Catalog {
continue; continue;
} }
groupRefs.put(groupRef); groupRefs.put(groupRef);
const group = this.xref.fetch(groupRef);
groups.push({ groups.push(this.#readOptionalContentGroup(groupRef));
id: groupRef.toString(),
name:
typeof group.get("Name") === "string"
? stringToPDFString(group.get("Name"))
: null,
intent:
typeof group.get("Intent") === "string"
? stringToPDFString(group.get("Intent"))
: null,
});
} }
config = this._readOptionalContentConfig(defaultConfig, groupRefs); config = this.#readOptionalContentConfig(defaultConfig, groupRefs);
config.groups = groups; config.groups = groups;
} catch (ex) { } catch (ex) {
if (ex instanceof MissingDataException) { if (ex instanceof MissingDataException) {
@ -469,7 +459,65 @@ class Catalog {
return shadow(this, "optionalContentConfig", config); return shadow(this, "optionalContentConfig", config);
} }
_readOptionalContentConfig(config, contentGroupRefs) { #readOptionalContentGroup(groupRef) {
const group = this.xref.fetch(groupRef);
const obj = {
id: groupRef.toString(),
name: null,
intent: null,
usage: {
print: null,
view: null,
},
};
const name = group.get("Name");
if (typeof name === "string") {
obj.name = stringToPDFString(name);
}
let intent = group.getArray("Intent");
if (!Array.isArray(intent)) {
intent = [intent];
}
if (intent.every(i => i instanceof Name)) {
obj.intent = intent.map(i => i.name);
}
const usage = group.get("Usage");
if (!(usage instanceof Dict)) {
return obj;
}
const usageObj = obj.usage;
const print = usage.get("Print");
if (print instanceof Dict) {
const printState = print.get("PrintState");
if (printState instanceof Name) {
switch (printState.name) {
case "ON":
case "OFF":
usageObj.print = { printState: printState.name };
}
}
}
const view = usage.get("View");
if (view instanceof Dict) {
const viewState = view.get("ViewState");
if (viewState instanceof Name) {
switch (viewState.name) {
case "ON":
case "OFF":
usageObj.view = { viewState: viewState.name };
}
}
}
return obj;
}
#readOptionalContentConfig(config, contentGroupRefs) {
function parseOnOff(refs) { function parseOnOff(refs) {
const onParsed = []; const onParsed = [];
if (Array.isArray(refs)) { if (Array.isArray(refs)) {
@ -893,14 +941,13 @@ class Catalog {
case "PrintPageRange": case "PrintPageRange":
// The number of elements must be even. // The number of elements must be even.
if (Array.isArray(value) && value.length % 2 === 0) { if (Array.isArray(value) && value.length % 2 === 0) {
const isValid = value.every((page, i, arr) => { const isValid = value.every(
return ( (page, i, arr) =>
Number.isInteger(page) && Number.isInteger(page) &&
page > 0 && page > 0 &&
(i === 0 || page >= arr[i - 1]) && (i === 0 || page >= arr[i - 1]) &&
page <= this.numPages page <= this.numPages
); );
});
if (isValid) { if (isValid) {
prefValue = value; prefValue = value;
} }

View File

@ -691,9 +691,9 @@ async function createBuiltInCMap(name, fetchBuiltInCMap) {
const cMap = new CMap(true); const cMap = new CMap(true);
if (compressionType === CMapCompressionType.BINARY) { if (compressionType === CMapCompressionType.BINARY) {
return new BinaryCMapReader().process(cMapData, cMap, useCMap => { return new BinaryCMapReader().process(cMapData, cMap, useCMap =>
return extendCMap(cMap, fetchBuiltInCMap, useCMap); extendCMap(cMap, fetchBuiltInCMap, useCMap)
}); );
} }
if (compressionType === CMapCompressionType.NONE) { if (compressionType === CMapCompressionType.NONE) {
const lexer = new Lexer(new Stream(cMapData)); const lexer = new Lexer(new Stream(cMapData));

View File

@ -386,6 +386,17 @@ const XMLEntities = {
/* ' */ 0x27: "&apos;", /* ' */ 0x27: "&apos;",
}; };
function* codePointIter(str) {
for (let i = 0, ii = str.length; i < ii; i++) {
const char = str.codePointAt(i);
if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) {
// char is represented by two u16
i++;
}
yield char;
}
}
function encodeToXmlString(str) { function encodeToXmlString(str) {
const buffer = []; const buffer = [];
let start = 0; let start = 0;
@ -600,8 +611,22 @@ function getRotationMatrix(rotation, width, height) {
} }
} }
/**
* Get the number of bytes to use to represent the given positive integer.
* If n is zero, the function returns 0 which means that we don't need to waste
* a byte to represent it.
* @param {number} x - a positive integer.
* @returns {number}
*/
function getSizeInBytes(x) {
// n bits are required for numbers up to 2^n - 1.
// So for a number x, we need ceil(log2(1 + x)) bits.
return Math.ceil(Math.ceil(Math.log2(1 + x)) / 8);
}
export { export {
arrayBuffersToBytes, arrayBuffersToBytes,
codePointIter,
collectActions, collectActions,
encodeToXmlString, encodeToXmlString,
escapePDFName, escapePDFName,
@ -610,6 +635,7 @@ export {
getLookupTableFactory, getLookupTableFactory,
getNewAnnotationsMap, getNewAnnotationsMap,
getRotationMatrix, getRotationMatrix,
getSizeInBytes,
isAscii, isAscii,
isWhiteSpace, isWhiteSpace,
log2, log2,

View File

@ -13,13 +13,14 @@
* limitations under the License. * limitations under the License.
*/ */
import { Dict, Name } from "./primitives.js";
import { import {
codePointIter,
escapePDFName, escapePDFName,
getRotationMatrix, getRotationMatrix,
numberToString, numberToString,
stringToUTF16HexString, stringToUTF16HexString,
} from "./core_utils.js"; } from "./core_utils.js";
import { Dict, Name } from "./primitives.js";
import { import {
LINE_DESCENT_FACTOR, LINE_DESCENT_FACTOR,
LINE_FACTOR, LINE_FACTOR,
@ -251,35 +252,6 @@ class FakeUnicodeFont {
); );
} }
get toUnicodeRef() {
if (!FakeUnicodeFont._toUnicodeRef) {
const toUnicode = `/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (Adobe)
/Ordering (UCS) /Supplement 0 >> def
/CMapName /Adobe-Identity-UCS def
/CMapType 2 def
1 begincodespacerange
<0000> <FFFF>
endcodespacerange
1 beginbfrange
<0000> <FFFF> <0000>
endbfrange
endcmap CMapName currentdict /CMap defineresource pop end end`;
const toUnicodeStream = (FakeUnicodeFont.toUnicodeStream =
new StringStream(toUnicode));
const toUnicodeDict = new Dict(this.xref);
toUnicodeStream.dict = toUnicodeDict;
toUnicodeDict.set("Length", toUnicode.length);
FakeUnicodeFont._toUnicodeRef =
this.xref.getNewPersistentRef(toUnicodeStream);
}
return FakeUnicodeFont._toUnicodeRef;
}
get fontDescriptorRef() { get fontDescriptorRef() {
if (!FakeUnicodeFont._fontDescriptorRef) { if (!FakeUnicodeFont._fontDescriptorRef) {
const fontDescriptor = new Dict(this.xref); const fontDescriptor = new Dict(this.xref);
@ -350,7 +322,7 @@ endcmap CMapName currentdict /CMap defineresource pop end end`;
baseFont.set("Subtype", Name.get("Type0")); baseFont.set("Subtype", Name.get("Type0"));
baseFont.set("Encoding", Name.get("Identity-H")); baseFont.set("Encoding", Name.get("Identity-H"));
baseFont.set("DescendantFonts", [this.descendantFontRef]); baseFont.set("DescendantFonts", [this.descendantFontRef]);
baseFont.set("ToUnicode", this.toUnicodeRef); baseFont.set("ToUnicode", Name.get("Identity-H"));
return this.xref.getNewPersistentRef(baseFont); return this.xref.getNewPersistentRef(baseFont);
} }
@ -390,6 +362,26 @@ endcmap CMapName currentdict /CMap defineresource pop end end`;
return this.resources; return this.resources;
} }
static getFirstPositionInfo(rect, rotation, fontSize) {
// Get the position of the first char in the rect.
const [x1, y1, x2, y2] = rect;
let w = x2 - x1;
let h = y2 - y1;
if (rotation % 180 !== 0) {
[w, h] = [h, w];
}
const lineHeight = LINE_FACTOR * fontSize;
const lineDescent = LINE_DESCENT_FACTOR * fontSize;
return {
coords: [0, h + lineDescent - lineHeight],
bbox: [0, 0, w, h],
matrix:
rotation !== 0 ? getRotationMatrix(rotation, h, lineHeight) : undefined,
};
}
createAppearance(text, rect, rotation, fontSize, bgColor, strokeAlpha) { createAppearance(text, rect, rotation, fontSize, bgColor, strokeAlpha) {
const ctx = this._createContext(); const ctx = this._createContext();
const lines = []; const lines = [];
@ -400,8 +392,8 @@ endcmap CMapName currentdict /CMap defineresource pop end end`;
// languages, like arabic, it'd be wrong because of ligatures. // languages, like arabic, it'd be wrong because of ligatures.
const lineWidth = ctx.measureText(line).width; const lineWidth = ctx.measureText(line).width;
maxWidth = Math.max(maxWidth, lineWidth); maxWidth = Math.max(maxWidth, lineWidth);
for (const char of line.split("")) { for (const code of codePointIter(line)) {
const code = char.charCodeAt(0); const char = String.fromCodePoint(code);
let width = this.widths.get(code); let width = this.widths.get(code);
if (width === undefined) { if (width === undefined) {
const metrics = ctx.measureText(char); const metrics = ctx.measureText(char);

View File

@ -30,7 +30,11 @@ import {
Util, Util,
warn, warn,
} from "../shared/util.js"; } from "../shared/util.js";
import { AnnotationFactory, PopupAnnotation } from "./annotation.js"; import {
AnnotationFactory,
PopupAnnotation,
WidgetAnnotation,
} from "./annotation.js";
import { import {
collectActions, collectActions,
getInheritableProperty, getInheritableProperty,
@ -766,19 +770,26 @@ class Page {
} }
const sortedAnnotations = []; const sortedAnnotations = [];
let popupAnnotations; let popupAnnotations, widgetAnnotations;
// Ensure that PopupAnnotations are handled last, since they depend on // Ensure that PopupAnnotations are handled last, since they depend on
// their parent Annotation in the display layer; fixes issue 11362. // their parent Annotation in the display layer; fixes issue 11362.
for (const annotation of await Promise.all(annotationPromises)) { for (const annotation of await Promise.all(annotationPromises)) {
if (!annotation) { if (!annotation) {
continue; continue;
} }
if (annotation instanceof WidgetAnnotation) {
(widgetAnnotations ||= []).push(annotation);
continue;
}
if (annotation instanceof PopupAnnotation) { if (annotation instanceof PopupAnnotation) {
(popupAnnotations ||= []).push(annotation); (popupAnnotations ||= []).push(annotation);
continue; continue;
} }
sortedAnnotations.push(annotation); sortedAnnotations.push(annotation);
} }
if (widgetAnnotations) {
sortedAnnotations.push(...widgetAnnotations);
}
if (popupAnnotations) { if (popupAnnotations) {
sortedAnnotations.push(...popupAnnotations); sortedAnnotations.push(...popupAnnotations);
} }
@ -930,7 +941,14 @@ class PDFDocument {
// Find the end of the first object. // Find the end of the first object.
stream.reset(); stream.reset();
if (find(stream, ENDOBJ_SIGNATURE)) { if (find(stream, ENDOBJ_SIGNATURE)) {
startXRef = stream.pos + 6 - stream.start; stream.skip(6);
let ch = stream.peekByte();
while (isWhiteSpace(ch)) {
stream.pos++;
ch = stream.peekByte();
}
startXRef = stream.pos - stream.start;
} }
} else { } else {
// Find `startxref` by checking backwards from the end of the file. // Find `startxref` by checking backwards from the end of the file.
@ -1577,6 +1595,7 @@ class PDFDocument {
} else { } else {
promise = catalog.getPageDict(pageIndex); promise = catalog.getPageDict(pageIndex);
} }
// eslint-disable-next-line arrow-body-style
promise = promise.then(([pageDict, ref]) => { promise = promise.then(([pageDict, ref]) => {
return new Page({ return new Page({
pdfManager: this.pdfManager, pdfManager: this.pdfManager,

View File

@ -526,23 +526,22 @@ class PartialEvaluator {
const args = group ? [matrix, null] : [matrix, bbox]; const args = group ? [matrix, null] : [matrix, bbox];
operatorList.addOp(OPS.paintFormXObjectBegin, args); operatorList.addOp(OPS.paintFormXObjectBegin, args);
return this.getOperatorList({ await this.getOperatorList({
stream: xobj, stream: xobj,
task, task,
resources: dict.get("Resources") || resources, resources: dict.get("Resources") || resources,
operatorList, operatorList,
initialState, initialState,
}).then(function () {
operatorList.addOp(OPS.paintFormXObjectEnd, []);
if (group) {
operatorList.addOp(OPS.endGroup, [groupOptions]);
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
}
}); });
operatorList.addOp(OPS.paintFormXObjectEnd, []);
if (group) {
operatorList.addOp(OPS.endGroup, [groupOptions]);
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
}
} }
_sendImgData(objId, imgData, cacheGlobally = false) { _sendImgData(objId, imgData, cacheGlobally = false) {
@ -1007,7 +1006,7 @@ class PartialEvaluator {
}); });
} }
handleSetFont( async handleSetFont(
resources, resources,
fontArgs, fontArgs,
fontRef, fontRef,
@ -1019,40 +1018,33 @@ class PartialEvaluator {
) { ) {
const fontName = fontArgs?.[0] instanceof Name ? fontArgs[0].name : null; const fontName = fontArgs?.[0] instanceof Name ? fontArgs[0].name : null;
return this.loadFont( let translated = await this.loadFont(
fontName, fontName,
fontRef, fontRef,
resources, resources,
fallbackFontDict, fallbackFontDict,
cssFontInfo cssFontInfo
) );
.then(translated => {
if (!translated.font.isType3Font) {
return translated;
}
return translated
.loadType3Data(this, resources, task)
.then(function () {
// Add the dependencies to the parent operatorList so they are
// resolved before Type3 operatorLists are executed synchronously.
operatorList.addDependencies(translated.type3Dependencies);
return translated; if (translated.font.isType3Font) {
}) try {
.catch(reason => { await translated.loadType3Data(this, resources, task);
return new TranslatedFont({ // Add the dependencies to the parent operatorList so they are
loadedName: "g_font_error", // resolved before Type3 operatorLists are executed synchronously.
font: new ErrorFont(`Type3 font load error: ${reason}`), operatorList.addDependencies(translated.type3Dependencies);
dict: translated.font, } catch (reason) {
evaluatorOptions: this.options, translated = new TranslatedFont({
}); loadedName: "g_font_error",
}); font: new ErrorFont(`Type3 font load error: ${reason}`),
}) dict: translated.font,
.then(translated => { evaluatorOptions: this.options,
state.font = translated.font; });
translated.send(this.handler); }
return translated.loadedName; }
});
state.font = translated.font;
translated.send(this.handler);
return translated.loadedName;
} }
handleText(chars, state) { handleText(chars, state) {
@ -1129,8 +1121,8 @@ class PartialEvaluator {
case "Font": case "Font":
isSimpleGState = false; isSimpleGState = false;
promise = promise.then(() => { promise = promise.then(() =>
return this.handleSetFont( this.handleSetFont(
resources, resources,
null, null,
value[0], value[0],
@ -1140,8 +1132,8 @@ class PartialEvaluator {
).then(function (loadedName) { ).then(function (loadedName) {
operatorList.addDependency(loadedName); operatorList.addDependency(loadedName);
gStateObj.push([key, [loadedName, value[1]]]); gStateObj.push([key, [loadedName, value[1]]]);
}); })
}); );
break; break;
case "BM": case "BM":
gStateObj.push([key, normalizeBlendMode(value)]); gStateObj.push([key, normalizeBlendMode(value)]);
@ -1154,16 +1146,16 @@ class PartialEvaluator {
if (value instanceof Dict) { if (value instanceof Dict) {
isSimpleGState = false; isSimpleGState = false;
promise = promise.then(() => { promise = promise.then(() =>
return this.handleSMask( this.handleSMask(
value, value,
resources, resources,
operatorList, operatorList,
task, task,
stateManager, stateManager,
localColorSpaceCache localColorSpaceCache
); )
}); );
gStateObj.push([key, true]); gStateObj.push([key, true]);
} else { } else {
warn("Unsupported SMask type"); warn("Unsupported SMask type");
@ -1196,15 +1188,15 @@ class PartialEvaluator {
break; break;
} }
} }
return promise.then(function () { await promise;
if (gStateObj.length > 0) {
operatorList.addOp(OPS.setGState, [gStateObj]);
}
if (isSimpleGState) { if (gStateObj.length > 0) {
localGStateCache.set(cacheKey, gStateRef, gStateObj); operatorList.addOp(OPS.setGState, [gStateObj]);
} }
});
if (isSimpleGState) {
localGStateCache.set(cacheKey, gStateRef, gStateObj);
}
} }
loadFont( loadFont(
@ -1214,6 +1206,7 @@ class PartialEvaluator {
fallbackFontDict = null, fallbackFontDict = null,
cssFontInfo = null cssFontInfo = null
) { ) {
// eslint-disable-next-line arrow-body-style
const errorFont = async () => { const errorFont = async () => {
return new TranslatedFont({ return new TranslatedFont({
loadedName: "g_font_error", loadedName: "g_font_error",
@ -1393,17 +1386,17 @@ class PartialEvaluator {
const y = args[1] + args[3]; const y = args[1] + args[3];
minMax = [ minMax = [
Math.min(args[0], x), Math.min(args[0], x),
Math.max(args[0], x),
Math.min(args[1], y), Math.min(args[1], y),
Math.max(args[0], x),
Math.max(args[1], y), Math.max(args[1], y),
]; ];
break; break;
case OPS.moveTo: case OPS.moveTo:
case OPS.lineTo: case OPS.lineTo:
minMax = [args[0], args[0], args[1], args[1]]; minMax = [args[0], args[1], args[0], args[1]];
break; break;
default: default:
minMax = [Infinity, -Infinity, Infinity, -Infinity]; minMax = [Infinity, Infinity, -Infinity, -Infinity];
break; break;
} }
operatorList.addOp(OPS.constructPath, [[fn], args, minMax]); operatorList.addOp(OPS.constructPath, [[fn], args, minMax]);
@ -1427,15 +1420,15 @@ class PartialEvaluator {
const x = args[0] + args[2]; const x = args[0] + args[2];
const y = args[1] + args[3]; const y = args[1] + args[3];
minMax[0] = Math.min(minMax[0], args[0], x); minMax[0] = Math.min(minMax[0], args[0], x);
minMax[1] = Math.max(minMax[1], args[0], x); minMax[1] = Math.min(minMax[1], args[1], y);
minMax[2] = Math.min(minMax[2], args[1], y); minMax[2] = Math.max(minMax[2], args[0], x);
minMax[3] = Math.max(minMax[3], args[1], y); minMax[3] = Math.max(minMax[3], args[1], y);
break; break;
case OPS.moveTo: case OPS.moveTo:
case OPS.lineTo: case OPS.lineTo:
minMax[0] = Math.min(minMax[0], args[0]); minMax[0] = Math.min(minMax[0], args[0]);
minMax[1] = Math.max(minMax[1], args[0]); minMax[1] = Math.min(minMax[1], args[1]);
minMax[2] = Math.min(minMax[2], args[1]); minMax[2] = Math.max(minMax[2], args[0]);
minMax[3] = Math.max(minMax[3], args[1]); minMax[3] = Math.max(minMax[3], args[1]);
break; break;
} }
@ -2191,6 +2184,7 @@ class PartialEvaluator {
case OPS.beginMarkedContentProps: case OPS.beginMarkedContentProps:
if (!(args[0] instanceof Name)) { if (!(args[0] instanceof Name)) {
warn(`Expected name for beginMarkedContentProps arg0=${args[0]}`); warn(`Expected name for beginMarkedContentProps arg0=${args[0]}`);
operatorList.addOp(OPS.beginMarkedContentProps, ["OC", null]);
continue; continue;
} }
if (args[0].name === "OC") { if (args[0].name === "OC") {
@ -2211,6 +2205,10 @@ class PartialEvaluator {
warn( warn(
`getOperatorList - ignoring beginMarkedContentProps: "${reason}".` `getOperatorList - ignoring beginMarkedContentProps: "${reason}".`
); );
operatorList.addOp(OPS.beginMarkedContentProps, [
"OC",
null,
]);
return; return;
} }
throw reason; throw reason;
@ -2281,6 +2279,7 @@ class PartialEvaluator {
viewBox, viewBox,
markedContentData = null, markedContentData = null,
disableNormalization = false, disableNormalization = false,
keepWhiteSpace = false,
}) { }) {
// Ensure that `resources`/`stateManager` is correctly initialized, // Ensure that `resources`/`stateManager` is correctly initialized,
// even if the provided parameter is e.g. `null`. // even if the provided parameter is e.g. `null`.
@ -2347,11 +2346,12 @@ class PartialEvaluator {
twoLastChars[twoLastCharsPos] = char; twoLastChars[twoLastCharsPos] = char;
twoLastCharsPos = nextPos; twoLastCharsPos = nextPos;
return ret; return !keepWhiteSpace && ret;
} }
function shouldAddWhitepsace() { function shouldAddWhitepsace() {
return ( return (
!keepWhiteSpace &&
twoLastChars[twoLastCharsPos] !== " " && twoLastChars[twoLastCharsPos] !== " " &&
twoLastChars[(twoLastCharsPos + 1) % 2] === " " twoLastChars[(twoLastCharsPos + 1) % 2] === " "
); );
@ -2554,29 +2554,21 @@ class PartialEvaluator {
}; };
} }
function handleSetFont(fontName, fontRef) { async function handleSetFont(fontName, fontRef) {
return self const translated = await self.loadFont(fontName, fontRef, resources);
.loadFont(fontName, fontRef, resources)
.then(function (translated) { if (translated.font.isType3Font) {
if (!translated.font.isType3Font) { try {
return translated; await translated.loadType3Data(self, resources, task);
} } catch {
return translated // Ignore Type3-parsing errors, since we only use `loadType3Data`
.loadType3Data(self, resources, task) // here to ensure that we'll always obtain a useful /FontBBox.
.catch(function () { }
// Ignore Type3-parsing errors, since we only use `loadType3Data` }
// here to ensure that we'll always obtain a useful /FontBBox.
}) textState.loadedName = translated.loadedName;
.then(function () { textState.font = translated.font;
return translated; textState.fontMatrix = translated.font.fontMatrix || FONT_IDENTITY_MATRIX;
});
})
.then(function (translated) {
textState.loadedName = translated.loadedName;
textState.font = translated.font;
textState.fontMatrix =
translated.font.fontMatrix || FONT_IDENTITY_MATRIX;
});
} }
function applyInverseRotation(x, y, matrix) { function applyInverseRotation(x, y, matrix) {
@ -2814,6 +2806,10 @@ class PartialEvaluator {
} }
} }
if (keepWhiteSpace) {
compareWithLastPosition(0);
}
return; return;
} }
@ -2836,7 +2832,7 @@ class PartialEvaluator {
} }
let scaledDim = glyphWidth * scale; let scaledDim = glyphWidth * scale;
if (category.isWhitespace) { if (!keepWhiteSpace && category.isWhitespace) {
// Don't push a " " in the textContentItem // Don't push a " " in the textContentItem
// (except when it's between two non-spaces chars), // (except when it's between two non-spaces chars),
// it will be done (if required) in next call to // it will be done (if required) in next call to
@ -3272,6 +3268,7 @@ class PartialEvaluator {
viewBox, viewBox,
markedContentData, markedContentData,
disableNormalization, disableNormalization,
keepWhiteSpace,
}) })
.then(function () { .then(function () {
if (!sinkWrapper.enqueueInvoked) { if (!sinkWrapper.enqueueInvoked) {
@ -3436,13 +3433,11 @@ class PartialEvaluator {
}); });
} }
extractDataStructures(dict, baseDict, properties) { async extractDataStructures(dict, properties) {
const xref = this.xref; const xref = this.xref;
let cidToGidBytes; let cidToGidBytes;
// 9.10.2 // 9.10.2
const toUnicodePromise = this.readToUnicode( const toUnicodePromise = this.readToUnicode(properties.toUnicode);
properties.toUnicode || dict.get("ToUnicode") || baseDict.get("ToUnicode")
);
if (properties.composite) { if (properties.composite) {
// CIDSystemInfo helps to match CID to glyphs // CIDSystemInfo helps to match CID to glyphs
@ -3562,21 +3557,19 @@ class PartialEvaluator {
properties.baseEncodingName = baseEncodingName; properties.baseEncodingName = baseEncodingName;
properties.hasEncoding = !!baseEncodingName || differences.length > 0; properties.hasEncoding = !!baseEncodingName || differences.length > 0;
properties.dict = dict; properties.dict = dict;
return toUnicodePromise
.then(readToUnicode => { properties.toUnicode = await toUnicodePromise;
properties.toUnicode = readToUnicode;
return this.buildToUnicode(properties); const builtToUnicode = await this.buildToUnicode(properties);
}) properties.toUnicode = builtToUnicode;
.then(builtToUnicode => {
properties.toUnicode = builtToUnicode; if (cidToGidBytes) {
if (cidToGidBytes) { properties.cidToGidMap = this.readCidToGidMap(
properties.cidToGidMap = this.readCidToGidMap( cidToGidBytes,
cidToGidBytes, builtToUnicode
builtToUnicode );
); }
} return properties;
return properties;
});
} }
/** /**
@ -3726,7 +3719,9 @@ class PartialEvaluator {
properties.composite && properties.composite &&
((properties.cMap.builtInCMap && ((properties.cMap.builtInCMap &&
!(properties.cMap instanceof IdentityCMap)) || !(properties.cMap instanceof IdentityCMap)) ||
(properties.cidSystemInfo.registry === "Adobe" && // The font is supposed to have a CIDSystemInfo dictionary, but some
// PDFs don't include it (fixes issue 17689), hence the `?'.
(properties.cidSystemInfo?.registry === "Adobe" &&
(properties.cidSystemInfo.ordering === "GB1" || (properties.cidSystemInfo.ordering === "GB1" ||
properties.cidSystemInfo.ordering === "CNS1" || properties.cidSystemInfo.ordering === "CNS1" ||
properties.cidSystemInfo.ordering === "Japan1" || properties.cidSystemInfo.ordering === "Japan1" ||
@ -3775,70 +3770,70 @@ class PartialEvaluator {
return new IdentityToUnicodeMap(properties.firstChar, properties.lastChar); return new IdentityToUnicodeMap(properties.firstChar, properties.lastChar);
} }
readToUnicode(cmapObj) { async readToUnicode(cmapObj) {
if (!cmapObj) { if (!cmapObj) {
return Promise.resolve(null); return null;
} }
if (cmapObj instanceof Name) { if (cmapObj instanceof Name) {
return CMapFactory.create({ const cmap = await CMapFactory.create({
encoding: cmapObj, encoding: cmapObj,
fetchBuiltInCMap: this._fetchBuiltInCMapBound, fetchBuiltInCMap: this._fetchBuiltInCMapBound,
useCMap: null, useCMap: null,
}).then(function (cmap) { });
if (cmap instanceof IdentityCMap) {
return new IdentityToUnicodeMap(0, 0xffff);
}
return new ToUnicodeMap(cmap.getMap());
}
if (cmapObj instanceof BaseStream) {
try {
const cmap = await CMapFactory.create({
encoding: cmapObj,
fetchBuiltInCMap: this._fetchBuiltInCMapBound,
useCMap: null,
});
if (cmap instanceof IdentityCMap) { if (cmap instanceof IdentityCMap) {
return new IdentityToUnicodeMap(0, 0xffff); return new IdentityToUnicodeMap(0, 0xffff);
} }
return new ToUnicodeMap(cmap.getMap()); const map = new Array(cmap.length);
}); // Convert UTF-16BE
} else if (cmapObj instanceof BaseStream) { // NOTE: cmap can be a sparse array, so use forEach instead of
return CMapFactory.create({ // `for(;;)` to iterate over all keys.
encoding: cmapObj, cmap.forEach(function (charCode, token) {
fetchBuiltInCMap: this._fetchBuiltInCMapBound, // Some cmaps contain *only* CID characters (fixes issue9367.pdf).
useCMap: null, if (typeof token === "number") {
}).then( map[charCode] = String.fromCodePoint(token);
function (cmap) { return;
if (cmap instanceof IdentityCMap) {
return new IdentityToUnicodeMap(0, 0xffff);
} }
const map = new Array(cmap.length); const str = [];
// Convert UTF-16BE for (let k = 0; k < token.length; k += 2) {
// NOTE: cmap can be a sparse array, so use forEach instead of const w1 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
// `for(;;)` to iterate over all keys. if ((w1 & 0xf800) !== 0xd800) {
cmap.forEach(function (charCode, token) { // w1 < 0xD800 || w1 > 0xDFFF
// Some cmaps contain *only* CID characters (fixes issue9367.pdf). str.push(w1);
if (typeof token === "number") { continue;
map[charCode] = String.fromCodePoint(token);
return;
} }
const str = []; k += 2;
for (let k = 0; k < token.length; k += 2) { const w2 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
const w1 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1); str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
if ((w1 & 0xf800) !== 0xd800) {
// w1 < 0xD800 || w1 > 0xDFFF
str.push(w1);
continue;
}
k += 2;
const w2 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
}
map[charCode] = String.fromCodePoint(...str);
});
return new ToUnicodeMap(map);
},
reason => {
if (reason instanceof AbortException) {
return null;
} }
if (this.options.ignoreErrors) { map[charCode] = String.fromCodePoint(...str);
warn(`readToUnicode - ignoring ToUnicode data: "${reason}".`); });
return null; return new ToUnicodeMap(map);
} } catch (reason) {
throw reason; if (reason instanceof AbortException) {
return null;
} }
); if (this.options.ignoreErrors) {
warn(`readToUnicode - ignoring ToUnicode data: "${reason}".`);
return null;
}
throw reason;
}
} }
return Promise.resolve(null); return null;
} }
readCidToGidMap(glyphsData, toUnicode) { readCidToGidMap(glyphsData, toUnicode) {
@ -3967,7 +3962,7 @@ class PartialEvaluator {
isSerifFont(baseFontName) { isSerifFont(baseFontName) {
// Simulating descriptor flags attribute // Simulating descriptor flags attribute
const fontNameWoStyle = baseFontName.split("-")[0]; const fontNameWoStyle = baseFontName.split("-", 1)[0];
return ( return (
fontNameWoStyle in getSerifFonts() || /serif/gi.test(fontNameWoStyle) fontNameWoStyle in getSerifFonts() || /serif/gi.test(fontNameWoStyle)
); );
@ -4027,7 +4022,7 @@ class PartialEvaluator {
} }
let composite = false; let composite = false;
let hash, toUnicode; let hash;
if (type.name === "Type0") { if (type.name === "Type0") {
// If font is a composite // If font is a composite
// - get the descendant font // - get the descendant font
@ -4052,6 +4047,8 @@ class PartialEvaluator {
const firstChar = dict.get("FirstChar") || 0, const firstChar = dict.get("FirstChar") || 0,
lastChar = dict.get("LastChar") || (composite ? 0xffff : 0xff); lastChar = dict.get("LastChar") || (composite ? 0xffff : 0xff);
const descriptor = dict.get("FontDescriptor"); const descriptor = dict.get("FontDescriptor");
const toUnicode = dict.get("ToUnicode") || baseDict.get("ToUnicode");
if (descriptor) { if (descriptor) {
hash = new MurmurHash3_64(); hash = new MurmurHash3_64();
@ -4089,7 +4086,6 @@ class PartialEvaluator {
hash.update(`${firstChar}-${lastChar}`); // Fixes issue10665_reduced.pdf hash.update(`${firstChar}-${lastChar}`); // Fixes issue10665_reduced.pdf
toUnicode = dict.get("ToUnicode") || baseDict.get("ToUnicode");
if (toUnicode instanceof BaseStream) { if (toUnicode instanceof BaseStream) {
const stream = toUnicode.str || toUnicode; const stream = toUnicode.str || toUnicode;
const uint8array = stream.buffer const uint8array = stream.buffer
@ -4174,7 +4170,6 @@ class PartialEvaluator {
cssFontInfo, cssFontInfo,
}) { }) {
const isType3Font = type === "Type3"; const isType3Font = type === "Type3";
let properties;
if (!descriptor) { if (!descriptor) {
if (isType3Font) { if (isType3Font) {
@ -4197,7 +4192,7 @@ class PartialEvaluator {
const metrics = this.getBaseFontMetrics(baseFontName); const metrics = this.getBaseFontMetrics(baseFontName);
// Simulating descriptor flags attribute // Simulating descriptor flags attribute
const fontNameWoStyle = baseFontName.split("-")[0]; const fontNameWoStyle = baseFontName.split("-", 1)[0];
const flags = const flags =
(this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) |
(metrics.monospace ? FontFlags.FixedPitch : 0) | (metrics.monospace ? FontFlags.FixedPitch : 0) |
@ -4205,7 +4200,7 @@ class PartialEvaluator {
? FontFlags.Symbolic ? FontFlags.Symbolic
: FontFlags.Nonsymbolic); : FontFlags.Nonsymbolic);
properties = { const properties = {
type, type,
name: baseFontName, name: baseFontName,
loadedName: baseDict.loadedName, loadedName: baseDict.loadedName,
@ -4239,24 +4234,25 @@ class PartialEvaluator {
standardFontName standardFontName
); );
} }
return this.extractDataStructures(dict, dict, properties).then(
newProperties => { const newProperties = await this.extractDataStructures(
if (widths) { dict,
const glyphWidths = []; properties
let j = firstChar;
for (const width of widths) {
glyphWidths[j++] = this.xref.fetchIfRef(width);
}
newProperties.widths = glyphWidths;
} else {
newProperties.widths = this.buildCharCodeToWidth(
metrics.widths,
newProperties
);
}
return new Font(baseFontName, file, newProperties);
}
); );
if (widths) {
const glyphWidths = [];
let j = firstChar;
for (const width of widths) {
glyphWidths[j++] = this.xref.fetchIfRef(width);
}
newProperties.widths = glyphWidths;
} else {
newProperties.widths = this.buildCharCodeToWidth(
metrics.widths,
newProperties
);
}
return new Font(baseFontName, file, newProperties);
} }
} }
@ -4360,7 +4356,7 @@ class PartialEvaluator {
} }
} }
properties = { const properties = {
type, type,
name: fontName.name, name: fontName.name,
subtype, subtype,
@ -4403,13 +4399,10 @@ class PartialEvaluator {
properties.vertical = properties.cMap.vertical; properties.vertical = properties.cMap.vertical;
} }
return this.extractDataStructures(dict, baseDict, properties).then( const newProperties = await this.extractDataStructures(dict, properties);
newProperties => { this.extractWidths(dict, descriptor, newProperties);
this.extractWidths(dict, descriptor, newProperties);
return new Font(fontName.name, fontFile, newProperties); return new Font(fontName.name, fontFile, newProperties);
}
);
} }
static buildFontPaths(font, glyphs, handler, evaluatorOptions) { static buildFontPaths(font, glyphs, handler, evaluatorOptions) {
@ -4769,124 +4762,128 @@ class EvaluatorPreprocessor {
// //
// If variableArgs === true: [0, `numArgs`] expected // If variableArgs === true: [0, `numArgs`] expected
// If variableArgs === false: exactly `numArgs` expected // If variableArgs === false: exactly `numArgs` expected
return shadow(this, "opMap", { return shadow(
// Graphic state this,
w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false }, "opMap",
J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false }, Object.assign(Object.create(null), {
j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false }, // Graphic state
M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false }, w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false },
d: { id: OPS.setDash, numArgs: 2, variableArgs: false }, J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false },
ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false }, j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false },
i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false }, M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false },
gs: { id: OPS.setGState, numArgs: 1, variableArgs: false }, d: { id: OPS.setDash, numArgs: 2, variableArgs: false },
q: { id: OPS.save, numArgs: 0, variableArgs: false }, ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false },
Q: { id: OPS.restore, numArgs: 0, variableArgs: false }, i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false },
cm: { id: OPS.transform, numArgs: 6, variableArgs: false }, gs: { id: OPS.setGState, numArgs: 1, variableArgs: false },
q: { id: OPS.save, numArgs: 0, variableArgs: false },
Q: { id: OPS.restore, numArgs: 0, variableArgs: false },
cm: { id: OPS.transform, numArgs: 6, variableArgs: false },
// Path // Path
m: { id: OPS.moveTo, numArgs: 2, variableArgs: false }, m: { id: OPS.moveTo, numArgs: 2, variableArgs: false },
l: { id: OPS.lineTo, numArgs: 2, variableArgs: false }, l: { id: OPS.lineTo, numArgs: 2, variableArgs: false },
c: { id: OPS.curveTo, numArgs: 6, variableArgs: false }, c: { id: OPS.curveTo, numArgs: 6, variableArgs: false },
v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false }, v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false },
y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false }, y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false },
h: { id: OPS.closePath, numArgs: 0, variableArgs: false }, h: { id: OPS.closePath, numArgs: 0, variableArgs: false },
re: { id: OPS.rectangle, numArgs: 4, variableArgs: false }, re: { id: OPS.rectangle, numArgs: 4, variableArgs: false },
S: { id: OPS.stroke, numArgs: 0, variableArgs: false }, S: { id: OPS.stroke, numArgs: 0, variableArgs: false },
s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false }, s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false },
f: { id: OPS.fill, numArgs: 0, variableArgs: false }, f: { id: OPS.fill, numArgs: 0, variableArgs: false },
F: { id: OPS.fill, numArgs: 0, variableArgs: false }, F: { id: OPS.fill, numArgs: 0, variableArgs: false },
"f*": { id: OPS.eoFill, numArgs: 0, variableArgs: false }, "f*": { id: OPS.eoFill, numArgs: 0, variableArgs: false },
B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false }, B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false },
"B*": { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false }, "B*": { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false },
b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false }, b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false },
"b*": { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false }, "b*": { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false },
n: { id: OPS.endPath, numArgs: 0, variableArgs: false }, n: { id: OPS.endPath, numArgs: 0, variableArgs: false },
// Clipping // Clipping
W: { id: OPS.clip, numArgs: 0, variableArgs: false }, W: { id: OPS.clip, numArgs: 0, variableArgs: false },
"W*": { id: OPS.eoClip, numArgs: 0, variableArgs: false }, "W*": { id: OPS.eoClip, numArgs: 0, variableArgs: false },
// Text // Text
BT: { id: OPS.beginText, numArgs: 0, variableArgs: false }, BT: { id: OPS.beginText, numArgs: 0, variableArgs: false },
ET: { id: OPS.endText, numArgs: 0, variableArgs: false }, ET: { id: OPS.endText, numArgs: 0, variableArgs: false },
Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false }, Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false },
Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false }, Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false },
Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false }, Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false },
TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false }, TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false },
Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false }, Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false },
Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false }, Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false },
Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false }, Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false },
Td: { id: OPS.moveText, numArgs: 2, variableArgs: false }, Td: { id: OPS.moveText, numArgs: 2, variableArgs: false },
TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false }, TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false },
Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false }, Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false },
"T*": { id: OPS.nextLine, numArgs: 0, variableArgs: false }, "T*": { id: OPS.nextLine, numArgs: 0, variableArgs: false },
Tj: { id: OPS.showText, numArgs: 1, variableArgs: false }, Tj: { id: OPS.showText, numArgs: 1, variableArgs: false },
TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false }, TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false },
"'": { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false }, "'": { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false },
'"': { '"': {
id: OPS.nextLineSetSpacingShowText, id: OPS.nextLineSetSpacingShowText,
numArgs: 3, numArgs: 3,
variableArgs: false, variableArgs: false,
}, },
// Type3 fonts // Type3 fonts
d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false }, d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false },
d1: { d1: {
id: OPS.setCharWidthAndBounds, id: OPS.setCharWidthAndBounds,
numArgs: 6, numArgs: 6,
variableArgs: false, variableArgs: false,
}, },
// Color // Color
CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false }, CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false },
cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false }, cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false },
SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true }, SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true },
SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true }, SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true },
sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true }, sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true },
scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true }, scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true },
G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false }, G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false },
g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false }, g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false },
RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false }, RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false },
rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false }, rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false },
K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false }, K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false },
k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false }, k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false },
// Shading // Shading
sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false }, sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false },
// Images // Images
BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false }, BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false },
ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false }, ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false },
EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false }, EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false },
// XObjects // XObjects
Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false }, Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false },
MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false }, MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false },
DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false }, DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false },
BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false }, BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false },
BDC: { BDC: {
id: OPS.beginMarkedContentProps, id: OPS.beginMarkedContentProps,
numArgs: 2, numArgs: 2,
variableArgs: false, variableArgs: false,
}, },
EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false }, EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false },
// Compatibility // Compatibility
BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false }, BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false },
EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false }, EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false },
// (reserved partial commands for the lexer) // (reserved partial commands for the lexer)
BM: null, BM: null,
BD: null, BD: null,
true: null, true: null,
fa: null, fa: null,
fal: null, fal: null,
fals: null, fals: null,
false: null, false: null,
nu: null, nu: null,
nul: null, nul: null,
null: null, null: null,
}); })
);
} }
static MAX_INVALID_PATH_OPS = 10; static MAX_INVALID_PATH_OPS = 10;

View File

@ -48,6 +48,8 @@ const substitutionMap = new Map([
"Thorndale", "Thorndale",
"TeX Gyre Termes", "TeX Gyre Termes",
"FreeSerif", "FreeSerif",
"Linux Libertine O",
"Libertinus Serif",
"DejaVu Serif", "DejaVu Serif",
"Bitstream Vera Serif", "Bitstream Vera Serif",
"Ubuntu", "Ubuntu",
@ -148,6 +150,8 @@ const substitutionMap = new Map([
"Cumberland", "Cumberland",
"TeX Gyre Cursor", "TeX Gyre Cursor",
"FreeMono", "FreeMono",
"Linux Libertine Mono O",
"Libertinus Mono",
], ],
style: NORMAL, style: NORMAL,
ultimate: "monospace", ultimate: "monospace",
@ -323,6 +327,48 @@ function getStyleToAppend(style) {
return ""; return "";
} }
function getFamilyName(str) {
// See https://gitlab.freedesktop.org/fontconfig/fontconfig/-/blob/14d466b30a8ab4a9d789977ed94f2c30e7209267/src/fcname.c#L137.
const keywords = new Set([
"thin",
"extralight",
"ultralight",
"demilight",
"semilight",
"light",
"book",
"regular",
"normal",
"medium",
"demibold",
"semibold",
"bold",
"extrabold",
"ultrabold",
"black",
"heavy",
"extrablack",
"ultrablack",
"roman",
"italic",
"oblique",
"ultracondensed",
"extracondensed",
"condensed",
"semicondensed",
"normal",
"semiexpanded",
"expanded",
"extraexpanded",
"ultraexpanded",
"bolditalic",
]);
return str
.split(/[- ,+]+/g)
.filter(tok => !keywords.has(tok.toLowerCase()))
.join(" ");
}
/** /**
* Generate font description. * Generate font description.
* @param {Object} param0, font substitution description. * @param {Object} param0, font substitution description.
@ -470,7 +516,7 @@ function getFontSubstitution(
(italic && ITALIC) || (italic && ITALIC) ||
NORMAL; NORMAL;
substitutionInfo = { substitutionInfo = {
css: loadedName, css: `"${getFamilyName(baseFontName)}",${loadedName}`,
guessFallback: true, guessFallback: true,
loadedName, loadedName,
baseFontName, baseFontName,
@ -492,7 +538,7 @@ function getFontSubstitution(
const fallback = guessFallback ? "" : `,${ultimate}`; const fallback = guessFallback ? "" : `,${ultimate}`;
substitutionInfo = { substitutionInfo = {
css: `${loadedName}${fallback}`, css: `"${getFamilyName(baseFontName)}",${loadedName}${fallback}`,
guessFallback, guessFallback,
loadedName, loadedName,
baseFontName, baseFontName,

View File

@ -968,7 +968,7 @@ class Font {
// Fallback to checking the font name, in order to improve text-selection, // Fallback to checking the font name, in order to improve text-selection,
// since the /Flags-entry is often wrong (fixes issue13845.pdf). // since the /Flags-entry is often wrong (fixes issue13845.pdf).
if (!isSerifFont && !properties.isSimulatedFlags) { if (!isSerifFont && !properties.isSimulatedFlags) {
const baseName = name.replaceAll(/[,_]/g, "-").split("-")[0], const baseName = name.replaceAll(/[,_]/g, "-").split("-", 1)[0],
serifFonts = getSerifFonts(); serifFonts = getSerifFonts();
for (const namePart of baseName.split("+")) { for (const namePart of baseName.split("+")) {
if (serifFonts[namePart]) { if (serifFonts[namePart]) {
@ -1286,7 +1286,7 @@ class Font {
} }
amendFallbackToUnicode(properties); amendFallbackToUnicode(properties);
this.loadedName = fontName.split("-")[0]; this.loadedName = fontName.split("-", 1)[0];
} }
checkAndRepair(name, font, properties) { checkAndRepair(name, font, properties) {
@ -2093,9 +2093,7 @@ class Font {
endOffset: 0, endOffset: 0,
}); });
} }
locaEntries.sort((a, b) => { locaEntries.sort((a, b) => a.offset - b.offset);
return a.offset - b.offset;
});
// Now the offsets are sorted, calculate the end offset of each glyph. // Now the offsets are sorted, calculate the end offset of each glyph.
// The last loca entry's endOffset is not calculated since it's the end // The last loca entry's endOffset is not calculated since it's the end
// of the data and will be stored on the previous entry's endOffset. // of the data and will be stored on the previous entry's endOffset.
@ -2103,9 +2101,7 @@ class Font {
locaEntries[i].endOffset = locaEntries[i + 1].offset; locaEntries[i].endOffset = locaEntries[i + 1].offset;
} }
// Re-sort so glyphs aren't out of order. // Re-sort so glyphs aren't out of order.
locaEntries.sort((a, b) => { locaEntries.sort((a, b) => a.index - b.index);
return a.index - b.index;
});
// Calculate the endOffset of the "first" glyph correctly when there are // Calculate the endOffset of the "first" glyph correctly when there are
// *multiple* empty ones at the start of the data (fixes issue14618.pdf). // *multiple* empty ones at the start of the data (fixes issue14618.pdf).
for (i = 0; i < numGlyphs; i++) { for (i = 0; i < numGlyphs; i++) {
@ -2121,6 +2117,14 @@ class Font {
break; break;
} }
// If the last offset is 0 in the loca table then we can't compute the
// endOffset for the last glyph. So in such a case we set the endOffset
// to the end of the data (fixes issue #17671).
const last = locaEntries.at(-2);
if (last.offset !== 0 && last.endOffset === 0) {
last.endOffset = oldGlyfDataLength;
}
const missingGlyphs = Object.create(null); const missingGlyphs = Object.create(null);
let writeOffset = 0; let writeOffset = 0;
itemEncode(locaData, 0, writeOffset); itemEncode(locaData, 0, writeOffset);

View File

@ -35,7 +35,7 @@ import {
getNewAnnotationsMap, getNewAnnotationsMap,
XRefParseException, XRefParseException,
} from "./core_utils.js"; } from "./core_utils.js";
import { Dict, Ref } from "./primitives.js"; import { Dict, isDict, Ref } from "./primitives.js";
import { LocalPdfManager, NetworkPdfManager } from "./pdf_manager.js"; import { LocalPdfManager, NetworkPdfManager } from "./pdf_manager.js";
import { AnnotationFactory } from "./annotation.js"; import { AnnotationFactory } from "./annotation.js";
import { clearGlobalCaches } from "./cleanup_helper.js"; import { clearGlobalCaches } from "./cleanup_helper.js";
@ -726,6 +726,8 @@ class WorkerMessageHandler {
acroFormRef, acroFormRef,
acroForm, acroForm,
xfaData, xfaData,
// Use the same kind of XRef as the previous one.
useXrefStream: isDict(xref.topDict, "XRef"),
}).finally(() => { }).finally(() => {
xref.resetNewTemporaryRef(); xref.resetNewTemporaryRef();
}); });
@ -880,6 +882,9 @@ class WorkerMessageHandler {
.ensureXRef("trailer") .ensureXRef("trailer")
.then(trailer => trailer.get("Prev")); .then(trailer => trailer.get("Prev"));
}); });
handler.on("GetStartXRefPos", function (data) {
return pdfManager.ensureDoc("startXRef");
});
handler.on("GetAnnotArray", function (data) { handler.on("GetAnnotArray", function (data) {
return pdfManager.getPage(data.pageIndex).then(function (page) { return pdfManager.getPage(data.pageIndex).then(function (page) {
return page.annotations.map(a => a.toString()); return page.annotations.map(a => a.toString());

View File

@ -18,12 +18,14 @@ import { Dict, isName, Name, Ref } from "./primitives.js";
import { import {
escapePDFName, escapePDFName,
escapeString, escapeString,
getSizeInBytes,
numberToString, numberToString,
parseXFAPath, parseXFAPath,
} from "./core_utils.js"; } from "./core_utils.js";
import { SimpleDOMNode, SimpleXMLParser } from "./xml_parser.js"; import { SimpleDOMNode, SimpleXMLParser } from "./xml_parser.js";
import { BaseStream } from "./base_stream.js"; import { BaseStream } from "./base_stream.js";
import { calculateMD5 } from "./crypto.js"; import { calculateMD5 } from "./crypto.js";
import { Stream } from "./stream.js";
async function writeObject(ref, obj, buffer, { encrypt = null }) { async function writeObject(ref, obj, buffer, { encrypt = null }) {
const transform = encrypt?.createCipherTransform(ref.num, ref.gen); const transform = encrypt?.createCipherTransform(ref.num, ref.gen);
@ -32,7 +34,7 @@ async function writeObject(ref, obj, buffer, { encrypt = null }) {
await writeDict(obj, buffer, transform); await writeDict(obj, buffer, transform);
} else if (obj instanceof BaseStream) { } else if (obj instanceof BaseStream) {
await writeStream(obj, buffer, transform); await writeStream(obj, buffer, transform);
} else if (Array.isArray(obj)) { } else if (Array.isArray(obj) || ArrayBuffer.isView(obj)) {
await writeArray(obj, buffer, transform); await writeArray(obj, buffer, transform);
} }
buffer.push("\nendobj\n"); buffer.push("\nendobj\n");
@ -132,7 +134,7 @@ async function writeValue(value, buffer, transform) {
buffer.push(`/${escapePDFName(value.name)}`); buffer.push(`/${escapePDFName(value.name)}`);
} else if (value instanceof Ref) { } else if (value instanceof Ref) {
buffer.push(`${value.num} ${value.gen} R`); buffer.push(`${value.num} ${value.gen} R`);
} else if (Array.isArray(value)) { } else if (Array.isArray(value) || ArrayBuffer.isView(value)) {
await writeArray(value, buffer, transform); await writeArray(value, buffer, transform);
} else if (typeof value === "string") { } else if (typeof value === "string") {
if (transform) { if (transform) {
@ -281,6 +283,112 @@ function updateXFA({ xfaData, xfaDatasetsRef, newRefs, xref }) {
newRefs.push({ ref: xfaDatasetsRef, data }); newRefs.push({ ref: xfaDatasetsRef, data });
} }
async function getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer) {
buffer.push("xref\n");
const indexes = getIndexes(newRefs);
let indexesPosition = 0;
for (const { ref, data } of newRefs) {
if (ref.num === indexes[indexesPosition]) {
buffer.push(
`${indexes[indexesPosition]} ${indexes[indexesPosition + 1]}\n`
);
indexesPosition += 2;
}
// The EOL is \r\n to make sure that every entry is exactly 20 bytes long.
// (see 7.5.4 - Cross-Reference Table).
buffer.push(
`${baseOffset.toString().padStart(10, "0")} ${Math.min(ref.gen, 0xffff).toString().padStart(5, "0")} n\r\n`
);
baseOffset += data.length;
}
computeIDs(baseOffset, xrefInfo, newXref);
buffer.push("trailer\n");
await writeDict(newXref, buffer);
buffer.push("\nstartxref\n", baseOffset.toString(), "\n%%EOF\n");
}
function getIndexes(newRefs) {
const indexes = [];
for (const { ref } of newRefs) {
if (ref.num === indexes.at(-2) + indexes.at(-1)) {
indexes[indexes.length - 1] += 1;
} else {
indexes.push(ref.num, 1);
}
}
return indexes;
}
async function getXRefStreamTable(
xrefInfo,
baseOffset,
newRefs,
newXref,
buffer
) {
const xrefTableData = [];
let maxOffset = 0;
let maxGen = 0;
for (const { ref, data } of newRefs) {
maxOffset = Math.max(maxOffset, baseOffset);
const gen = Math.min(ref.gen, 0xffff);
maxGen = Math.max(maxGen, gen);
xrefTableData.push([1, baseOffset, gen]);
baseOffset += data.length;
}
newXref.set("Index", getIndexes(newRefs));
const offsetSize = getSizeInBytes(maxOffset);
const maxGenSize = getSizeInBytes(maxGen);
const sizes = [1, offsetSize, maxGenSize];
newXref.set("W", sizes);
computeIDs(baseOffset, xrefInfo, newXref);
const structSize = sizes.reduce((a, x) => a + x, 0);
const data = new Uint8Array(structSize * xrefTableData.length);
const stream = new Stream(data);
stream.dict = newXref;
let offset = 0;
for (const [type, objOffset, gen] of xrefTableData) {
offset = writeInt(type, sizes[0], offset, data);
offset = writeInt(objOffset, sizes[1], offset, data);
offset = writeInt(gen, sizes[2], offset, data);
}
await writeObject(xrefInfo.newRef, stream, buffer, {});
buffer.push("startxref\n", baseOffset.toString(), "\n%%EOF\n");
}
function computeIDs(baseOffset, xrefInfo, newXref) {
if (Array.isArray(xrefInfo.fileIds) && xrefInfo.fileIds.length > 0) {
const md5 = computeMD5(baseOffset, xrefInfo);
newXref.set("ID", [xrefInfo.fileIds[0], md5]);
}
}
function getTrailerDict(xrefInfo, newRefs, useXrefStream) {
const newXref = new Dict(null);
newXref.set("Prev", xrefInfo.startXRef);
const refForXrefTable = xrefInfo.newRef;
if (useXrefStream) {
newRefs.push({ ref: refForXrefTable, data: "" });
newXref.set("Size", refForXrefTable.num + 1);
newXref.set("Type", Name.get("XRef"));
} else {
newXref.set("Size", refForXrefTable.num);
}
if (xrefInfo.rootRef !== null) {
newXref.set("Root", xrefInfo.rootRef);
}
if (xrefInfo.infoRef !== null) {
newXref.set("Info", xrefInfo.infoRef);
}
if (xrefInfo.encryptRef !== null) {
newXref.set("Encrypt", xrefInfo.encryptRef);
}
return newXref;
}
async function incrementalUpdate({ async function incrementalUpdate({
originalData, originalData,
xrefInfo, xrefInfo,
@ -293,6 +401,7 @@ async function incrementalUpdate({
acroFormRef = null, acroFormRef = null,
acroForm = null, acroForm = null,
xfaData = null, xfaData = null,
useXrefStream = false,
}) { }) {
await updateAcroform({ await updateAcroform({
xref, xref,
@ -314,9 +423,6 @@ async function incrementalUpdate({
}); });
} }
const newXref = new Dict(null);
const refForXrefTable = xrefInfo.newRef;
let buffer, baseOffset; let buffer, baseOffset;
const lastByte = originalData.at(-1); const lastByte = originalData.at(-1);
if (lastByte === /* \n */ 0x0a || lastByte === /* \r */ 0x0d) { if (lastByte === /* \n */ 0x0a || lastByte === /* \r */ 0x0d) {
@ -328,61 +434,23 @@ async function incrementalUpdate({
baseOffset = originalData.length + 1; baseOffset = originalData.length + 1;
} }
newXref.set("Size", refForXrefTable.num + 1); const newXref = getTrailerDict(xrefInfo, newRefs, useXrefStream);
newXref.set("Prev", xrefInfo.startXRef); newRefs = newRefs.sort(
newXref.set("Type", Name.get("XRef")); (a, b) => /* compare the refs */ a.ref.num - b.ref.num
);
if (xrefInfo.rootRef !== null) { for (const { data } of newRefs) {
newXref.set("Root", xrefInfo.rootRef);
}
if (xrefInfo.infoRef !== null) {
newXref.set("Info", xrefInfo.infoRef);
}
if (xrefInfo.encryptRef !== null) {
newXref.set("Encrypt", xrefInfo.encryptRef);
}
// Add a ref for the new xref and sort them
newRefs.push({ ref: refForXrefTable, data: "" });
newRefs = newRefs.sort((a, b) => {
// compare the refs
return a.ref.num - b.ref.num;
});
const xrefTableData = [[0, 1, 0xffff]];
const indexes = [0, 1];
let maxOffset = 0;
for (const { ref, data } of newRefs) {
maxOffset = Math.max(maxOffset, baseOffset);
xrefTableData.push([1, baseOffset, Math.min(ref.gen, 0xffff)]);
baseOffset += data.length;
indexes.push(ref.num, 1);
buffer.push(data); buffer.push(data);
} }
newXref.set("Index", indexes); await (useXrefStream
? getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer)
: getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer));
if (Array.isArray(xrefInfo.fileIds) && xrefInfo.fileIds.length > 0) { const totalLength = buffer.reduce(
const md5 = computeMD5(baseOffset, xrefInfo); (a, str) => a + str.length,
newXref.set("ID", [xrefInfo.fileIds[0], md5]); originalData.length
}
const offsetSize = Math.ceil(Math.log2(maxOffset) / 8);
const sizes = [1, offsetSize, 2];
const structSize = sizes[0] + sizes[1] + sizes[2];
const tableLength = structSize * xrefTableData.length;
newXref.set("W", sizes);
newXref.set("Length", tableLength);
buffer.push(`${refForXrefTable.num} ${refForXrefTable.gen} obj\n`);
await writeDict(newXref, buffer, null);
buffer.push(" stream\n");
const bufferLen = buffer.reduce((a, str) => a + str.length, 0);
const footer = `\nendstream\nendobj\nstartxref\n${baseOffset}\n%%EOF\n`;
const array = new Uint8Array(
originalData.length + bufferLen + tableLength + footer.length
); );
const array = new Uint8Array(totalLength);
// Original data // Original data
array.set(originalData); array.set(originalData);
@ -394,16 +462,6 @@ async function incrementalUpdate({
offset += str.length; offset += str.length;
} }
// New xref table
for (const [type, objOffset, gen] of xrefTableData) {
offset = writeInt(type, sizes[0], offset, array);
offset = writeInt(objOffset, sizes[1], offset, array);
offset = writeInt(gen, sizes[2], offset, array);
}
// Add the footer
writeString(footer, offset, array);
return array; return array;
} }

View File

@ -129,12 +129,10 @@ function getRelevant(data) {
return data return data
.trim() .trim()
.split(/\s+/) .split(/\s+/)
.map(e => { .map(e => ({
return { excluded: e[0] === "-",
excluded: e[0] === "-", viewname: e.substring(1),
viewname: e.substring(1), }));
};
});
} }
function getColor(data, def = [0, 0, 0]) { function getColor(data, def = [0, 0, 0]) {

View File

@ -1838,9 +1838,10 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
const getItems = event => { const getItems = event => {
const options = event.target.options; const options = event.target.options;
return Array.prototype.map.call(options, option => { return Array.prototype.map.call(options, option => ({
return { displayValue: option.textContent, exportValue: option.value }; displayValue: option.textContent,
}); exportValue: option.value,
}));
}; };
if (this.enableScripting && this.hasJSActions) { if (this.enableScripting && this.hasJSActions) {
@ -2889,7 +2890,7 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
* @property {Array} annotations * @property {Array} annotations
* @property {PDFPageProxy} page * @property {PDFPageProxy} page
* @property {IPDFLinkService} linkService * @property {IPDFLinkService} linkService
* @property {IDownloadManager} downloadManager * @property {IDownloadManager} [downloadManager]
* @property {AnnotationStorage} [annotationStorage] * @property {AnnotationStorage} [annotationStorage]
* @property {string} [imageResourcesPath] - Path for image resources, mainly * @property {string} [imageResourcesPath] - Path for image resources, mainly
* for annotation icons. Include trailing slash. * for annotation icons. Include trailing slash.

View File

@ -212,6 +212,42 @@ class AnnotationStorage {
? { map, hash: hash.hexdigest(), transfer } ? { map, hash: hash.hexdigest(), transfer }
: SerializableEmpty; : SerializableEmpty;
} }
get editorStats() {
let stats = null;
const typeToEditor = new Map();
for (const value of this.#storage.values()) {
if (!(value instanceof AnnotationEditor)) {
continue;
}
const editorStats = value.telemetryFinalData;
if (!editorStats) {
continue;
}
const { type } = editorStats;
if (!typeToEditor.has(type)) {
typeToEditor.set(type, Object.getPrototypeOf(value).constructor);
}
stats ||= Object.create(null);
const map = (stats[type] ||= new Map());
for (const [key, val] of Object.entries(editorStats)) {
if (key === "type") {
continue;
}
let counters = map.get(key);
if (!counters) {
counters = new Map();
map.set(key, counters);
}
const count = counters.get(val) ?? 0;
counters.set(val, count + 1);
}
}
for (const [type, editor] of typeToEditor) {
stats[type] = editor.computeTelemetryFinalData(stats[type]);
}
return stats;
}
} }
/** /**

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