Peter Muturi há 1 ano atrás
pai
commit
09f57aa0fa
100 ficheiros alterados com 23120 adições e 0 exclusões
  1. 64 0
      .env.example
  2. BIN
      .env.swp
  3. 0 0
      =
  4. 79 0
      app/Console/Commands/InstantiateStatTree.php
  5. 157 0
      app/Console/Commands/clientsToGsheet.php
  6. 150 0
      app/Console/Commands/recordsToGsheet.php
  7. 711 0
      app/Http/Controllers/AdminController.php
  8. 44 0
      app/Http/Controllers/ClauseArgController.php
  9. 317 0
      app/Http/Controllers/DnaController.php
  10. 97 0
      app/Http/Controllers/DocumentsController.php
  11. 140 0
      app/Http/Controllers/GsheetController.php
  12. 297 0
      app/Http/Controllers/InvoiceController.php
  13. 28 0
      app/Http/Controllers/PayerController.php
  14. 48 0
      app/Http/Controllers/StatTreeLineReportColumnController.php
  15. 27 0
      app/Http/Controllers/SupervisingPhysicianController.php
  16. 27 0
      app/Http/Middleware/EnsureClientIsNotShadowOfPro.php
  17. 29 0
      app/Http/Middleware/EnsureMcpPro.php
  18. 29 0
      app/Http/Middleware/EnsureNaPro.php
  19. BIN
      app/Models/.Segment.php.swp
  20. 22 0
      app/Models/AdministratorBillFlagUpdate.php
  21. 13 0
      app/Models/ClauseArg.php
  22. 11 0
      app/Models/ClientBpWeightPhoneNumberStatus.php
  23. 22 0
      app/Models/ClientCarePlanFlagUpdate.php
  24. 15 0
      app/Models/ClientRepFollowUp.php
  25. 23 0
      app/Models/ClientReviewRequest.php
  26. 13 0
      app/Models/ClientRtmTransmission.php
  27. 21 0
      app/Models/ClientStickyNote.php
  28. 32 0
      app/Models/CompanyProDocument.php
  29. 34 0
      app/Models/Customer.php
  30. 14 0
      app/Models/CustomerTransaction.php
  31. 14 0
      app/Models/GiftCard.php
  32. 24 0
      app/Models/Invoice.php
  33. 14 0
      app/Models/InvoiceTransaction.php
  34. 11 0
      app/Models/Isms.php
  35. 12 0
      app/Models/NoteReasons.php
  36. 11 0
      app/Models/OutgoingEmailTemplate.php
  37. 17 0
      app/Models/PaymentMethod.php
  38. 15 0
      app/Models/ProEvent.php
  39. 13 0
      app/Models/SegmentSummaryChange.php
  40. 16 0
      app/Models/SegmentSummarySuggestion.php
  41. 11 0
      app/Models/Stamp.php
  42. 17 0
      app/Models/StatTreeLineClauseArg.php
  43. 18 0
      app/Models/StatTreeLineReportColumn.php
  44. 11 0
      app/Models/Status.php
  45. 17 0
      app/Models/VisitTemplateAccess.php
  46. 18 0
      app/Models/VisitTemplateSegmentTemplate.php
  47. 75 0
      config/constants.php
  48. 19 0
      config/patient-intake-data.php
  49. 34 0
      config/rtm.php
  50. 14 0
      copy-js.sh
  51. 284 0
      coverage_spec_april_29_2022.txt
  52. 67 0
      js-dev/click-to-copy.js
  53. 142 0
      js-dev/dq.js
  54. 32 0
      js-dev/icd-autocomplete.js
  55. 81 0
      js-dev/mc-init.js
  56. 756 0
      js-dev/mc.js
  57. 66 0
      js-dev/option-list.js
  58. 189 0
      js-dev/pro-suggest.js
  59. 302 0
      js-dev/shortcut.js
  60. 22 0
      js-dev/show-on-click.js
  61. 49 0
      js-dev/stag-collapsible-card.js
  62. 472 0
      js-dev/stag-popup.js
  63. 307 0
      js-dev/stag-suggest.js
  64. 66 0
      js-dev/stag-table-filter.js
  65. 77 0
      js-dev/tsvToArray.js
  66. 1146 0
      js-dev/yemi.js
  67. BIN
      public/img/behavior-rx.png
  68. BIN
      public/img/behavior-rx/cravings.png
  69. BIN
      public/img/behavior-rx/food-log.png
  70. BIN
      public/img/behavior-rx/phone-tracker.png
  71. BIN
      public/img/behavior-rx/relaxation.png
  72. BIN
      public/img/behavior-rx/reward.png
  73. BIN
      public/img/behavior-rx/sleep.png
  74. BIN
      public/img/behavior-rx/social.png
  75. BIN
      public/img/behavior-rx/stress.png
  76. BIN
      public/img/behavior-rx/work.png
  77. BIN
      public/img/exercise-rx.png
  78. BIN
      public/img/exercise-rx/bike.png
  79. BIN
      public/img/exercise-rx/elliptical.png
  80. BIN
      public/img/exercise-rx/jog.png
  81. BIN
      public/img/exercise-rx/strength.png
  82. BIN
      public/img/exercise-rx/swim.png
  83. BIN
      public/img/exercise-rx/walk.png
  84. BIN
      public/img/node.png
  85. BIN
      public/img/nutrition-rx.png
  86. BIN
      public/img/nutrition-rx/hs.png
  87. BIN
      public/img/nutrition-rx/hsb.png
  88. BIN
      public/img/nutrition-rx/ig.png
  89. BIN
      public/img/nutrition-rx/us.png
  90. BIN
      public/img/nutrition-rx/vc.png
  91. BIN
      public/img/nutrition-rx/wi.png
  92. BIN
      public/img/p-phone.png
  93. BIN
      public/img/pdf.png
  94. 14 0
      public/js/.gitignore
  95. 32 0
      public/js/icd-autocomplete.js
  96. 177 0
      public/js/pdfjs-2.12.313/LICENSE
  97. 15955 0
      public/js/pdfjs-2.12.313/build/pdf.js
  98. 0 0
      public/js/pdfjs-2.12.313/build/pdf.js.map
  99. 39 0
      public/js/pdfjs-2.12.313/build/pdf.sandbox.js
  100. 0 0
      public/js/pdfjs-2.12.313/build/pdf.sandbox.js.map

+ 64 - 0
.env.example

@@ -0,0 +1,64 @@
+APP_NAME=Stag
+APP_ENV=local
+APP_KEY=base64:1yKRgeLWTeEXTfh51vXtJaf6GJaRUn4NHzdlOdyDpRY=
+APP_DEBUG=true
+APP_URL=http://localhost
+
+LOG_CHANNEL=stack
+
+DB_CONNECTION=pgsql
+DB_HOST=127.0.0.1
+DB_PORT=5432
+DB_DATABASE=stag2
+DB_USERNAME=postgres
+DB_PASSWORD=pass
+
+DB_HOST_FDB=localhost
+DB_PORT_FDB=5432
+DB_DATABASE_FDB=fdbhealth
+DB_USERNAME_FDB=postgres
+DB_PASSWORD_FDB=pass
+
+BROADCAST_DRIVER=log
+CACHE_DRIVER=file
+QUEUE_CONNECTION=sync
+SESSION_DRIVER=file
+SESSION_LIFETIME=120
+
+REDIS_HOST=127.0.0.1
+REDIS_PASSWORD=null
+REDIS_PORT=6379
+
+MAIL_MAILER=smtp
+MAIL_HOST=smtp.mailtrap.io
+MAIL_PORT=2525
+MAIL_USERNAME=null
+MAIL_PASSWORD=null
+MAIL_ENCRYPTION=null
+MAIL_FROM_ADDRESS=null
+MAIL_FROM_NAME="${APP_NAME}"
+
+AWS_ACCESS_KEY_ID=
+AWS_SECRET_ACCESS_KEY=
+AWS_DEFAULT_REGION=us-east-1
+AWS_BUCKET=
+
+PUSHER_APP_ID=
+PUSHER_APP_KEY=
+PUSHER_APP_SECRET=
+PUSHER_APP_CLUSTER=mt1
+
+MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
+MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
+
+BACKEND_URL="http://localhost:8080/api"
+ADMIN_PORTAL_URL="http://localhost:3000"
+
+AUTH_URL="https://pro.leadershiphealth.local"
+
+BACKEND_WS_URL=http://localhost:8080/ws
+AGORA_APPID=9d04292b03524927a8fe9d937a448d85
+AGORA_MODE=screen
+
+GOOGLE_SPREADSHEET_ID=15pM6zM5o-S55SCLO5qkAbKCWAzYRZvDkAbgnsDNqWjk
+GOOGLE_SPREADSHEET_PRODUCTS_SHEET_NAME=records

BIN
.env.swp


+ 0 - 0
=


+ 79 - 0
app/Console/Commands/InstantiateStatTree.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Models\Client;
+use App\Models\Pro;
+use App\Models\StatTree;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Http;
+
+class InstantiateStatTree extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'stat-tree:instantiate {slug} {pro-class}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Instantiate Stat Tree For Multiple Pros';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        global $argv;
+
+        // load the tree from slug and ensure it is a template
+        /** @var StatTree $statTree */
+        $statTree = StatTree::where('slug', $argv[2])->first();
+        if(!$statTree) {
+            $this->error("Tree with specified slug does not exist!");
+            return 0;
+        }
+        if(!$statTree->is_template) {
+            $this->error("Tree with specified slug is not a template!");
+            return 0;
+        }
+
+        // check pro-class and get pro uids
+        $this->info($argv[3]);
+
+        $pros = Pro::where('is_active', TRUE)->whereRaw($argv[3])->get();
+        $this->info(count($pros) . " pros found.");
+
+        $this->info("Instantiating...");
+        $doneCount = 0;
+        if(count($pros) > 0) {
+            foreach ($pros as $pro) {
+                $statTree->instantiateForPro($pro);
+                $doneCount++;
+                if($doneCount % 50 == 0) {
+                    $this->info("$doneCount / " . count($pros) . " completed.");
+                }
+            }
+            $this->info("$doneCount / " . count($pros) . " completed.");
+        }
+
+    }
+
+}

+ 157 - 0
app/Console/Commands/clientsToGsheet.php

@@ -0,0 +1,157 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Models\BDTDevice;
+use App\Models\Client;
+use Google\Service\Sheets\ValueRange;
+use Google_Client;
+use Illuminate\Console\Command;
+use Revolution\Google\Sheets\Facades\Sheets;
+use Revolution\Google\Sheets\Sheets as SheetsSheets;
+
+class clientsToGsheet extends Command
+{
+  
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'clients:export-to-gsheet';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Export records to gsheet';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $this->pushSheet();
+        return 0;
+    }
+
+
+    function pushSheet(){
+
+        $spreadsheetId = config('app.googleSpreadsheetId');
+        $googleSpreadsheetProductsSheetName = config('app.googleSpreadsheetProductsSheetName'); 
+       
+        $client = $this->getApiClient();
+        $service = new \Google\Service\Sheets($client);
+
+        
+        $values = $this->getValues();
+
+
+        $range = $googleSpreadsheetProductsSheetName.'!A1:V1';
+        $body = new ValueRange([
+            'values' => $values
+        ]);
+        $params = [
+           'valueInputOption' => 'RAW'
+        ];
+
+        $result = $service->spreadsheets_values->append($spreadsheetId, $range, $body, $params);
+
+        $this->info(json_encode($result));
+
+    }
+
+
+    function getApiClient(){
+      
+        $KEY_FILE_LOCATION = storage_path('stag-gsheets-d9ead2f78b4b.json');
+
+        $client = new Google_Client();
+        $client->setApplicationName("My Rooster Admin");
+        $client->setAuthConfig($KEY_FILE_LOCATION);
+        
+        $client->setScopes([\Google\Service\Sheets::DRIVE, \Google\Service\Sheets::SPREADSHEETS]);
+
+        return $client;
+
+    }
+
+
+    private function getValues(){
+
+        $values = [];
+
+        $values[] = [
+            'Chart Number',
+            'Name',
+            'MCP',
+            'CC',
+            'Mailing Address State',
+            'Insurance',
+            'Is Part B Primary',
+            'Last Visit',
+            'Next Appt.',
+            'BP/Pulse Timestamp',
+            'Weight Timestamp',
+            'Created',
+            'Assigned On',
+            'Notes',
+            'Status',
+            'Temparature Gun Delivery Status',
+            'Pulse Oximeter Delivery Status',
+            'Cellular Bp Delivery Status',
+            'Weight Scale Delivery Status'
+        ];
+
+        Client::whereNull('shadow_pro_id')->chunk(1, function($clients) use (&$values){
+            foreach($clients as $patient){
+                $patientStr =($patient->chart_number).'~~'.
+                ($patient->displayName()).'~~'.
+                (@$patient->mcp ? $patient->mcp->displayName() : '--').'~~'.
+                (@$patient->defaultNaPro ? $patient->defaultNaPro->displayName() : '--').'~~'.
+                ($patient->mailing_address_state).'~~'.
+                ($patient->getPrimaryCoverage()?$patient->getPrimaryCoverage()->insuranceDisplayName():'-').'~~'.
+                ($patient->getPrimaryCoverage()?$patient->getPrimaryCoverage()->is_partbprimary:'-').'~~'.
+                (friendly_date($patient->most_recent_completed_mcp_note_date) ).'~~'.
+                ($patient->nextMcpAppointment ? friendly_date_time($patient->nextMcpAppointment->raw_date.' '.$patient->nextMcpAppointment->raw_start_time) : '-').'~~'.
+                (friendlier_date_time($patient->most_recent_cellular_bp_measurement_at) ).'~~'.
+                (friendlier_date_time($patient->most_recent_cellular_weight_measurement_at) ).'~~'.
+                (friendly_date_time($patient->created_at, false)).'~~'.
+                ($patient->getMcpAssignedOn()).'~~'.
+                (count($patient->activeNotes)).'~~'.
+                ($patient->client_engagement_status_category == 'DUMMY'? 'Test Record': $patient->client_engagement_status_category).'~~'.
+                ($patient->temparatureGunDeliveryStatus()).'~~'.
+                ($patient->pulseOximeterDeliveryStatus()).'~~'.
+                ($patient->hasBPDevice()?'DELIVERED':'').'~~'.
+                ($patient->hasWeightScaleDevice()?'DELIVERED':'').'~~';
+                $values[] = explode('~~', $patientStr);
+            }
+        });
+       
+        return $values;
+    }
+
+    
+}
+
+				
+			
+			
+				
+			
+				
+				

+ 150 - 0
app/Console/Commands/recordsToGsheet.php

@@ -0,0 +1,150 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Models\BDTDevice;
+use App\Models\Client;
+use App\Models\SimpleProduct;
+use Google\Service\Sheets\ValueRange;
+use Google_Client;
+use Illuminate\Console\Command;
+use Revolution\Google\Sheets\Facades\Sheets;
+use Revolution\Google\Sheets\Sheets as SheetsSheets;
+
+class recordsToGsheet extends Command
+{
+  
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'records:export-to-gsheet';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Export records to gsheet';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $this->pushSheet();
+        return 0;
+    }
+
+
+    function pushSheet(){
+
+        $spreadsheetId = config('app.googleSpreadsheetId');
+        $googleSpreadsheetProductsSheetName = config('app.googleSpreadsheetProductsSheetName'); 
+       
+        $client = $this->getApiClient();
+        $service = new \Google\Service\Sheets($client);
+
+        
+        $values = $this->getValues();
+
+
+        $range = $googleSpreadsheetProductsSheetName.'!A1:V1';
+        $body = new ValueRange([
+            'values' => $values
+        ]);
+        $params = [
+           'valueInputOption' => 'RAW'
+        ];
+
+        $result = $service->spreadsheets_values->append($spreadsheetId, $range, $body, $params);
+
+        $this->info(json_encode($result));
+
+    }
+
+
+    function getApiClient(){
+      
+        $KEY_FILE_LOCATION = storage_path('stag-gsheets-d9ead2f78b4b.json');
+
+        $client = new Google_Client();
+        $client->setApplicationName("My Rooster Admin");
+        $client->setAuthConfig($KEY_FILE_LOCATION);
+        
+        $client->setScopes([\Google\Service\Sheets::DRIVE, \Google\Service\Sheets::SPREADSHEETS]);
+
+        return $client;
+
+    }
+
+
+    private function getValues(){
+
+        $values = [];
+
+        $values[] = [
+            'Device Type',
+			'IMEI',
+			'Issued Yet?',
+			'Client',
+			'Used?',
+			'MCP',
+			'Issue Date',
+			'Last Meas. Date',
+			'Last Meas. Days Ago',
+			'Days with Remote Meas. this Month',
+			'Days with Remote Meas. last Month',
+			'Client Engagement Status Category',
+			'Admin Engagement Assessment Status',
+			'Mcp Engagement Assessment Status',
+			'Default Na Engagement Assessment Status',
+        ];
+
+        BDTDevice::chunk(1, function($bdtDevices) use (&$values){
+            foreach($bdtDevices as $bdtDevice){
+                $bdtDeviceStr =  $bdtDevice->category.'~~'.
+                    $bdtDevice->imei.'~~'.
+                    ($bdtDevice->clientBDTDevice ? 'Yes': 'No').'~~'.
+                    ($bdtDevice->clientBDTDevice?$bdtDevice->clientBDTDevice->client->displayName():'-').'~~'.
+                    ($bdtDevice->clientBDTDevice && $bdtDevice->clientBDTDevice->mostRecentMeasurement ? 'Yes': 'No').'~~'.
+                    ($bdtDevice->clientBDTDevice && $bdtDevice->clientBDTDevice->client->mcp ? $bdtDevice->clientBDTDevice->client->mcp->name_first.' '.$bdtDevice->clientBDTDevice->client->mcp->name_last:'-').'~~'.
+                    ($bdtDevice->clientBdtDevice? friendly_date_time($bdtDevice->clientBDTDevice->created_at) : '-').'~~'.
+                    ($bdtDevice->clientBDTDevice && $bdtDevice->clientBDTDevice->mostRecentMeasurement ? friendly_date_time($bdtDevice->clientBDTDevice->mostRecentMeasurement->measurement->ts_date_time) : '-').'~~'.
+                    ($bdtDevice->clientBDTDevice && $bdtDevice->clientBDTDevice->mostRecentMeasurement ? (date_diff(date_create($bdtDevice->clientBDTDevice->mostRecentMeasurement->measurement->ts_date_time), date_create('now'))->days) : '-').'~~'.
+                    (($bdtDevice->clientBDTDevice && $bdtDevice->clientBDTDevice->client->currentCareMonth()) ? $bdtDevice->clientBDTDevice->client->currentCareMonth()->number_of_days_with_remote_measurements:'-').'~~'.
+                    (($bdtDevice->clientBDTDevice && $bdtDevice->clientBDTDevice->client->previousCareMonth()) ? $bdtDevice->clientBDTDevice->client->previousCareMonth()->number_of_days_with_remote_measurements:'-').'~~'.
+                    @$bdtDevice->clientBDTDevice->client->client_engagement_status_category.'~~'.
+                    @$bdtDevice->clientBDTDevice->client->adminEngagementAssessmentStatus->status_category.'~~'.
+                    @$bdtDevice->clientBDTDevice->client->mcpEngagementAssessmentStatus->status_category.'~~'.
+                    @$bdtDevice->clientBDTDevice->client->defaultNaEngagementAssessmentStatus->status_category.'~~';
+                $values[] = explode('~~', $bdtDeviceStr);
+            }
+        });
+
+        return $values;
+    }
+
+    
+}
+
+				
+			
+			
+				
+			
+				
+				

+ 711 - 0
app/Http/Controllers/AdminController.php

@@ -0,0 +1,711 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\Appointment;
+use App\Models\BDTDevice;
+use App\Models\CareMonth;
+use App\Models\Client;
+use App\Models\ClientBDTDevice;
+use App\Models\ClientInfoLine;
+use App\Models\Erx;
+use App\Models\Facility;
+use App\Models\Handout;
+use App\Models\IncomingReport;
+use App\Models\MBClaim;
+use App\Models\MBPayer;
+use App\Models\Note;
+use App\Models\NoteTemplate;
+use App\Models\Pro;
+use App\Models\Product;
+use App\Models\ProProAccess;
+use App\Models\SectionTemplate;
+use App\Models\Shipment;
+use App\Models\SupplyOrder;
+use App\Models\Ticket;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\File;
+use App\Models\Bill;
+use App\Models\ClientSMS;
+
+use Illuminate\Support\Facades\Http;
+use PDF;
+
+class AdminController extends Controller
+{
+
+    public function patients(Request $request)
+    {
+        $filters = $request->all();
+        $patients = Client::whereNull('shadow_pro_id');
+
+       
+        if ($request->input('name')) {
+            $name = trim($request->input('name'));
+            if ($name) {
+                $patients = $patients->where(function ($q) use ($name) {
+                    $q->where('name_first', 'ILIKE', '%' . $name . '%')
+                        ->orWhere('name_last', 'ILIKE', '%' . $name . '%');
+                });
+            }
+        }
+
+        if ($request->input('mcp')) {
+            if($request->input('mcp') == 'NO_MCP'){
+                $patients = $patients->whereNull('mcp_pro_id');
+            }else{
+                $mcp = Pro::where('uid', trim($request->input('mcp')))->first();
+                if ($mcp) {
+                    $patients = $patients->where('mcp_pro_id', $mcp->id);
+                }
+            }
+        }
+
+        if ($request->input('na')) {
+            if($request->input('na') == 'NO_NA'){
+                $patients = $patients->whereNull('default_na_pro_id');
+            }else{
+                $na = Pro::where('uid', trim($request->input('na')))->first();
+                if ($na) {
+                    $patients = $patients->where('default_na_pro_id', $na->id);
+                }
+            }
+           
+        }
+
+        if ($request->input('ob')) {
+            if ($request->input('ob') == 'yes') {
+                $patients = $patients->where('has_mcp_done_onboarding_visit', 'YES');
+            } else {
+                $patients = $patients->where('has_mcp_done_onboarding_visit', '!=', 'YES');
+            }
+        }
+
+        if ($request->input('next_appointment_category')) {
+            if($request->input('next_appointment_category') == 'NONE'){
+                $patients = $patients->whereNull('next_mcp_appointment_id');
+            }else{
+                $self = $this;
+                $patients = $patients->whereHas('nextMcpAppointment', function($pQry) use ($request, $self){
+                    return $self->filterMultiQuery($request, $pQry, 'raw_date', 'next_appointment_category', 'next_appointment_value_1', 'next_appointment_value_2');
+                });
+            }
+        }
+
+        if ($request->input('chart_number')) {
+            $patients = $patients->where('chart_number', 'ILIKE' , '%'.$request->input('chart_number').'%');
+        }
+
+        if ($request->input('home_address_state')) {
+
+            if($request->input('home_address_state') == 'NONE'){
+                $patients = $patients->whereRaw("mailing_address_state IS NULL OR TRIM(BOTH FROM mailing_address_state = ''");
+            }else if($request->input('home_address_state') == 'NOT_MD'){
+                $patients = $patients->whereRaw("(TRIM(BOTH FROM mailing_address_state) NOT ILIKE 'MD' AND TRIM(BOTH FROM mailing_address_state) NOT ILIKE 'MARYLAND')");
+            }else{
+                $patients = $patients->whereRaw("TRIM(BOTH FROM mailing_address_state) = '" . $request->input('home_address_state') . "'");
+            }
+        }
+
+        $this->filterMultiQuery($request, $patients, 'age_in_years', 'age_category', 'age_value_1', 'age_value_2', false);
+        $this->filterSimpleQuery($request, $patients, 'sex', 'sex');
+        $this->filterMultiQuery($request, $patients, 'usual_bmi_max', 'bmi_category', 'bmi_value_1', 'bmi_value_2', false);
+        $this->filterMultiQuery($request, $patients, 'most_recent_weight_at', 'last_weighed_in_category', 'last_weighed_in_value_1', 'last_weighed_in_value_2');
+        $this->filterMultiQuery($request, $patients, 'most_recent_bp_at', 'last_bp_category', 'last_bp_value_1', 'last_bp_value_2');
+        $this->filterMultiQuery($request, $patients, 'created_at', 'created_at', 'created_at_value_1', 'created_at_value_2');
+        $this->filterMultiQuery($request, $patients, 'most_recent_completed_mcp_note_date', 'last_visit_category', 'last_visit_value_1', 'last_visit_value_2');
+
+        $fVal = $request->input('has_email');
+        if($fVal) {
+            if($fVal === 'YES') {
+                $patients = $patients->whereRaw("(email_address IS NOT NULL AND TRIM(email_address) != '')");
+            }
+            else {
+                $patients = $patients->whereRaw("(email_address IS NULL OR TRIM(email_address) = '')");
+            }
+        }
+
+        $fVal = $request->input('has_account');
+        if($fVal) {
+            if($fVal === 'YES') {
+                $patients = $patients->whereRaw("((SELECT COUNT(ac.id) FROM account_client ac WHERE ac.client_id = client.id) > 0)");
+            }
+            else {
+                $patients = $patients->whereRaw("((SELECT COUNT(ac.id) FROM account_client ac WHERE ac.client_id = client.id) = 0)");
+            }
+        }
+
+        $fVal = $request->input('has_default_mcp_company_pro');
+        if($fVal) {
+            if($fVal === 'YES') {
+                $patients = $patients->whereRaw("(default_mcp_company_pro_id IS NOT NULL)");
+            }
+            else {
+                $patients = $patients->whereRaw("(default_mcp_company_pro_id IS NULL)");
+            }
+        }
+
+        $fVal = $request->input('has_default_mcp_company_pro_payer');
+        if($fVal) {
+            if($fVal === 'YES') {
+                $patients = $patients->whereRaw("(default_mcp_company_pro_payer_id IS NOT NULL)");
+            }
+            else {
+                $patients = $patients->whereRaw("(default_mcp_company_pro_payer_id IS NULL)");
+            }
+        }
+
+        $fVal = $request->input('has_default_mcp_company_location');
+        if($fVal) {
+            if($fVal === 'YES') {
+                $patients = $patients->whereRaw("(default_mcp_company_location_id IS NOT NULL)");
+            }
+            else {
+                $patients = $patients->whereRaw("(default_mcp_company_location_id IS NULL)");
+            }
+        }
+
+        $fVal = $request->input('has_bp_device');
+        if($fVal) {
+            if($fVal === 'YES') {
+                $patients = $patients->whereRaw("((SELECT count(sh.id) " .
+                    "FROM shipment sh LEFT JOIN supply_order so ON so.shipment_id = sh.id " .
+                    "WHERE so.product_id = 1 AND sh.status IN ('DELIVERED', 'DISPATCHED') AND so.client_id = client.id) > 0)");
+            }
+            else {
+                $patients = $patients->whereRaw("((SELECT count(sh.id) " .
+                    "FROM shipment sh LEFT JOIN supply_order so ON so.shipment_id = sh.id " .
+                    "WHERE so.product_id = 1 AND sh.status IN ('DELIVERED', 'DISPATCHED') AND so.client_id = client.id) = 0)");
+            }
+        }
+
+        $fVal = $request->input('has_weight_scale');
+        if($fVal) {
+            if($fVal === 'YES') {
+                $patients = $patients->whereRaw("((SELECT count(sh.id) " .
+                    "FROM shipment sh LEFT JOIN supply_order so ON so.shipment_id = sh.id " .
+                    "WHERE so.product_id = 2 AND sh.status IN ('DELIVERED', 'DISPATCHED') AND so.client_id = client.id) > 0)");
+            }
+            else {
+                $patients = $patients->whereRaw("((SELECT count(sh.id) " .
+                    "FROM shipment sh LEFT JOIN supply_order so ON so.shipment_id = sh.id " .
+                    "WHERE so.product_id = 2 AND sh.status IN ('DELIVERED', 'DISPATCHED') AND so.client_id = client.id) = 0)");
+            }
+        }
+
+        $fVal = $request->input('has_pulse_ox');
+        if($fVal) {
+            if($fVal === 'YES') {
+                $patients = $patients->whereRaw("((SELECT count(sh.id) " .
+                    "FROM shipment sh LEFT JOIN supply_order so ON so.shipment_id = sh.id " .
+                    "WHERE so.product_id = 3 AND sh.status IN ('DELIVERED', 'DISPATCHED') AND so.client_id = client.id) > 0)");
+            }
+            else {
+                $patients = $patients->whereRaw("((SELECT count(sh.id) " .
+                    "FROM shipment sh LEFT JOIN supply_order so ON so.shipment_id = sh.id " .
+                    "WHERE so.product_id = 3 AND sh.status IN ('DELIVERED', 'DISPATCHED') AND so.client_id = client.id) = 0)");
+            }
+        }
+
+        $fVal = $request->input('has_temp_fun');
+        if($fVal) {
+            if($fVal === 'YES') {
+                $patients = $patients->whereRaw("((SELECT count(sh.id) " .
+                    "FROM shipment sh LEFT JOIN supply_order so ON so.shipment_id = sh.id " .
+                    "WHERE so.product_id = 4 AND sh.status IN ('DELIVERED', 'DISPATCHED') AND so.client_id = client.id) > 0)");
+            }
+            else {
+                $patients = $patients->whereRaw("((SELECT count(sh.id) " .
+                    "FROM shipment sh LEFT JOIN supply_order so ON so.shipment_id = sh.id " .
+                    "WHERE so.product_id = 4 AND sh.status IN ('DELIVERED', 'DISPATCHED') AND so.client_id = client.id) = 0)");
+            }
+        }
+
+        $fVal = $request->input('imei');
+        if($fVal) {
+            $patients = $patients->whereRaw("((SELECT count(cbd.id) FROM client_bdt_device cbd 
+            WHERE cbd.client_id = client.id AND cbd.device_id IN (SELECT bd.id FROM bdt_device bd WHERE bd.imei LIKE '%$fVal%' AND bd.is_active IS TRUE)) > 0)");
+        }
+
+        if($request->input('number_of_measurements')){
+            $keyName = $request->input('number_of_measurements');
+            $measurementCountQuery = '(SELECT COUNT(*) FROM measurement WHERE measurement.client_id = client.id AND is_active IS TRUE AND is_cellular IS TRUE AND is_cellular_zero IS NOT TRUE)';
+            switch($keyName) {
+                case 'EXACTLY':
+                    if($request->input('number_of_measurements_value_1')) {
+                        $patients->whereRaw($measurementCountQuery . '='.$request->input('number_of_measurements_value_1'));
+                    }
+                    break;
+                case 'LESS_THAN':
+                    if($request->input('number_of_measurements_value_1')) {
+                        $patients->whereRaw($measurementCountQuery . '<='.$request->input('number_of_measurements_value_1'));
+                    }
+                    break;
+                case 'GREATER_THAN':
+                    if($request->input('number_of_measurements_value_1')) {
+                        $patients->whereRaw($measurementCountQuery . '>='.$request->input('number_of_measurements_value_1'));
+                    }
+                    break;
+                case 'BETWEEN':
+                    if($request->input('number_of_measurements_value_1') && $request->input('number_of_measurements_value_2')) { 
+                        $patients->whereRaw($measurementCountQuery.'>='.$request->input('number_of_measurements_value_1') .' AND '. $measurementCountQuery . '<='.$request->input('number_of_measurements_value_2'));
+                    }
+                    break;
+                case 'NOT_BETWEEN':
+                    if($request->input('number_of_measurements_value_1') && $request->input('number_of_measurements_value_2')) {
+                        $patients->where(function ($q) use ($request, $measurementCountQuery) {
+                                $q->whereRaw($measurementCountQuery . '<'.$request->input('number_of_measurements_value_1') .' OR '. $measurementCountQuery . '>'.$request->input('number_of_measurements_value_2'));                               
+                        });
+                    }
+                    break;
+            }
+        }
+
+        $status = $request->input('status');
+        if($status){
+            if($status === 'ACTIVE'){
+                $patients->where('is_active', true)->where(function($q) use ($status){
+                    return $q->where('client_engagement_status_category', $status)
+                    ->orWhereNull('client_engagement_status_category');
+                });    
+            }elseif($status === 'NONE'){
+                $patients->whereNull('client_engagement_status_category');
+            }else {
+                $patients->where('client_engagement_status_category', $status);
+            }
+
+        }
+
+        $initiative = $request->input('initiative');
+        if($initiative){
+            $wildCardedInitiative = '%'.$initiative.'%';
+            $patients->where('initiative', 'ilike', $wildCardedInitiative);
+        }
+
+        $include_test_records = $request->input('include_test_records');
+        if(!$include_test_records && $status != 'DUMMY'){
+            $patients = $patients->where(function ($q) {
+                $q->whereNull('client_engagement_status_category')
+                    ->orWhere('client_engagement_status_category', '<>', 'DUMMY');
+            });
+        }
+
+        $zero_deductible = $request->input('zero_deductible');
+        if($zero_deductible){
+            $patients = $patients->where(function ($q) {
+                $q->where('mpb_remaining', 0);
+            });
+        }
+
+        $insurance = $request->get('insurance');
+        if($insurance){
+            if($insurance === 'MEDICARE'){
+                $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($cpcQuery) {
+                    return $cpcQuery->where('is_partbprimary', '=', 'YES');
+                });
+            }else{
+                $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($cpcQuery) use ($insurance){
+                    return $cpcQuery->where('commercial_payer_id', '=', $insurance);
+                });
+            }
+        }
+
+        $sortBy = $request->input('sort_by') ?: 'name_first';
+        $sortDir = $request->input('sort_dir') ?: 'ASC';
+
+        $sortBySQL = "$sortBy $sortDir NULLS LAST";
+
+        if($sortBy !== 'client_engagement_status_category' && $request->input('status')) {
+            $sortBySQL = "client_engagement_status_category DESC NULLS LAST";
+        }
+
+        $patients = $patients->orderByRaw($sortBySQL)->paginate(25);
+
+        $insurances = DB::select('SELECT DISTINCT commercial_payer_name, commercial_payer_id FROM client_primary_coverage WHERE commercial_payer_name IS NOT NULL ORDER BY commercial_payer_name ASC');
+
+        return view('app.admin.patients', compact('patients', 'filters', 'insurances'));
+    }
+
+    public function partBPatients(Request $request){
+        
+        $filters = $request->all();
+        $patients = Client::whereNull('shadow_pro_id');
+
+      
+        if ($request->input('name')) {
+            $name = trim($request->input('name'));
+            if ($name) {
+                $patients = $patients->where(function ($q) use ($name) {
+                    $q->where('name_first', 'ILIKE', '%' . $name . '%')
+                        ->orWhere('name_last', 'ILIKE', '%' . $name . '%');
+                });
+            }
+        }
+
+        if ($request->input('mcp')) {
+            if($request->input('mcp') == 'NO_MCP'){
+                $patients = $patients->whereNull('mcp_pro_id');
+            }else{
+                $mcp = Pro::where('uid', trim($request->input('mcp')))->first();
+                if ($mcp) {
+                    $patients = $patients->where('mcp_pro_id', $mcp->id);
+                }
+            }
+        }
+
+        if ($request->input('na')) {
+            if($request->input('na') == 'NO_NA'){
+                $patients = $patients->whereNull('default_na_pro_id');
+            }else{
+                $na = Pro::where('uid', trim($request->input('na')))->first();
+                if ($na) {
+                    $patients = $patients->where('default_na_pro_id', $na->id);
+                }
+            }
+           
+        }
+
+        if ($request->input('next_appointment_category')) {
+            if($request->input('next_appointment_category') == 'NONE'){
+                $patients = $patients->whereNull('next_mcp_appointment_id');
+            }
+        }
+
+        if ($request->input('chart_number')) {
+            $patients = $patients->where('chart_number', 'ILIKE' , '%'.$request->input('chart_number').'%');
+        }
+
+        if ($request->input('home_address_state')) {
+
+            if($request->input('home_address_state') == 'NONE'){
+                $patients = $patients->whereNull('mailing_address_state');
+            }else if($request->input('home_address_state') == 'NOT_MD'){
+                $patients = $patients->where('mailing_address_state', '<>' , 'MD');
+            }else{
+                $patients = $patients->where('mailing_address_state', '=' , $request->input('home_address_state'));
+            }
+        }
+
+        $this->filterMultiQuery($request, $patients, 'age_in_years', 'age_category', 'age_value_1', 'age_value_2', false);
+        $this->filterSimpleQuery($request, $patients, 'sex', 'sex');
+        $this->filterMultiQuery($request, $patients, 'usual_bmi_max', 'bmi_category', 'bmi_value_1', 'bmi_value_2', false);
+        $this->filterMultiQuery($request, $patients, 'most_recent_weight_at', 'last_weighed_in_category', 'last_weighed_in_value_1', 'last_weighed_in_value_2');
+        $this->filterMultiQuery($request, $patients, 'most_recent_bp_at', 'last_bp_category', 'last_bp_value_1', 'last_bp_value_2');
+
+        if($request->input('deductible')){
+            $keyName = $request->input('deductible');
+
+            switch($keyName) {
+                case 'EXACTLY':
+                        $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($q) use ($request){
+                            return $q->where('auto_medicare_mpb_deductible', '=', $request->input('deductible_value_1'));
+                        });
+                    break;
+                case 'LESS_THAN':
+                    if($request->input('deductible_value_1')) {
+                        $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($q) use ($request){
+                            return $q->where('auto_medicare_mpb_deductible', '<=', $request->input('deductible_value_1'));
+                        });
+                    }
+                    break;
+                case 'GREATER_THAN':
+                    if($request->input('deductible_value_1')) {
+                        $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($q) use ($request){
+                            return $q->where('auto_medicare_mpb_deductible', '>=', $request->input('deductible_value_1'));
+                        });
+                    }
+                    break;
+                case 'BETWEEN':
+                    $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($q) use ($request){
+                        return $q->where('auto_medicare_mpb_deductible', '>=', $request->input('deductible_value_1'))
+                        ->where('auto_medicare_mpb_deductible', '<=', $request->input('deductible_value_2'));
+                    });
+                    break;
+                case 'NOT_BETWEEN':
+                    if($request->input('deductible_value_1') && $request->input('deductible_value_2')) {
+                        $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($q) use ($request){
+
+                            return $q->where(function($qq) use ($request){
+                                return $qq->where('auto_medicare_mpb_deductible', '<', $request->input('deductible_value_1'))
+                                    ->orWhere('auto_medicare_mpb_deductible', '>', $request->input('deductible_value_2'));
+                            });
+                        });
+                    }
+                    break;
+            }
+        }
+
+        switch($request->input('status')) {
+            case 'ACTIVE':
+                $patients->where('is_active', true)->where('has_mcp_done_onboarding_visit', true);
+                break;
+            case 'AWAITING_VISIT':
+                $patients->where('is_active', true)->where('has_mcp_done_onboarding_visit', false);
+                break;
+            case 'INACTIVE':
+                $patients->where('is_active', '<>', true);
+                break;
+        }
+
+        $initiative = $request->input('initiative');
+        if($initiative){
+            $wildCardedInitiative = '%'.$initiative.'%';
+            $patients->where('initiative', 'ilike', $wildCardedInitiative);
+        }
+
+        $include_test_records = $request->input('include_test_records');
+        if(!$include_test_records){
+            $patients = $patients->where(function ($q) {
+                return $q->whereNull('client_engagement_status_category')
+                    ->orWhere('client_engagement_status_category', '<>', 'DUMMY');
+            });
+        }
+
+        
+        $with_claim_not_closed = $request->input('with_claim_not_closed');
+        if($with_claim_not_closed){
+            $patients = $patients->whereHas('notes', function ($q) {
+                return $q->where('is_claim_closed', false)
+                ->where('is_signed_by_hcp', true)
+                ->where('is_cancelled', false);
+            });
+        }
+
+        $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($cpcQuery){
+            return $cpcQuery->where('is_partbprimary', '=', 'YES');
+        });
+
+        $patients = $patients->orderBy('created_at', 'DESC')->paginate(25);
+        return view('app.admin.part_b_patients', compact('patients', 'filters'));
+    }
+
+    public function notes(Request $request)
+    {
+        $notes = Note::paginate(5);
+
+        // SELECT * FROM note WHERE client_id IN (SELECT id FROM client WHERE mcp_pro_id = :me.id);
+
+        return view('app.mcp.notes', compact('notes'));
+    }
+
+    public function notes_pending_summary_suggestion(Request $request){
+        $pro = $this->performer->pro;
+        $data = [
+            'records' => $pro->get_notes_pending_summary_suggestion_as_admin()
+        ];
+        return view('app.admin.notes_pending_summary_suggestion', $data);
+    }
+
+    public function notes_rejected_summary_suggestion(Request $request){
+        $pro = $this->performer->pro;
+        $data = [
+            'records' => $pro->get_notes_rejected_summary_suggestion_as_admin()
+        ];
+        return view('app.admin.notes_rejected_summary_suggestion', $data);
+    }
+
+
+    public function appointments(Request $request)
+    {
+        $appointments = Appointment::paginate(5);
+        return view('app.mcp.appointments', compact('appointments'));
+    }
+
+    public function bills(Request $request)
+    {
+        $bills = Bill::paginate(5);
+        return view('app.mcp.bills', compact('bills'));
+    }
+
+    public function erx_and_orders(Request $request)
+    {
+        $erxAndOrders = Erx::paginate(5);
+        return view('app.mcp.erx_and_orders', compact('erxAndOrders'));
+    }
+
+    public function reports(Request $request)
+    {
+        $data = [];
+        return view('app.mcp.reports', $data);
+    }
+
+    public function supply_orders(Request $request)
+    {
+        $supplyOrders = SupplyOrder::paginate(5);
+        return view('app.mcp.supply_orders', compact('supplyOrders'));
+    }
+
+    public function getCreateNewPatientScriptTemplate(Request $request){
+        $template = $request->get('template');
+        if(!$template) return $this->fail('No script template');
+
+        $path = resource_path() . '/views/app/patient/create-patient/scripts/' . $template . '.blade.php';
+        
+        if(!File::exists($path)) return $this->fail('Invalid script template');
+
+        $templateContent = file_get_contents($path);
+        return $this->pass($templateContent);
+    }
+    
+    public function bdtDevices(Request $request)
+    {
+        $filters = $request->all();
+        $bdtDevices = BDTDevice::query();
+
+        $imei = $request->input('imei');
+        if($imei){
+            $bdtDevices = $bdtDevices->where('imei', '=', $imei);
+        }
+        $client = $request->input('client');
+
+        if($client){
+            $client = '%'.$client.'%';
+            $bdtDevices = $bdtDevices->whereHas('clientBDTDevice', function($cbdtdQuery) use ($client) {
+                return $cbdtdQuery->whereHas('client', function($clientQuery) use ($client){
+                    return $clientQuery->where(function($q) use ($client){
+                        return $q->where('name_first', 'ilike', $client)
+                        ->orWhere('name_last', 'ilike', $client)
+                        ->orWhere('cell_number', 'ilike', $client)
+                        ->orWhereRaw("name_first||' '||name_last ILIKE "."'".$client."'"); 
+                    });
+                });
+            });
+        }
+
+        $is_issued = $request->input('is_issued');
+        if($is_issued){
+            if($is_issued == 'YES'){
+                $bdtDevices = $bdtDevices->whereHas('clientBDTDevice');
+            }
+
+            if($is_issued == 'NO'){
+                $bdtDevices = $bdtDevices->whereDoesntHave('clientBDTDevice');
+            }
+        }
+
+        $is_issued = $request->input('is_issued');
+        if($is_issued){
+            if($is_issued == 'YES'){
+                $bdtDevices = $bdtDevices->whereHas('clientBDTDevice');
+            }
+
+            if($is_issued == 'NO'){
+                $bdtDevices = $bdtDevices->whereDoesntHave('clientBDTDevice');
+            }
+        }
+
+        $mcp = $request->input('mcp');
+        if($mcp){
+            $bdtDevices = $bdtDevices->whereHas('clientBDTDevice', function($cbdtdQuery) use ($mcp) {
+                return $cbdtdQuery->whereHas('client', function($clientQuery) use ($mcp){
+                    $mcpPro = Pro::where('uid', $mcp)->first();
+                    return $clientQuery->where('mcp_pro_id', $mcpPro->id);
+                });
+            });
+        }
+
+        $bdtDevices = $bdtDevices->paginate(20);
+        
+       
+        return view('app.admin.bdt_devices', compact('bdtDevices', 'filters'));
+    }
+
+    public function patientsMissingDefasultSettings(Request $request){
+        $filters = $request->all();
+        $patients = Client::whereNull('shadow_pro_id');
+
+        $patients = $patients->where(function($qry){
+            return $qry->orWhereNull('mcp_pro_id')->orWhereNull('default_mcp_company_pro_id')->orWhereNull('default_mcp_company_pro_payer_id')->orWhereNull('default_mcp_company_location_id');
+        });
+
+        if ($request->input('name')) {
+            $name = trim($request->input('name'));
+            if ($name) {
+                $patients = $patients->where(function ($q) use ($name) {
+                    $q->where('name_first', 'ILIKE', '%' . $name . '%')
+                        ->orWhere('name_last', 'ILIKE', '%' . $name . '%');
+                });
+            }
+        }
+
+        if ($request->input('mcp')) {
+            if($request->input('mcp') == 'NO_MCP'){
+                $patients = $patients->whereNull('mcp_pro_id');
+            }else{
+                $mcp = Pro::where('uid', trim($request->input('mcp')))->first();
+                if ($mcp) {
+                    $patients = $patients->where('mcp_pro_id', $mcp->id);
+                }
+            }
+        }
+
+        if ($request->input('chart_number')) {
+            $patients = $patients->where('chart_number', 'ILIKE' , '%'.$request->input('chart_number').'%');
+        }
+
+        $status = $request->input('status');
+        if($status){
+            if($status == 'ACTIVE'){
+                $patients->where('is_active', true)->where(function($q) use ($status){
+                    return $q->where('client_engagement_status_category', $status)
+                    ->orWhereNull('client_engagement_status_category');
+                });    
+            }else {
+                $patients->where('client_engagement_status_category', $status);
+            }
+
+        }
+        
+        $insurance = $request->get('insurance');
+        if($insurance){
+            if($insurance === 'MEDICARE'){
+                $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($cpcQuery){
+                    return $cpcQuery->where('is_partbprimary', '=', 'YES');
+                });
+            }elseif($insurance === 'MEDICARE_PENDING'){
+                $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($cpcQuery){
+                    return $cpcQuery->where('plan_type', 'MEDICARE')->where('is_covered', '!=', 'YES');
+                });
+            }elseif($insurance === 'NOT_COVERED'){
+                $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($cpcQuery){
+                    return $cpcQuery->where('is_covered', '!=', 'YES');
+                });
+            }elseif($insurance === 'PENDING'){
+                $patients = $patients->whereHas('effectiveClientPrimaryCoverage', function($cpcQuery){
+                    return $cpcQuery->where('is_covered', '=', 'UNKNOWN');
+                });
+            }
+            else{
+                $patients = $patients->whereDoesntHave('effectiveClientPrimaryCoverage', function($cpcQuery){
+                    return $cpcQuery->where('is_partbprimary', '=', 'YES');
+                });
+            }
+        }
+        
+        $missing_default_settings = $request->get('missing_default_settings');
+        if($missing_default_settings){
+            if($missing_default_settings === 'NO_MCP') $patients = $patients->whereNull('mcp_pro_id');
+            if($missing_default_settings === 'NO_MCP_COMPANY_PRO') $patients = $patients->whereNull('default_mcp_company_pro_id');
+            if($missing_default_settings === 'NO_MCP_COMPANY_PRO_PAYER') $patients = $patients->whereNull('default_mcp_company_pro_payer_id');
+            if($missing_default_settings === 'NO_MCP_COMPANY_LOCATION') $patients = $patients->whereNull('default_mcp_company_location_id');
+        }
+
+        $care_plan = $request->get('care_plan');
+        if($care_plan){
+            if($care_plan === 'UNSIGNED_CARE_PLANS'){
+              $patients = $patients->whereHas('notes', function($noteQuery){ 
+                return $noteQuery->where('cm_setup_manager_signature_status', '!=', 'SIGNED');
+                });  
+            }
+            if($care_plan === 'UNCLEARED_CARE_PLANS'){
+                $patients = $patients->where('has_care_plan_flag', true)->where('is_flag_cleared', false);
+            }
+            
+        }
+
+        $patients = $patients->orderBy('created_at', 'DESC')->paginate(50);
+        return view('app.admin.patients_missing_default_settings', compact('patients', 'filters'));
+    }
+
+} 

+ 44 - 0
app/Http/Controllers/ClauseArgController.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\ClauseArg;
+use Illuminate\Http\Request;
+use App\Models\Clause;
+use Illuminate\Http\JsonResponse;
+use Illuminate\Support\Facades\DB;
+use Ramsey\Uuid\Uuid;
+use App\Models\StatTree;
+use App\Models\StatTreeLine;
+use App\Models\StatTreeLineClause;
+
+class ClauseArgController extends Controller
+{
+
+    // eps
+    public function create(Request $request) {
+        $clauseArg = new ClauseArg();
+        $nextId = DB::select("select nextval('clause_arg_id_seq')");
+        $clauseArg->id = $nextId[0]->nextval;
+        $clauseArg->clause_id = $request->input('clauseId');
+        $clauseArg->arg_text = $request->input('argText');
+        $clauseArg->field_type = $request->input('fieldType');
+        $clauseArg->save();
+        return $this->pass();
+    }
+    public function update(Request $request) {
+        $clauseArg = ClauseArg::where('id', $request->input('id'))->first();
+        if(!$clauseArg) return $this->fail('Clause arg not found!');
+        $clauseArg->arg_text = $request->input('argText');
+        $clauseArg->field_type = $request->input('fieldType');
+        $clauseArg->save();
+        return $this->pass();
+    }
+    public function remove(Request $request) {
+        $clauseArg = ClauseArg::where('id', $request->input('id'))->first();
+        if(!$clauseArg) return $this->fail('Clause arg not found!');
+        DB::select("delete from clause_arg where id = {$clauseArg->id}");
+        return $this->pass();
+    }
+
+}

+ 317 - 0
app/Http/Controllers/DnaController.php

@@ -0,0 +1,317 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\Appointment;
+use App\Models\BDTDevice;
+use App\Models\Bill;
+use App\Models\CareMonth;
+use App\Models\Client;
+use App\Models\ClientBDTDevice;
+use App\Models\ClientInfoLine;
+use App\Models\Erx;
+use App\Models\Facility;
+use App\Models\Handout;
+use App\Models\IncomingReport;
+use App\Models\MBClaim;
+use App\Models\MBPayer;
+use App\Models\Note;
+use App\Models\NoteTemplate;
+use App\Models\Pro;
+use App\Models\Product;
+use App\Models\ProProAccess;
+use App\Models\ProTeam;
+use App\Models\ProTransaction;
+use App\Models\SectionTemplate;
+use App\Models\Shipment;
+use App\Models\SupplyOrder;
+use App\Models\Ticket;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\File;
+
+use Illuminate\Support\Facades\Http;
+use PDF;
+
+class DnaController extends Controller
+{
+
+    public function patients(Request $request)
+    {
+        $filters = $request->all();
+        $patients = Client::whereNull('shadow_pro_id')->where('default_na_pro_id', $this->performer->pro->id);
+
+        if ($request->input('name')) {
+            $name = trim($request->input('name'));
+            if ($name) {
+                $patients = $patients->where(function ($q) use ($name) {
+                    $q->where('name_first', 'ILIKE', '%' . $name . '%')
+                        ->orWhere('name_last', 'ILIKE', '%' . $name . '%');
+                });
+            }
+        }
+
+        if ($request->input('home_address_state')) {
+
+            if($request->input('home_address_state') == 'NONE'){
+                $patients = $patients->whereNull('mailing_address_state');
+            }else if($request->input('home_address_state') == 'NOT_MD'){
+                $patients = $patients->where('mailing_address_state', '<>' , 'MD');
+            }else{
+                $patients = $patients->where('mailing_address_state', '=' , $request->input('home_address_state'));
+            }
+        }
+
+        $this->filterMultiQuery($request, $patients, 'age_in_years', 'age_category', 'age_value_1', 'age_value_2', false);
+        $this->filterSimpleQuery($request, $patients, 'sex', 'sex');
+        $this->filterMultiQuery($request, $patients, 'usual_bmi_max', 'bmi_category', 'bmi_value_1', 'bmi_value_2', false);
+        $this->filterMultiQuery($request, $patients, 'most_recent_completed_mcp_note_date', 'last_visit_category', 'last_visit_value_1', 'last_visit_value_2'); 
+        $this->filterMultiQuery($request, $patients, 'next_mcp_appointment_date', 'next_appointment_category', 'next_appointment_value_1', 'next_appointment_value_2');
+
+        switch($request->input('status')) {
+            case 'ACTIVE':
+                $patients->where('is_active', true)->where('has_mcp_done_onboarding_visit', true);
+                break;
+            case 'AWAITING_VISIT':
+                $patients->where('is_active', true)->where('has_mcp_done_onboarding_visit', false);
+                break;
+            case 'INACTIVE':
+                $patients->where('is_active', '<>', true);
+                break;
+        }
+        $sortBy = $request->input('sort_by') ?: 'name_first';
+        $sortDir = $request->input('sort_dir') ?: 'ASC';
+
+        $patients = $patients->orderByRaw("$sortBy $sortDir NULLS LAST");
+        
+        $patients = $patients->orderBy('created_at', 'DESC')->paginate(20);
+        return view('app.dna.patients', compact('patients', 'filters'));
+    }
+
+    public function encounters(Request $request)
+    {
+        $filters = $request->all();
+        $notes = Note::query();
+        $notes = $notes->where('ally_pro_id', $this->performer->pro->id);
+        $this->filterMultiQuery($request, $notes, 'effective_time', 'date_category', 'date_value_1', 'date_value_2');
+        $this->filterSimpleQuery($request, $notes, 'new_or_fu_or_na', 'new_or_fu_or_na');
+        $notes = $notes->orderBy('created_at', 'DESC')->paginate(20);
+        return view('app.dna.encounters', compact('notes', 'filters'));
+    }
+
+    public function notes(Request $request)
+    {
+        $data = [];
+        return view('app.dna.notes', $data);
+    }
+
+    public function appointments(Request $request)
+    {
+        $filters = $request->all();
+        $appointments = Appointment::select('appointment.*')
+                        ->join('client', 'client.id', '=', 'appointment.client_id')
+                        ->where('client.default_na_pro_id', $this->performer->pro->id);
+        $this->filterMultiQuery($request, $appointments, 'raw_date', 'date_category', 'date_value_1', 'date_value_2');
+        $this->filterSimpleQuery($request, $appointments, 'status', 'status');
+        $appointments = $appointments->orderBy('end_time', 'DESC')->paginate(20);
+        return view('app.dna.appointments', compact('appointments', 'filters'));
+    }
+
+    public function careMonths(Request $request){
+        $filters = $request->all();
+        $careMonths = CareMonth::select('care_month.*')
+                        ->join('client', 'client.id', '=', 'care_month.client_id')
+                        ->where('client.default_na_pro_id', $this->performer->pro->id);
+        $this->filterMultiQuery($request, $careMonths, 'raw_date', 'date_category', 'date_value_1', 'date_value_2');
+        $this->filterSimpleQuery($request, $careMonths, 'status', 'status');
+        $careMonths = $careMonths->orderBy('created_at', 'DESC')->paginate(20);
+        return view('app.dna.care-months', compact('careMonths', 'filters'));
+    }
+
+    public function financialTransactions(Request $request){
+        $filters = $request->all();
+        $financialTransactions = ProTransaction::select('pro_transaction.*')
+                                ->join('bill', 'bill.id', '=', 'pro_transaction.bill_id')
+                                ->where('bill.generic_pro_id', $this->performer->pro->id);
+        $financialTransactions = $financialTransactions->orderBy('created_at', 'DESC')->paginate(20);
+        return view('app.dna.financial-transactions', compact('financialTransactions', 'filters'));
+    }
+    public function myBills(Request $request){
+        $performerProID = $this->performer->pro->id;
+        $filters = $request->all();
+        $bills = Bill::where(function($q) use ($performerProID){
+            return $q->where('na_pro_id', '=', $performerProID )->orWhere('generic_pro_id', '=', $performerProID);
+        });
+        $this->filterMultiQuery($request, $bills, 'effective_date', 'date_category', 'date_value_1', 'date_value_2');
+        $this->filterMultiQuery($request, $bills, 'na_expected_payment_amount', 'amount_category', 'amount_value_1', 'amount_value_2');
+        
+        $status = $request->get('status');
+        if($status){
+            if($status === 'VERIFIED') $bills = $bills->where('is_verified', true);
+            if($status === 'ACTIVE') $bills = $bills->where('is_cancelled', false);
+            if($status === 'CANCELLED') $bills = $bills->where('is_cancelled', true);
+            if($status === 'SUBMITTED') $bills = $bills->where('is_submitted', true);
+        }
+        
+        $bills = $bills->orderBy('effective_date', 'DESC')->paginate(20);
+        return view('app.dna.my-bills', compact('bills', 'filters'));
+    }
+
+    public function myClinicalTeams(Request $request){
+        $filters = $request->all();
+        $teams = ProTeam::where('assistant_pro_id', $this->performer->pro->id);        
+        $teams = $teams->orderBy('created_at', 'DESC')->paginate(20);
+        return view('app.dna.my-clinical-teams', compact('teams', 'filters'));
+    }
+
+    public function bills(Request $request)
+    {
+        $data = [];
+        return view('app.dna.bills', $data);
+    }
+
+    public function erx_and_orders(Request $request)
+    {
+        $data = [];
+        return view('app.dna.erx_and_orders', $data);
+    }
+
+    public function reports(Request $request)
+    {
+        $data = [];
+        return view('app.dna.reports', $data);
+    }
+
+    public function supply_orders(Request $request)
+    {
+        $data = [];
+        return view('app.dna.supply_orders', $data);
+    }
+
+    public function new_patients_awaiting_visit(Request $request){
+        $data = [];
+        return view('app.dna.new_patients_awaiting_visit', $data);
+    }
+    public function notes_pending_signature(Request $request){
+        $data = [];
+        return view('app.dna.notes_pending_signature', $data);
+    }
+    public function notes_pending_billing(Request $request){
+        $data = [];
+        return view('app.dna.notes_pending_billing', $data);
+    }
+    public function reports_pending_signature(Request $request){
+        $data = [];
+        return view('app.dna.reports_pending_signature', $data);
+    }
+    public function patients_without_appointments(Request $request){
+        $data = [];
+        return view('app.dna.patients_without_appointments', $data);
+    }
+    public function patients_overdue_for_visit(Request $request){
+        $data = [];
+        return view('app.dna.patients_overdue_for_visit', $data);
+    }
+    public function cancelled_appointments_pending_review(Request $request){
+        $data = [];
+        return view('app.dna.cancelled_appointments_pending_review', $data);
+    }
+    public function cancelled_bills_pending_review(Request $request){
+        $data = [];
+        return view('app.dna.cancelled_bills_pending_review', $data);
+    }
+    public function cancelled_supply_orders_pending_review(Request $request){
+        $data = [];
+        return view('app.dna.cancelled_supply_orders_pending_review', $data);
+    }
+    public function erx_and_orders_pending_signature(Request $request){
+        $data = [];
+        return view('app.dna.erx_and_orders_pending_signature', $data);
+    }
+    public function supply_orders_pending_signature(Request $request){
+        $data = [];
+        return view('app.dna.supply_orders_pending_signature', $data);
+    }
+
+    //From the new spec 
+    public function myPatients(Request $request){
+        $pro = $this->performer->pro; 
+        $records = $pro->patientsRecordsAsDna();
+        return view('app.dna.dashboard.patients', compact('records'));
+    }
+    
+    public function patientsAwaitingMcpVisit(Request $request){
+        $pro = $this->performer->pro; 
+        $records = $pro->patientsAwaitingMcpVisitRecordsAsDna();
+        return view('app.dna.dashboard.patients_awaiting_mcp_visit', compact('records'));
+    }
+    
+    public function patientsWithoutAppointment(Request $request){
+        $pro = $this->performer->pro; 
+        $records = $pro->patientsWithoutAppointmentRecordsAsDna();
+        return view('app.dna.dashboard.patients_without_appointment', compact('records'));
+    }
+    
+    public function encountersPendingMyReview(Request $request){
+        $pro = $this->performer->pro; 
+        $records = $pro->encountersPendingMyReviewRecordsAsDna();
+        return view('app.dna.dashboard.encounters_pending_my_review', compact('records'));
+    }
+    
+    public function encountersInProgress(Request $request){
+        $pro = $this->performer->pro; 
+        $records = $pro->encountersInProgressRecordsAsDna();
+        return view('app.dna.dashboard.encounters_in_progress', compact('records'));
+    }
+    
+    public function appointmentsPendingConfirmation(Request $request){
+        $pro = $this->performer->pro; 
+        $records = $pro->appointmentsPendingConfirmationRecordsAsDna();
+        return view('app.dna.dashboard.appointments_pending_confirmation', compact('records'));
+    }
+    
+    public function cancelledAppointmentsPendingAck(Request $request){
+        $pro = $this->performer->pro; 
+        $records = $pro->cancelledAppointmentsPendingAckRecordsAsDna();
+        return view('app.dna.dashboard.cancelled_appointments_pending_ack', compact('records'));
+    }
+    
+    public function reportsPendingAck(Request $request){
+        $pro = $this->performer->pro; 
+        $records = $pro->reportsPendingAckRecordsAsDna();
+        return view('app.dna.dashboard.reports_pending_ack', compact('records'));
+    }
+    
+    public function supplyOrdersPendingMyAck(Request $request){
+        $pro = $this->performer->pro; 
+        $records = $pro->supplyOrdersPendingMyAckRecordsAsDna();
+        return view('app.dna.dashboard.supply_orders_pending_my_ack', compact('records'));
+    }
+    
+    public function supplyOrdersPendingHcpApproval(Request $request){
+        $pro = $this->performer->pro; 
+        $records = $pro->supplyOrdersPendingHcpApprovalRecordsAsDna();
+        return view('app.dna.dashboard.supply_orders_pending_hcp_approval', compact('records'));
+    }
+
+    public function teamDashboard(ProTeam $team){
+        $slug = $team->slug ?? $team->uid;
+        $url = config('app.stagfe6_url') . '/flyers/json-list?slug=' . $slug;
+
+        $arrContextOptions=array(
+            "ssl"=>array(
+                "verify_peer"=>false,
+                "verify_peer_name"=>false,
+            ),
+        );        
+        $response = @file_get_contents($url, false, stream_context_create($arrContextOptions));
+        $response = @json_decode($response);
+        $flyerTemplates = [];
+        if(isset($response->data)){
+            $flyerTemplates = $response->data;
+        }
+        return view('app.dna.teams.dashboard', compact('team','flyerTemplates'));
+    }
+    
+
+}

+ 97 - 0
app/Http/Controllers/DocumentsController.php

@@ -0,0 +1,97 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\Company;
+use Illuminate\Http\Request;
+use App\Models\CompanyProDocument;
+use PDF;
+use Illuminate\Support\Carbon;
+
+class DocumentsController extends Controller
+{
+
+
+    public function generateDocumentPDF($uid)
+    {
+        $company_pro_document = CompanyProDocument::where('uid', $uid)->first();
+        if (!$company_pro_document) abort(404);
+
+        $company = Company::where('id', $company_pro_document->company_id)->first();
+        if (!$company) abort(404);
+
+        $pro = $company_pro_document->pro;
+
+        // {token} replacements
+
+        // 1. replace "custom" fields (entered by candidate pro)
+        $html = $company_pro_document->content_html;
+        if($company_pro_document->custom_fields_data) {
+            $customFieldsData = json_decode($company_pro_document->custom_fields_data, true);
+            foreach ($customFieldsData as $k => $v) {
+                $html = str_replace('{' . $k . '}', '<span>' . $v . '</span>', $html);
+            }
+        }
+
+        // replace database driven fields
+        $html = preg_replace_callback(
+            '/{([^}]+)}/',
+            function ($match) use ($company, $company_pro_document, $pro) {
+                $token = $match[1];
+                $replacement = '';
+                if(strpos($token, '.') !== FALSE) {
+                    $token = explode('.', $token);
+
+
+                    // if prefixed with * - means pre-send fill
+                    $waitForCountersignToShow = false;
+                    if($token[0][0] === '*') {
+                        $token[0] = substr($token[0], 1);
+                        $waitForCountersignToShow = true;
+                    }
+
+                    $replacement = @${$token[0]}->{$token[1]};
+
+                    // special cases
+
+                    // if the fields are relating to PRO SIGNATURE, then don't display anything until signing
+                    if($token[0] === 'company_pro_document') {
+                        if (!$company_pro_document->has_pro_signed &&
+                            ($token[1] === 'pro_signatures' || $token[1] === 'pro_signed_at')) {
+                            $replacement = '';
+                        }
+                    }
+
+                    // if you want to $waitForCountersignToShow, then do that
+                    if($waitForCountersignToShow && !$company_pro_document->has_hrm_pro_counter_signed){
+                        $replacement = '';
+                    }
+
+                    if(strpos($token[1], "_at") === strlen($token[1]) - 3) {
+                        if(!!$replacement) {
+                            $replacement = date('m/d/Y', strtotime($replacement));
+                        }
+                    }
+
+                }
+                else {
+                    switch ($token) {
+                        case 'TODAY':
+                            $replacement = date('Y-m-d');
+                            break;
+                        default:
+                            $replacement = '<span style="color:red;">' . $token . '</span>';
+                            break;
+                    }
+                }
+                return $replacement;
+            },
+            $html
+        );
+
+         $pdf = PDF::loadView('layouts.document-pdf', compact('company_pro_document', 'html'));
+         return $pdf->stream($uid.'.pdf');
+
+//        return view('layouts.document-pdf', compact('company_pro_document', 'html'));
+    }
+}

+ 140 - 0
app/Http/Controllers/GsheetController.php

@@ -0,0 +1,140 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Exception;
+use Google\Service\Sheets\ValueRange;
+use Google_Client;
+use Illuminate\Console\Command;
+use Revolution\Google\Sheets\Facades\Sheets;
+use Revolution\Google\Sheets\Sheets as SheetsSheets;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+
+class GsheetController extends Controller
+{
+    
+
+    public function testGsheet(){
+        $sql = "
+        SELECT client.name_first, client.name_last,
+       (client.name_first || ' ' || client.name_last) as client_name,
+       (mcp_pro.name_first || ' ' || mcp_pro.name_last) as mcp_pro_name,
+       (rmm_pro.name_first || ' ' || rmm_pro.name_last) as rmm_pro_name,
+       client.dob,
+       care_month.is_client_enrolled_in_rm,
+       client.most_recent_completed_mcp_note_date,
+       client.most_recent_completed_mcp_note_id,
+       mrmnote.effective_dateest::date as most_recent_completed_mcp_note_date_cm,
+       client.cell_number,
+       client.is_assigned_cellular_bp_device,
+       client.is_assigned_cellular_weight_scale_device,
+       care_month.start_date,
+       care_month.rm_total_time_in_seconds_by_mcp,
+       care_month.rm_total_time_in_seconds_by_rmm_pro,
+       care_month.number_of_days_with_remote_measurements,
+       care_month.has_anyone_interacted_with_client_about_rm,
+       care_month.has_mcp_interacted_with_client_about_rm,
+       care_month.rm_num_measurements_not_stamped_by_mcp,
+       care_month.rm_num_measurements_not_stamped_by_non_hcp,
+       care_month.rm_num_measurements_not_stamped_by_rmm,
+       care_month.rm_num_measurements_not_stamped_by_rme,
+       client.cell_number,
+       client.most_recent_cellular_bp_dbp_mm_hg,
+       client.most_recent_cellular_bp_sbp_mm_hg,
+       client.most_recent_cellular_bp_measurement_at,      
+       client.most_recent_cellular_weight_value,
+       client.most_recent_cellular_weight_measurement_at
+FROM care_month join client on care_month.client_id = client.id join note mrnote on client.most_recent_completed_mcp_note_id = mrnote.id
+     left join note mrmnote on mrmnote.id = (
+        select max(n.id) from note n 
+        where 
+              n.client_id = client.id AND 
+              n.is_cancelled = FALSE AND
+              (n.is_signed_by_hcp IS NOT NULL AND n.is_signed_by_hcp = TRUE) AND
+              n.effective_dateest::date >= care_month.start_date::date AND 
+              n.effective_dateest::date < (care_month.start_date::date + INTERVAL '1 month')
+     )
+    left join pro mcp_pro on care_month.mcp_pro_id = mcp_pro.id
+    left join pro rmm_pro on care_month.rmm_pro_id = rmm_pro.id
+        ";
+        $sqlParams = [];
+
+        $values = $this->getValues($sql, $sqlParams);
+
+        $spreadsheetId = '1jRCkukeSfZufY8gpKSGYgv9cgeDbA1ZYP4pKJhyPP_o';
+        $sheetName = 'Sheet1';
+        return $this->exportToGsheet($sql, $sqlParams, $spreadsheetId, $sheetName);
+
+    }
+
+
+    private function exportToGsheet($sql, $sqlParams, $spreadsheetId, $sheetName){
+       
+        $client = $this->getApiClient();
+        $service = new \Google\Service\Sheets($client);
+
+        
+        $values = $this->getValues($sql, $sqlParams);
+
+        $range = $sheetName.'!A1:V1';
+        $body = new ValueRange([
+            'values' => $values
+        ]);
+        $params = [
+           'valueInputOption' => 'RAW'
+        ];
+
+        $result = $service->spreadsheets_values->append($spreadsheetId, $range, $body, $params);
+
+        return $result;
+    }
+
+
+    function getApiClient(){
+      
+        $KEY_FILE_LOCATION = storage_path('stag-gsheets-d9ead2f78b4b.json');
+
+        $client = new Google_Client();
+        $client->setApplicationName("My Rooster Admin");
+        $client->setAuthConfig($KEY_FILE_LOCATION);
+        
+        $client->setScopes([\Google\Service\Sheets::DRIVE, \Google\Service\Sheets::SPREADSHEETS]);
+
+        return $client;
+
+    }
+
+
+    private function getValues($sql, $sqlParams){
+
+        $values = [];
+
+        $raws = DB::select($sql, $sqlParams);
+
+        if(!count($raws)){
+            throw new \Exception("No data");
+        }
+
+        $firstRaw = $raws[0];
+
+        $headers = [];
+        foreach($firstRaw as $k => $val) {
+            $headers[] = $k;
+        }
+        $values[] = $headers;
+
+        
+        foreach($raws as $raw){
+            $rawStr = '';
+            foreach($headers as $header ){
+                $rawStr = $rawStr.$raw->$header.'~~';
+            }
+            $values[] = explode('~~', $rawStr);
+        }
+        
+       
+        return $values;
+    }
+
+}

+ 297 - 0
app/Http/Controllers/InvoiceController.php

@@ -0,0 +1,297 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Lib\Backend;
+use App\Models\AppSession;
+use App\Models\BillingReport;
+use App\Models\CareMonth;
+use App\Models\ClaimEDI;
+use App\Models\ClientProChange;
+use App\Models\Company;
+use App\Models\Customer;
+use App\Models\CustomerTransaction;
+use App\Models\GiftCard;
+use App\Models\Handout;
+use App\Models\Invoice;
+use App\Models\InvoiceTransaction;
+use App\Models\MBClaim;
+use App\Models\Measurement;
+use App\Models\Bill;
+use App\Models\Claim;
+use App\Models\Client;
+use App\Models\McpRequest;
+use App\Models\McCodeCheck;
+use App\Models\Note;
+use App\Models\Pack;
+use App\Models\Pro;
+use App\Models\Product;
+use App\Models\ProFavorite;
+use App\Models\ProGeneralAvailability;
+use App\Models\ProProAccess;
+use App\Models\ProRate;
+use App\Models\ProSpecificAvailability;
+use App\Models\ProSpecificUnavailability;
+use App\Models\ProTeam;
+use App\Models\ProTextShortcut;
+use App\Models\ProTransaction;
+use App\Models\Shipment;
+use App\Models\SupplyOrder;
+use App\Models\Team;
+use App\Models\Ticket;
+use App\Models\AccountInvite;
+use App\Models\ClientMeasurementDaysPerMonth;
+use App\Models\ClientBDTDevice;
+use App\Models\ClientMemo;
+use Carbon\Carbon;
+use Cassandra\Custom;
+use Illuminate\Pagination\LengthAwarePaginator;
+use Illuminate\Support\Facades\Cookie;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Http;
+use MongoDB\Driver\Session;
+use PDF;
+use DateTime;
+use DateTimeZone;
+use Illuminate\Http\Request;
+use App\Models\SegmentTemplate;
+use App\Models\VisitTemplate;
+use App\Models\VisitTemplateSegmentTemplate;
+use App\Models\VisitTemplateAccess;
+
+class InvoiceController extends Controller
+{
+
+    private static $PAGE_SIZE = 25;
+
+    public function companies(Request $request) {
+        $records = Company::orderBy('name', 'ASC')->where('is_active', true)->paginate(InvoiceController::$PAGE_SIZE);
+        return view ('app.invoice-center.companies', compact('records'));
+    }
+
+    public function customers(Request $request) {
+        $records = Customer::orderBy('created_at', 'DESC');
+        $company = null;
+        if($request->input('companyUid')) {
+            $company = Company::where('uid', $request->input('companyUid'))->first();
+            if($company) {
+                $records = $records->where('company_id', $company->id);
+            }
+        }
+        $records = $records->paginate(InvoiceController::$PAGE_SIZE);
+        return view ('app.invoice-center.customers', compact('records', 'company'));
+    }
+
+    public function giftCards(Request $request) {
+        $records = GiftCard::orderBy('created_at', 'DESC');
+        $company = null;
+        if($request->input('companyUid')) {
+            $company = Company::where('uid', $request->input('companyUid'))->first();
+            if($company) {
+                $records = $records->where('company_id', $company->id);
+            }
+        }
+        $records = $records->paginate(InvoiceController::$PAGE_SIZE);
+        return view ('app.invoice-center.gift-cards', compact('records', 'company'));
+    }
+
+    public function invoices(Request $request) {
+        $records = Invoice::orderBy('created_at', 'DESC');
+        $customer = null;
+        if($request->input('customerUid')) {
+            $customer = Customer::where('uid', $request->input('customerUid'))->first();
+            if($customer) {
+                $records = $records->where('customer_id', $customer->id);
+            }
+        }
+        $records = $records->paginate(InvoiceController::$PAGE_SIZE);
+        return view ('app.invoice-center.invoices', compact('records', 'customer'));
+    }
+
+    public function customerTransactions(Request $request) {
+        $records = CustomerTransaction::orderBy('created_at', 'DESC');
+        $customer = null;
+        if($request->input('customerUid')) {
+            $customer = Customer::where('uid', $request->input('customerUid'))->first();
+            if($customer) {
+                $records = $records->where('customer_id', $customer->id);
+            }
+        }
+        $records = $records->paginate(InvoiceController::$PAGE_SIZE);
+        return view ('app.invoice-center.customer-transactions', compact('records', 'customer'));
+    }
+
+    public function invoiceTransactions(Request $request) {
+        $records = InvoiceTransaction::orderBy('created_at', 'DESC');
+        $invoice = null;
+        if($request->input('invoiceUid')) {
+            $invoice = Invoice::where('uid', $request->input('invoiceUid'))->first();
+            if($invoice) {
+                $records = $records->where('invoice_id', $invoice->id);
+            }
+        }
+        $records = $records->paginate(InvoiceController::$PAGE_SIZE);
+        return view ('app.invoice-center.invoice-transactions', compact('records', 'invoice'));
+    }
+
+    private function getICCustomer($sessionKey) {
+        $customer = false;
+        if($sessionKey) {
+            Cookie::queue('sessionKey', $sessionKey);
+        }
+        else {
+            $session = get_current_session();
+            if(!$session) {
+                abort(403);
+            }
+            else {
+                $customer = Customer::where('id', $session->customer_id)->first();
+                if(!$customer) {
+                    abort(403);
+                }
+            }
+        }
+        return $customer;
+    }
+
+    public function icPayInvoice(Request $request, $invoiceUid, $sessionKey = '') {
+        $customer = $this->getICCustomer($sessionKey);
+        if(!$customer) {
+            return redirect(route('icPayInvoice', ['invoiceUid' => $invoiceUid]));
+        }
+        $invoice = Invoice::where('uid', $invoiceUid)->where('is_active', true)->first();
+        if (!$invoice) abort(404);
+        $company = $customer->company;
+        return view('app.invoice-center.ic-pay-invoice', compact('invoice', 'customer', 'company'));
+    }
+
+    public function icCustomerPortal(Request $request, $sessionKey = '') {
+        $customer = $this->getICCustomer($sessionKey);
+        if(!$customer) {
+            return redirect(route('icCustomerPortal'));
+        }
+        $client = $customer->client;
+        $company = $customer->company;
+        return view('app.invoice-center.ic-customer-portal', compact('customer', 'company'));
+    }
+
+    public function icManageAccount(Request $request, $sessionKey = '') {
+        $customer = $this->getICCustomer($sessionKey);
+        if(!$customer) {
+            return redirect(route('icManageAccount'));
+        }
+        $client = $customer->client;
+        $company = $customer->company;
+        return view('app.invoice-center.ic-manage-account', compact('customer', 'company', 'client'));
+    }
+
+    public function companySuggestJSON(Request $request) {
+        $term = $request->input('term') ? trim($request->input('term')) : '';
+        if (empty($term)) return '';
+        $matches = DB::select("
+SELECT company.uid,
+       company.name as text
+FROM company
+WHERE company.name ILIKE :term
+ORDER BY company.name",
+            ['term' => $term . '%']
+        );
+        return json_encode([
+            "success" => true,
+            "data" => $matches
+        ]);
+    }
+
+    public function clientSuggestJSON(Request $request) {
+        $term = $request->input('term') ? trim($request->input('term')) : '';
+        if (empty($term)) return '';
+
+        // if multiple words in query, check for all (max 2)
+        $term2 = '';
+        if(strpos($term, ' ') !== FALSE) {
+            $terms = explode(' ', $term);
+            $term = trim($terms[0]);
+            $term2 = trim($terms[1]);
+        }
+
+        if(!empty($term2)) {
+            $matches = DB::select("
+SELECT client.uid,
+       (client.name_first || ' ' || client.name_last) as text
+FROM client
+WHERE (client.name_first ILIKE :term OR client.name_last ILIKE :term OR client.name_first ILIKE :term2 OR client.name_last ILIKE :term2)
+ORDER BY client.name_first, client.name_last",
+                ['term' => $term . '%', 'term2' => $term2 . '%']
+            );
+        }
+        else {
+            $matches = DB::select("
+SELECT client.uid,
+       (client.name_first || ' ' || client.name_last) as text
+FROM client
+WHERE (client.name_first ILIKE :term OR client.name_last ILIKE :term)
+ORDER BY client.name_first, client.name_last",
+                ['term' => $term . '%']
+            );
+        }
+
+        return json_encode([
+            "success" => true,
+            "data" => $matches
+        ]);
+    }
+
+    public function customerSuggestJSON(Request $request) {
+        $term = $request->input('term') ? trim($request->input('term')) : '';
+        if (empty($term)) return '';
+
+        // if multiple words in query, check for all (max 2)
+        $term2 = '';
+        if(strpos($term, ' ') !== FALSE) {
+            $terms = explode(' ', $term);
+            $term = trim($terms[0]);
+            $term2 = trim($terms[1]);
+        }
+
+        if(!empty($term2)) {
+            $matches = DB::select("
+SELECT customer.uid,
+       (client.name_first || ' ' || client.name_last || ' (' || company.name || ')') as text
+FROM client join customer on client.id = customer.client_id join company on customer.company_id = company.id
+WHERE (client.name_first ILIKE :term OR client.name_last ILIKE :term OR client.name_first ILIKE :term2 OR client.name_last ILIKE :term2)
+ORDER BY client.name_first, client.name_last",
+                ['term' => $term . '%', 'term2' => $term2 . '%']
+            );
+        }
+        else {
+            $matches = DB::select("
+SELECT customer.uid,
+       (client.name_first || ' ' || client.name_last || ' (' || company.name || ')') as text
+FROM client join customer on client.id = customer.client_id join company on customer.company_id = company.id
+WHERE (client.name_first ILIKE :term OR client.name_last ILIKE :term)
+ORDER BY client.name_first, client.name_last",
+                ['term' => $term . '%']
+            );
+        }
+
+        return json_encode([
+            "success" => true,
+            "data" => $matches
+        ]);
+    }
+
+    public function customerInvoicesJSON(Request $request, Customer $customer) {
+        $invoices = [];
+        foreach ($customer->invoices as $invoice) {
+            $invoices[] = [
+                "uid" => $invoice->uid,
+                "text" => $invoice->displayName()
+            ];
+        }
+        return json_encode([
+            "success" => true,
+            "data" => $invoices
+        ]);
+    }
+   
+}

+ 28 - 0
app/Http/Controllers/PayerController.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Validator;
+
+use App\Models\Payer;
+use Illuminate\Support\Facades\DB;
+
+class PayerController extends Controller
+{
+	public function searchPayerV2JSON(Request $request)
+	{
+		$term = $request->input('term') ? trim($request->input('term')) : '';
+		if (empty($term)) return '';
+		$matches = DB::select(
+			"
+			SELECT id, uid, (name || ' (' || COALESCE(availity_payer_id, '--') || ')') as text FROM payer WHERE name ILIKE :term OR memo ILIKE :term", 
+			['term' => '%' . $term . '%']
+		);
+
+		return json_encode([
+			"success" => true,
+			"data" => $matches
+		]);
+	}
+}

+ 48 - 0
app/Http/Controllers/StatTreeLineReportColumnController.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace App\Http\Controllers;
+
+
+use App\Models\Clause;
+use App\Models\StatTreeLineClause;
+use App\Models\StatTreeLineReportColumn;
+use Illuminate\Http\Request;
+use App\Models\StatTree;
+use App\Models\StatTreeLine;
+use App\Models\Client;
+use App\Models\Pro;
+use Illuminate\Support\Facades\DB;
+use Ramsey\Uuid\Uuid;
+
+class StatTreeLineReportColumnController extends Controller
+{
+
+    // eps
+    public function create(Request $request) {
+        $column = new StatTreeLineReportColumn();
+        $nextId = DB::select("select nextval('stat_tree_line_report_column_id_seq')");
+        $column->id = $nextId[0]->nextval;
+        $column->uid = Uuid::uuid4();
+        $column->stat_tree_line_id = $request->input('statTreeLineId');
+        $column->label = $request->input('label');
+        $column->display_key = $request->input('displayKey');
+        $positionIndex = DB::select("select max(position_index) from stat_tree_line_report_column where stat_tree_line_id = {$column->stat_tree_line_id}");
+        $column->position_index = is_numeric($positionIndex[0]->max) ? $positionIndex[0]->max + 1 : 1;
+        $column->save();
+        return $this->pass();
+    }
+    public function update(Request $request) {
+        $column = StatTreeLineReportColumn::where('uid', $request->input('uid'))->first();
+        if(!$column) return $this->fail('Column not found!');
+        $column->label = $request->input('label');
+        $column->display_key = $request->input('displayKey');
+        $column->save();
+        return $this->pass();
+    }
+    public function remove(Request $request) {
+        $column = StatTreeLineReportColumn::where('uid', $request->input('uid'))->first();
+        if(!$column) return $this->fail('Column not found!');
+        DB::select("delete from stat_tree_line_report_column where id = {$column->id}");
+        return $this->pass();
+    }
+}

+ 27 - 0
app/Http/Controllers/SupervisingPhysicianController.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Http\Controllers;
+
+
+use Illuminate\Http\Request;
+use App\Models\ClientReviewRequest;
+class SupervisingPhysicianController extends Controller
+{
+
+    public function dashboard(Request $request){
+        $performer = $this->performer();
+        $pro = $performer->pro;
+        $performerProID = $performer->pro->id;
+
+        $milliseconds = strtotime(date('Y-m-d')) . '000'; //required by the calendar
+        return view('app.ps.dashboard', compact( 'milliseconds'));
+    }
+
+    public function clientReviewRequests(Request $request){
+        $hideTitle = $request->get('hideTitle');
+        $performer = $this->performer();
+        $pro = $performer->pro;
+        $reviewRequests = ClientReviewRequest::where('pro_id', $pro->id)->where('is_active', true)->orderBy('created_at', 'DESC')->paginate(50);
+        return view('app.ps.review-requests.list', compact('reviewRequests', 'hideTitle'));
+    }
+}

+ 27 - 0
app/Http/Middleware/EnsureClientIsNotShadowOfPro.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Models\AppSession;
+use Closure;
+
+class EnsureClientIsNotShadowOfPro
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @return mixed
+     */
+    public function handle($request, Closure $next)
+    {
+        $patient = \request()->route('patient');
+        if(!!$patient) {
+            if(!!$patient->shadow_pro_id) {
+                abort(403);
+            }
+        }
+        return $next($request);
+    }
+}

+ 29 - 0
app/Http/Middleware/EnsureMcpPro.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Models\AppSession;
+use Closure;
+
+class EnsureMcpPro
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @return mixed
+     */
+    public function handle($request, Closure $next)
+    {
+        $sessionKey = $request->cookie('sessionKey');
+        $appSession = AppSession::where('session_key', $sessionKey)->where('is_active', true)->first();
+        $authenticated = $sessionKey && $appSession && $appSession->pro && $appSession->pro->is_enrolled_as_mcp;
+
+        if (!$authenticated) {
+            return abort(403);
+        }
+
+        return $next($request);
+    }
+}

+ 29 - 0
app/Http/Middleware/EnsureNaPro.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Models\AppSession;
+use Closure;
+
+class EnsureNaPro
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @return mixed
+     */
+    public function handle($request, Closure $next)
+    {
+        $sessionKey = $request->cookie('sessionKey');
+        $appSession = AppSession::where('session_key', $sessionKey)->where('is_active', true)->first();
+        $authenticated = $sessionKey && $appSession && $appSession->pro && $appSession->pro->is_considered_for_dna;
+
+        if (!$authenticated) {
+            return abort(403);
+        }
+
+        return $next($request);
+    }
+}

BIN
app/Models/.Segment.php.swp


+ 22 - 0
app/Models/AdministratorBillFlagUpdate.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class AdministratorBillFlagUpdate extends Model
+{
+    protected $table = 'administrator_bill_flag_update';
+
+    public function billl() {
+        return $this->hasOne(Bill::class, 'id', 'bill_id');
+    }
+
+    public function billFlagAcknowledgedByProAdmin() {
+        return $this->hasOne(Pro::class, 'id', 'flagged_by_administrator_pro_id');
+    }
+
+    public function billFlagAcknowledgedByPro() {
+        return $this->hasOne(Pro::class, 'id', 'administrator_flag_acknowledged_by_pro_id');
+    }
+}

+ 13 - 0
app/Models/ClauseArg.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class ClauseArg extends Model
+{    
+    protected $table = 'clause_arg';
+    public $timestamps = false;
+
+}

+ 11 - 0
app/Models/ClientBpWeightPhoneNumberStatus.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class ClientBpWeightPhoneNumberStatus extends Model
+{
+    protected $table = 'client_bp_weight_phone_number_status';
+
+}

+ 22 - 0
app/Models/ClientCarePlanFlagUpdate.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class ClientCarePlanFlagUpdate extends Model
+{
+    protected $table = 'client_care_plan_flag_update';
+
+    public function client() {
+        return $this->hasOne(Client::class, 'id', 'client_id');
+    }
+
+    public function carePlanFlagAcknowledgedBy() {
+        return $this->hasOne(Pro::class, 'id', 'flag_acknowledged_by_pro_id');
+    }
+
+    public function carePlanFlaggedBy() {
+        return $this->hasOne(Pro::class, 'id', 'flagged_by_pro_id');
+    }
+}

+ 15 - 0
app/Models/ClientRepFollowUp.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class ClientRepFollowUp extends Model
+{
+    protected $table = 'client_rep_follow_up';
+
+    public function pro(){
+        return $this->hasOne(Pro::class, 'id', 'client_rep_pro_id');
+    }
+
+}

+ 23 - 0
app/Models/ClientReviewRequest.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class ClientReviewRequest extends Model
+{
+    protected $table = 'client_review_request';
+
+    public function pro() {
+        return $this->hasOne(Pro::class, 'id', 'pro_id');
+    }
+
+    public function client() {
+        return $this->hasOne(Client::class, 'id', 'client_id');
+    }
+
+    public function createdBySession() {
+        return $this->hasOne(AppSession::class, 'id', 'created_by_session_id');
+    }
+
+}

+ 13 - 0
app/Models/ClientRtmTransmission.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class ClientRtmTransmission extends Model
+{
+
+    protected $table = "client_rtm_transmission";
+
+    //
+}

+ 21 - 0
app/Models/ClientStickyNote.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Relations\HasMany;
+use Illuminate\Database\Eloquent\Relations\HasOne;
+
+class ClientStickyNote extends Model
+{
+    protected $table = 'client_sticky_note';
+
+    public function createdBy(): HasOne
+    {
+        return $this->hasOne(AppSession::class, 'id', 'created_by_session_id');
+    }
+
+    public function client(): HasOne
+    {
+        return $this->hasOne(Client::class, 'id', 'client_id');
+    }
+}

+ 32 - 0
app/Models/CompanyProDocument.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class CompanyProDocument extends Model
+{
+
+    protected $table = 'company_pro_document';
+
+    public function companyPro()
+    {
+        return $this->hasOne(CompanyPro::class, 'id', 'company_pro_id');
+    }
+
+    public function company()
+    {
+        return $this->hasOne(Company::class, 'id', 'company_id');
+    }
+
+    public function pro()
+    {
+        return $this->hasOne(Pro::class, 'id', 'pro_id');
+    }
+
+    public function hrmSignature()
+    {
+        return $this->hasOne(Pro::class, 'id', 'counter_signing_hrm_pro_id');
+    }
+
+}

+ 34 - 0
app/Models/Customer.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+use Illuminate\Database\Eloquent\Relations\HasMany;
+
+class Customer extends Model
+{
+    protected $table = 'customer';
+
+    public function client() {
+        return $this->hasOne(Client::class, 'id', 'client_id');
+    }
+
+    public function company() {
+        return $this->hasOne(Company::class, 'id', 'company_id');
+    }
+
+    public function invoices() {
+        return $this->hasMany(Invoice::class, 'customer_id', 'id')->orderBy('created_at', 'DESC');
+    }
+
+    public function customerTransactions() {
+        return $this->hasMany(CustomerTransaction::class, 'customer_id', 'id')->orderBy('created_at', 'ASC');
+    }
+
+    public function paymentMethods() {
+        return $this->hasMany(PaymentMethod::class, 'customer_id', 'id')
+            ->where('is_active', true)
+            ->orderByRaw('created_at DESC');
+    }
+}

+ 14 - 0
app/Models/CustomerTransaction.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class CustomerTransaction extends Model
+{
+    protected $table = 'customer_transaction';
+
+    public function customer() {
+        return $this->hasOne(Customer::class, 'id', 'customer_id');
+    }
+}

+ 14 - 0
app/Models/GiftCard.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class GiftCard extends Model
+{
+    protected $table = 'gift_card';
+
+    public function company() {
+        return $this->hasOne(Company::class, 'id', 'company_id');
+    }
+}

+ 24 - 0
app/Models/Invoice.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class Invoice extends Model
+{
+    protected $table = 'invoice';
+
+    public function displayName() {
+        return '$' . $this->amount .
+        ($this->description ? ' | ' . substr($this->description, 0, 15) : '') .
+        ' | ' . friendly_date_time($this->created_at);
+    }
+
+    public function customer() {
+        return $this->hasOne(Customer::class, 'id', 'customer_id');
+    }
+
+    public function invoiceTransactions() {
+        return $this->hasMany(InvoiceTransaction::class, 'invoice_id', 'id')->orderBy('created_at', 'ASC');
+    }
+}

+ 14 - 0
app/Models/InvoiceTransaction.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class InvoiceTransaction extends Model
+{
+    protected $table = 'invoice_transaction';
+
+    public function invoice() {
+        return $this->hasOne(Invoice::class, 'id', 'invoice_id');
+    }
+}

+ 11 - 0
app/Models/Isms.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class Isms extends Model
+{
+    protected $table = 'isms';
+
+}

+ 12 - 0
app/Models/NoteReasons.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class NoteReasons extends Model
+{
+
+    protected $table = 'note_reasons';
+    //
+}

+ 11 - 0
app/Models/OutgoingEmailTemplate.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class OutgoingEmailTemplate extends Model
+{
+    protected $table = 'outgoing_email_template';
+
+}

+ 17 - 0
app/Models/PaymentMethod.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Models;
+
+class PaymentMethod extends Model
+{
+    protected $table = 'payment_method';
+
+    public function customer(){
+        return $this->hasOne(Customer::class, 'id', 'customer_id');
+    }
+
+    public function displayName(){
+        $parsed = json_decode($this->detail_json);
+        return "<b>{$parsed->card->brand}</b> ending in <b>{$parsed->card->last4}</b>, expiring {$parsed->card->exp_month} / {$parsed->card->exp_year}";
+    }
+}

+ 15 - 0
app/Models/ProEvent.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class ProEvent extends Model
+{
+    protected $table = 'pro_event';
+
+    public function pro()
+    {
+        return $this->hasOne(Pro::class, 'id', 'pro_id');
+    }
+}

+ 13 - 0
app/Models/SegmentSummaryChange.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class SegmentSummaryChange extends Model
+{
+    protected $table = 'segment_summary_change';
+
+   
+
+}

+ 16 - 0
app/Models/SegmentSummarySuggestion.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class SegmentSummarySuggestion extends Model
+{
+    protected $table = 'segment_summary_suggestion';
+
+    public function creator()
+    {
+        return $this->hasOne(Pro::class, 'id', 'created_by_pro_id');
+    }
+
+}

+ 11 - 0
app/Models/Stamp.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class Stamp extends Model
+{
+    protected $table = 'stamp';
+
+}

+ 17 - 0
app/Models/StatTreeLineClauseArg.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class StatTreeLineClauseArg extends Model
+{
+    public $table = 'stat_tree_line_clause_arg';
+    public $timestamps = false;
+
+    public function clauseArg(){
+        return $this->hasOne(ClauseArg::class, 'id', 'clause_arg_id');
+    }
+
+}

+ 18 - 0
app/Models/StatTreeLineReportColumn.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class StatTreeLineReportColumn extends Model
+{
+    protected $table = 'stat_tree_line_report_column';
+    public $timestamps = false;
+
+    public function getRouteKeyName()
+    {
+        return 'uid';
+    }
+
+}

+ 11 - 0
app/Models/Status.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class Status extends Model
+{
+    protected $table = 'status';
+
+}

+ 17 - 0
app/Models/VisitTemplateAccess.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class VisitTemplateAccess extends Model
+{
+    protected $table = 'visit_template_access';
+
+    public function pro() {
+        return $this->hasOne(Pro::class, 'id', 'pro_id');
+    }
+    public function visitTemplate() {
+        return $this->hasOne(Pro::class, 'id', 'visit_template_id');
+    }
+}

+ 18 - 0
app/Models/VisitTemplateSegmentTemplate.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Models;
+
+# use Illuminate\Database\Eloquent\Model;
+
+class VisitTemplateSegmentTemplate extends Model
+{
+    protected $table = 'visit_template_segment_template';
+
+    public function segmentTemplate(){
+        return $this->hasOne(SegmentTemplate::class, 'id', 'segment_template_id');
+    }
+
+    public function visitTemplate(){
+        return $this->hasOne(VisitTemplate::class, 'id', 'visit_template_id');
+    }
+}

+ 75 - 0
config/constants.php

@@ -0,0 +1,75 @@
+<?php
+  return [
+      'medicaid_states' => [
+        "MEDICAID ALABAMA",
+        "MEDICAID ALASKA",
+        "MEDICAID ARIZONA",
+        "MEDICAID ARKANSAS",
+        "MEDICAID CALIFORNIA MEDI-CAL",
+        "MEDICAID COLORADO",
+        "MEDICAID CONNECTICUT",
+        "MEDICAID DELAWARE",
+        "MEDICAID DISTRICT OF COLUMBIA",
+        "MEDICAID FLORIDA",
+        "MEDICAID GEORGIA",
+        "MEDICAID HAWAII",
+        "MEDICAID IDAHO",
+        "MEDICAID ILLINOIS",
+        "MEDICAID INDIANA",
+        "MEDICAID IOWA",
+        "MEDICAID KANSAS",
+        "MEDICAID KENTUCKY",
+        "MEDICAID LOUISIANA",
+        "MEDICAID MAINE",
+        "MEDICAID MARYLAND",
+        "MEDICAID MARYLAND DHMH",
+        "MEDICAID MASSACHUSETTS",
+        "MEDICAID MICHIGAN",
+        "MEDICAID MINNESOTA",
+        "MEDICAID MISSISSIPPI",
+        "MEDICAID MISSISSIPPI",
+        "MEDICAID MISSOURI",
+        "MEDICAID MONTANA",
+        "MEDICAID NEBRASKA",
+        "MEDICAID NEVADA",
+        "MEDICAID NEW HAMPSHIRE",
+        "MEDICAID NEW JERSEY",
+        "MEDICAID NEW MEXICO",
+        "MEDICAID NEW YORK",
+        "MEDICAID NEW YORK",
+        "MEDICAID NORTH CAROLINA",
+        "MEDICAID NORTH DAKOTA",
+        "MEDICAID OHIO",
+        "MEDICAID OKLAHOMA",
+        "MEDICAID OREGON",
+        "MEDICAID OREGON (DHS OMAP)",
+        "MEDICAID PENNSYLVANIA",
+        "MEDICAID RHODE ISLAND",
+        "MEDICAID SOUTH CAROLINA",
+        "MEDICAID SOUTH DAKOTA",
+        "MEDICAID TENNESSEE",
+        "MEDICAID TEXAS",
+        "MEDICAID TEXAS AND TEXAS HEALTH STEPS",
+        "MEDICAID UTAH",
+        "MEDICAID VERMONT",
+        "MEDICAID VIRGINIA",
+        "MEDICAID WASHINGTON (PROVIDER ONE)",
+        "MEDICAID WEST VIRGINIA",
+        "MEDICAID WISCONSIN",
+        "MEDICAID WYOMING",
+      ],
+      'client_engagement_status_color_codes' => [
+        'ACTIVE' => 'rgba(157, 223, 172, 0.5)',
+        'INACTIVE' => 'rgba(220, 53, 69, 0.5)',
+        'ENTRY_ERROR' => 'rgba(220, 53, 69, 0.5)',
+        'DUMMY' => 'rgba(255, 193, 7, 0.5)',
+        'DECEASED' => 'rgba(78, 80, 82, 0.5)',
+        'DUPLICATE' => 'rgba(23, 162, 184, 0.5)',
+        'NO_LONGER_INTERESTED' => 'rgba(255, 3, 61, 0.5)',
+        'BAD_RECORD' => 'rgba(102, 16, 242, 0.5)',
+        'NO_LONGER_ELIGIBLE' => 'rgba(253, 126, 20, 0.5)',
+      ]
+  ];
+
+
+?>

+ 19 - 0
config/patient-intake-data.php

@@ -0,0 +1,19 @@
+<?php 
+
+return [
+    'height' => 'Height',
+    'weight' => 'Weight',
+    'last_vitamin_d' => 'Last Vitamin D',
+    'ethnicity' => 'Ethnicity',
+    'ethnicity_checkboxes' => [
+        'is_hispanic' => 'Hispanic',
+        'is_black_or_aa' => 'Black or African American',
+        'is_native_american' => 'Native American'
+    ],
+    'hypertension' => 'Hypertension',
+    'diabetes' => 'Diabetes',
+    'copd' => 'COPD',
+    'arthritis' => 'Arthritis',
+    'emailAddress' => 'Email Address',
+    'stickyNote' => 'Sticky Note'
+];

+ 34 - 0
config/rtm.php

@@ -0,0 +1,34 @@
+<?php
+
+return [
+    'exercises' => [
+        [
+            'name' => 'Bench Press',
+            'description' => 'Description of bench press goes here. Not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset.',
+            'image' => 'https://cdn.mos.cms.futurecdn.net/pLaRi5jXSHDKu6WRydetBo-970-80.jpg.webp',
+            'video' => 'https://www.youtube.com/embed/aclHkVaku9U',
+            'props' => [
+                'Weekly', 'Daily', 'Sets', 'Reps'
+            ]
+        ],
+        [
+            'name' => 'Squats',
+            'description' => 'Description of squats goes here. Not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset.',
+            'image' => 'https://media.self.com/photos/5ea9bc77bb9c6b75996c7e91/4:3/w_640,c_limit/squats_woman_exercise.jpg',
+            'video' => 'https://www.youtube.com/embed/aclHkVaku9U',
+            'props' => [
+                'Weekly', 'Daily', 'Sets', 'Reps'
+            ]
+        ],
+        [
+            'name' => 'Walking',
+            'description' => 'Description of walking goes here. Not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset.',
+            'image' => 'https://i0.wp.com/post.greatist.com/wp-content/uploads/sites/2/2020/04/GRT-female-walking-street-1296x728-header.jpg?w=1575',
+            'video' => 'https://www.youtube.com/embed/aclHkVaku9U',
+            'props' => [
+                'Weekly', 'Daily', 'Duration', 'Intensity'
+            ]
+        ],
+
+    ]
+];

+ 14 - 0
copy-js.sh

@@ -0,0 +1,14 @@
+\cp js-dev/yemi.js public/js/yemi.js
+\cp js-dev/tsvToArray.js public/js/tsvToArray.js
+\cp js-dev/stag-table-filter.js  public/js/stag-table-filter.js
+\cp js-dev/stag-suggest.js  public/js/stag-suggest.js
+\cp js-dev/stag-popup.js  public/js/stag-popup.js
+\cp js-dev/stag-collapsible-card.js  public/js/stag-collapsible-card.js
+\cp js-dev/show-on-click.js  public/js/show-on-click.js
+\cp js-dev/shortcut.js  public/js/shortcut.js
+\cp js-dev/pro-suggest.js  public/js/pro-suggest.js
+\cp js-dev/option-list.js  public/js/option-list.js
+\cp js-dev/mc-init.js  public/js/mc-init.js
+\cp js-dev/mc.js  public/js/mc.js
+\cp js-dev/dq.js  public/js/dq.js
+\cp js-dev/click-to-copy.js  public/js/click-to-copy.js

+ 284 - 0
coverage_spec_april_29_2022.txt

@@ -0,0 +1,284 @@
+Determine which client->primaryCoverage to use 
+
+if there is latest_manual_client_primary_coverage_id  and its not cancelled use it 
+else:
+    if there is latest_auto_refresh_client_primary_coverage_id and latest_new_client_primary_coverage_id use the latest 
+    else use whichever is there 
+    else
+        no coverage 
+
+TEST CASE
+    - create a new client 
+    - add manual coverage 
+    - cancel manual coverage 
+    - add new coverage 
+    - auto refresh the new coverage 
+    - add another new 
+
+
+=====================
+- add new (automatically when you create a client ), or when you go Primary Coverage -> Add +
+- go  primary coverage, on an exising coverage, do manual determination 
+- go to primary coverage, on an existing coverage, click refresh 
+
+
+client->getPrimaryCoverage(); //Already done 
+TODO: use this everywhere on the ui NO $client->latestClientPrimaryCoverage
+
+1. header blade 
+2. thin blade to be used for tables
+
+How to display on the header and table columns
+- is client covered  
+        $coverage->is_covered
+        - Medicare 
+            IF AUTO/NEW
+                autoMedicareIsPartBActive;
+                autoMedicareIsPartBPrimary;
+                autoMedicareIsPartCActive;
+                autoMedicareIsInpatient;
+                autoMedicareIsHospiceOrHomeHealth;
+                autoMedicareMpbRemaining
+            IF MANUAL 
+                manualDeterminationCategory
+                manualMedicareIsPartBActive
+                manualMedicareIsPartBPrimary
+                manualMedicareIsPartCActive
+                manualMedicareIsInpatient
+                manualMedicareIsHospiceOrHomeHealth
+                manualMedicareIsMsp
+                manualMedicareMspMemo
+        - Commercial
+                commercialPayerUid;
+                commercialPayerName;
+                **commercialMemberIdentifier;
+                **commercialGroupNumber;
+                **mcrNumber;
+                mcdPayerName;
+                **mcdNumber;
+            IF AUTO/NEW
+                autoCommercialIsMatchFound;
+                autoCommercialMoreSpecificPayerId; //gives official commerical name 
+                if has medicare 
+                    autoMedicareIsMatchFound
+                    autoMedicareIsPartBActive;
+                    autoMedicareIsPartBPrimary;
+                    autoMedicareIsPartCActive;
+                    autoMedicareIsInpatient;
+                    autoMedicareIsHospiceOrHomeHealth;
+                    mpbRemaining 
+                if has medicaid 
+                    autoMedicaidIsMatchFound
+
+            IF MANUAL 
+                manualDeterminationCategory
+                manualCommercialIsMatched
+                if has medicare 
+                    manualMedicareIsMatched
+                    manualMedicareIsPartBActive
+                    manualMedicareIsPartBPrimary
+                    manualMedicareIsPartCActive
+                    manualMedicareIsInpatient
+                    manualMedicareIsHospiceOrHomeHealth
+                    manualMedicareIsMsp
+                    manualMedicareMspMemo
+                if has medicaid 
+                    manualMedicaidIsMatched;
+
+        - Medicaid 
+            mcdPayerName;
+		    mcdNumber;
+            IF AUTO/NEW
+                autoMedicaidIsMatchFound
+            IF MANUAL
+                manualDeterminationCategory
+                manualMedicareIsMatched
+
+
+ 
+    latest_auto_refresh_client_primary_coverage_id //latest after refresh
+    latest_client_primary_coverage_id //lastest after manual or refresh
+    latest_manual_client_primary_coverage_id //latest after manual
+    latest_new_client_primary_coverage_id /latest after a client has just been created, always the latest client_primary_coverage, 
+
+How to display on client primary coverage section
+on coverage section show 3 tabs with all the columns 
+    latest_manual_client_primary_coverage_id //latest after manual
+    latest_auto_refresh_client_primary_coverage_id //latest after refresh
+    latest_new_client_primary_coverage_id
+- Highlight the one that is currently in use 
+
+auto_medicare_detail_json
+auto_commercial_detail_json
+auto_medicaid_detail_json
+
+
+
+client 
+    is_hospice
+    is_mcn_valid_number
+    is_medicare_advantage
+    is_part_b_primary
+    mcn
+    mcn_address_city
+    mcn_address_state
+    mcn_address_street_line1
+    mcn_address_street_line2
+    mcn_address_zip
+    mcn_error_details
+    mcn_follow_up_action_code
+    mcn_follow_up_action_description
+    mcn_reject_reason_code
+    mcn_reject_reason_description
+    mcn_response_detail
+    medicare_advantage_plan
+    mother_maiden_name
+    was_medicare_validation_successful
+    is_coverage_manually_verified
+    coverage_manual_verification_memo
+    latest_eligible_refresh_id
+    latest_eligible_refresh_at
+    mpb_active
+    mpb_start_date
+    mpb_end_date
+    mpb_deductible
+    mpb_remaining
+    mpb_insurance_type
+    mpb_insurance_type_label
+    mpb_coinsurance_percent
+    mpb_info_valid_until
+    mpb_info_valid_till
+    mpb_last_refreshed_atpayer_name
+    payer_name
+    payer_member_id
+    non_mc_primary_payer_id
+    non_mc_secondary_payer_id
+    latest_auto_refresh_client_primary_coverage_id
+    latest_client_primary_coverage_id
+    latest_manual_client_primary_coverage_id
+    latest_new_client_primary_coverage_id
+    temporary_outsider_new_client_primary_coverage_id
+    is_auto_part_b_primary
+
+
+
+client_primary_coverage
+    client_id
+    creation_strategy
+    auto_refresh_of_client_primary_coverage_id
+    manual_determination_of_client_primary_coverage_id
+    plan_type
+    is_partbprimary
+    is_manually_determined
+    is_entry_error
+    subscriber_name_first
+    subscriber_name_last
+    subscriber_sex
+    subscriber_dob
+    date_of_service
+    auto_medicare_is_partbprimary
+    auto_medicare_is_partbactive
+    auto_medicare_is_partcactive
+    auto_medicare_is_inpatient
+    auto_medicare_is_hospice_or_home_health
+    auto_medicare_is_msp
+    auto_medicare_msp_memo
+    auto_medicare_mpb_start_date
+    auto_medicare_mpb_end_date
+    auto_medicare_mpb_deductible
+    auto_medicare_mpb_remaining
+    auto_medicare_mpb_insurance_type
+    auto_medicare_mpb_insurance_type_label
+    auto_medicare_mpb_coinsurance_percent
+    auto_medicare_mpb_info_valid_until
+    auto_medicare_mpb_info_valid_till
+    auto_medicare_mpb_last_refreshed_at
+    was_successful
+    reject_reason_code
+    reject_reason_description
+    follow_up_action_code
+    follow_up_action_description
+    details
+    is_mcn_valid_number
+    address_street_line1
+    address_street_line2
+    address_city
+    address_state
+    address_zip
+    is_hospice
+    mcn_response_detail
+    billing_address
+    reason_not_partb
+    reason_not_partbmemo
+    is_medicare_advantage
+    medicare_advantage_plan
+    mpb_active
+    mpb_start_date
+    mpb_end_date
+    mpb_deductible
+    mpb_remaining
+    mpb_insurance_type
+    mpb_insurance_type_label
+    mpb_coinsurance_percent
+    mpb_info_valid_until
+    mpb_info_valid_till
+    mpb_last_refreshed_at
+    manual_determination_strategy
+    manual_determination_category
+    manual_determination_category_memo
+    manual_medicare_is_partbprimary
+    manual_medicare_is_partbactive
+    manual_medicare_is_partcactive
+    manual_medicare_is_inpatient
+    manual_medicare_is_hospice_or_home_health
+    manual_medicare_is_msp
+    manual_medicare_msp_memo
+    auto_medicare_result_id
+    mcd_number
+    mcr_number
+    subscriber_name_middle
+    subscriber_name_suffix
+    auto_commercial_detail_json
+    auto_commercial_is_match_found
+    auto_commercial_more_specific_payer_id
+    auto_medicaid_detail_json
+    auto_medicaid_is_match_found
+    auto_medicare_is_match_found
+    commercial_member_identifier
+    commercial_payer_id
+    commercial_payer_name
+    is_partcactive
+    is_patient_subscriber
+    manual_medicaid_is_matched
+    manual_medicare_is_matched
+    mcd_payer_id
+    patient_dob
+    patient_name_first
+    patient_name_last
+    patient_name_middle
+    patient_name_suffix
+    patient_relationship_to_subscriber
+    patient_sex
+    commercial_group_number
+    auto_medicare_detail_json
+    is_covered
+    last_updated_at
+    deductible_amount
+    family_deductible
+    member_accumulated_total
+    plan_description
+    plan_effective_date
+    provider_status
+    total_family_balance
+    total_individual_balance
+    mental_health_coverage
+    telehealth_coverage
+    cancellation_memo
+    cancelled_at
+    cancelled_by_session_id
+    is_cancelled
+
+
+    medicare
+    medicaid 
+    commercial

+ 67 - 0
js-dev/click-to-copy.js

@@ -0,0 +1,67 @@
+(function() {
+    function fallbackCopyTextToClipboard(text, pasteTo = false) {
+        var textArea = document.createElement("textarea");
+        textArea.value = text;
+
+        // Avoid scrolling to bottom
+        textArea.style.top = "0";
+        textArea.style.left = "0";
+        textArea.style.position = "fixed";
+
+        document.body.appendChild(textArea);
+        textArea.focus();
+        textArea.select();
+
+        try {
+            var successful = document.execCommand('copy');
+            var msg = successful ? 'successful' : 'unsuccessful';
+            console.log('Fallback: Copying text command was ' + msg);
+            toastr.success('Copied!');
+            pasteToElement(pasteTo, text);
+        } catch (err) {
+            console.error('Fallback: Oops, unable to copy', err);
+        }
+
+        document.body.removeChild(textArea);
+    }
+    function copyTextToClipboard(text, pasteTo = false) {
+        if (!navigator.clipboard) {
+            fallbackCopyTextToClipboard(text);
+            return;
+        }
+        navigator.clipboard.writeText(text).then(function() {
+            console.log('Async: Copying to clipboard was successful!');
+            toastr.success('Copied!');
+            pasteToElement(pasteTo, text);
+        }, function(err) {
+            console.error('Async: Could not copy text: ', err);
+        });
+    }
+    function pasteToElement(_elem, _text) {
+        if(_elem && _elem.length) {
+            // if rte
+            if(_elem.is('.ql-container') && _elem[0].__quill) {
+                let qlRoot = _elem[0].__quill.root;
+                if($.trim($(qlRoot.innerHTML).text()) === '') {
+                    _elem[0].__quill.clipboard.dangerouslyPasteHTML(0, _text);
+                    _elem[0].__quill.root.focus();
+                }
+            }
+            else _elem.val(_text);
+        }
+    }
+
+    function init() {
+        $(document)
+            .off('click.click-to-copy', '.click-to-copy')
+            .on('click.click-to-copy', '.click-to-copy', function(event) {
+                let self = $(this);
+                copyTextToClipboard(self.text(),
+                    self.is('[auto-paste]') ? self.closest('form').find(self.attr('auto-paste')) : false);
+            });
+        window.copyTextToClipboard = copyTextToClipboard;
+    }
+
+    addMCInitializer('click-to-copy', init);
+
+}).call(window);

+ 142 - 0
js-dev/dq.js

@@ -0,0 +1,142 @@
+(function() {
+    window.initDQ = function() {
+        $(document)
+            .off('change input paste', '.dq-edit-container input, .dq-edit-container textarea, .dq-edit-container select')
+            .on('change input paste', '.dq-edit-container input, .dq-edit-container textarea, .dq-edit-container select', function() {
+                let key = $(this).closest('.dq-line').attr('dq-key'),
+                    dataElem = $(this).closest('.dq-edit-container').find('>.dq-data-map').first(),
+                    current = JSON.parse(dataElem.text());
+                current[key] = $(this).val();
+                let serialized = JSON.stringify(current);
+                dataElem.text(serialized);
+                $(this).closest('form').find('input[name="data"]').val(serialized);
+                let fullData = {
+                    lines: JSON.parse($(this).closest('.dq-edit-container').find('>.dq-definition').first().text()),
+                    dataMap: current
+                };
+                $(this).closest('form').find('input[name="data"]').val(JSON.stringify(fullData));
+
+                runDQConditions($(this).closest('.dq-edit-container'));
+            });
+        $(document)
+            .off('input.auto-grow', '.dq-edit-container textarea')
+            .on('input.auto-grow', '.dq-edit-container textarea', function() {
+                this.style.minHeight = "calc(1.5em + .5rem + 2px)";
+                this.style.height = "calc(1.5em + .5rem + 2px)";
+                this.style.height = (this.scrollHeight)+"px";
+            });
+    };
+
+    function resolveAtomicCondition(_condition, _dataMap) {
+        if(!_condition.hasOwnProperty('key') || !_condition.hasOwnProperty('value')) {
+            _condition.resolution = false;
+            return;
+        }
+        let key = _condition.key, op = _condition.hasOwnProperty('op') ? _condition.op : 'eq';
+        let lhs = _dataMap[key], rhs = _condition.value;
+        switch(op) {
+            case 'eq':
+                _condition.resolution = (lhs == rhs); // NOTE: using == instead of === on purpose
+                break;
+            case 'lt':
+                _condition.resolution = (+lhs < +rhs);
+                break;
+            case 'lte':
+                _condition.resolution = (+lhs <= +rhs);
+                break;
+            case 'gt':
+                _condition.resolution = (+lhs > +rhs);
+                break;
+            case 'gte':
+                _condition.resolution = (+lhs >= +rhs);
+                break;
+            default:
+                _condition.resolution = false;
+        }
+    }
+
+    function resolveAllAtomicConditions(_conditions, _dataMap) {
+        if(Array.isArray(_conditions)) {
+            for (let i = 0; i < _conditions.length; i++) {
+                resolveAllAtomicConditions(_conditions[i], _dataMap);
+            }
+        }
+        else if(typeof _conditions === 'object') {
+            resolveAtomicCondition(_conditions, _dataMap);
+        }
+    }
+
+    function reduceConditionsIntoResolutions(_conditions) {
+        for (let i = 0; i < _conditions.length; i++) {
+            // if simple object, resolve
+            if(!Array.isArray(_conditions[i]) && typeof _conditions[i] === 'object') {
+                _conditions.splice(i, 1, _conditions[i].resolution);
+            }
+            else if(Array.isArray(_conditions[i])) {
+                reduceConditionsIntoResolutions(_conditions[i]);
+            }
+        }
+    }
+
+    function combineResolutionListsIntoSingleResolutions(_conditions) {
+        console.log('ALIX 1', _conditions);
+        for (let i = 0; i < _conditions.length; i++) {
+            if(Array.isArray(_conditions[i])) {
+                _conditions[i] = combineResolutionListsIntoSingleResolutions(_conditions[i]);
+            }
+        }
+        console.log('ALIX 2', _conditions);
+
+        // at this point, the array will have only booleans and "AND", "OR" combinators
+        let resolution = _conditions[0];
+        for (let i = 1; i < _conditions.length; i+=2) {
+            if(_conditions[i] === 'AND') {
+                resolution = resolution && _conditions[i + 1];
+            }
+            else if(_conditions[i] === 'OR') {
+                resolution = resolution || _conditions[i + 1];
+            }
+        }
+
+        return resolution;
+    }
+
+    window.runDQConditions = function(_parent) {
+
+        _parent.find('.dq-line.has-pre-condition').each(function() {
+            let conditions = JSON.parse($(this).find('>.dq-pre-condition').first().text()),
+                dataMap = JSON.parse($(this).closest('.dq-edit-container').find('>.dq-data-map').first().text());
+
+            resolveAllAtomicConditions(conditions, dataMap);
+
+            // if object, single condition with key, op and value
+            if(!Array.isArray(conditions) && typeof conditions === 'object') {
+                if(conditions.resolution) {
+                    $(this).removeClass('d-none');
+                }
+                else {
+                    $(this).addClass('d-none');
+                }
+            }
+            // else if array - means list of conditions with 'and' or 'or' separators - array size MUST be an odd number
+            else if(Array.isArray(conditions)) {
+
+                // goal is to reduce each item in the array into a single boolean - recursively
+                reduceConditionsIntoResolutions(conditions);
+
+                conditions = combineResolutionListsIntoSingleResolutions(conditions);
+
+                if(conditions) {
+                    $(this).removeClass('d-none');
+                }
+                else {
+                    $(this).addClass('d-none');
+                }
+
+            }
+
+        });
+
+    }
+    addMCInitializer('dq-edit', initDQ, '.dq-edit-container');
+}).call(window);

+ 32 - 0
js-dev/icd-autocomplete.js

@@ -0,0 +1,32 @@
+(function() {
+
+    function init() {
+        let self = this;
+        $('[icd-autocomplete-code]:not([ac-initialized])').each(function() {
+            let elem = this, dynID = 'icd-' + Math.ceil(Math.random() * 1000000),
+                codeElem = $(this), descElem = $(this).closest('form, tr').first().find('[icd-autocomplete-description]');
+            var targetDescElem = $(this).data('target');
+            if(targetDescElem){
+                descElem = $(this).closest('form').find(targetDescElem);
+            }
+            $(elem).attr('id', dynID);
+            new window.Def.Autocompleter.Search(dynID,
+                'https://clinicaltables.nlm.nih.gov/api/icd10cm/v3/search?sf=code,name&ef=name', {
+                    tableFormat: true,
+                    valueCols: [0],
+                    colHeaders: ['Code', 'Name'],
+                }
+            );
+            window.Def.Autocompleter.Event.observeListSelections(dynID, function() {
+                let autocomp = elem.autocomp, acData = autocomp.getSelectedItemData();
+                codeElem.val(acData[0].code).trigger('change');
+                descElem.val(acData[0].data['name']).attr('title', acData[0].data['name']).trigger('change');
+                return false;
+            });
+            $(elem).attr('ac-initialized', 1);
+        });
+    }
+
+    addMCInitializer('icd-autocomplete', init);
+
+}).call(window);

+ 81 - 0
js-dev/mc-init.js

@@ -0,0 +1,81 @@
+window.mcInitializers = {};
+window.addMCInitializer = function(_name, _func, _container) {
+    if(!!window.mcInitializers[_name]) {
+        // console.warn('ALIX initializer ' + _name + ' exists. Will overwrite.');
+        delete window.mcInitializers[_name];
+    }
+    window.mcInitializers[_name] = {
+        func: _func,
+        container: _container
+    };
+};
+window.runMCInitializers = function(_target = null) {
+    if(!!mcInitializers) {
+        // console.log('ALIX -----------------');
+        for(let initer in mcInitializers) {
+            if(mcInitializers.hasOwnProperty(initer)) {
+                try {
+                    let initerObj = mcInitializers[initer];
+                    if(!initerObj.container || $(initerObj.container).length) {
+                        // console.log("ALIX running MC initer", initer);
+                        initerObj.func(_target);
+                    }
+                    else {
+                        // console.warn("ALIX MC initer not in context. Removing ", initer);
+                        delete mcInitializers[initer];
+                        initerObj = null;
+                    }
+                }
+                catch(e) {
+                    console.warn('MC init error: ', e);
+                    console.warn('Initer: ', initer);
+                }
+            }
+        }
+    }
+};
+window.runMCInitializer = function(_initer) {
+    if(!!mcInitializers && !!mcInitializers[_initer]) {
+        try {
+            let initerObj = mcInitializers[_initer];
+            if(!initerObj.container || $(initerObj.container).length) {
+                // console.log("ALIX running MC initer", initer);
+                initerObj.func();
+            }
+            else {
+                // console.warn("ALIX MC initer not in context. Removing ", initer);
+                delete mcInitializers[_initer];
+                initerObj = null;
+            }
+        }
+        catch(e) {
+            console.warn('MC init error: ', e);
+            console.warn('Initer: ', _initer);
+        }
+    }
+};
+window.mcHooks = {};
+window.addMCHook = function(_name, _func) {
+    if(!!window.mcHooks[_name]) {
+        // console.warn('ALIX initializer ' + _name + ' exists. Will overwrite.');
+        delete window.mcHooks[_name];
+    }
+    window.mcHooks[_name] = {
+        func: _func
+    };
+};
+window.hasMCHook = function(_initer) {
+    return !!mcHooks && !!mcHooks[_initer];
+}
+window.runMCHook = function(_initer) {
+    if(!!mcHooks && !!mcHooks[_initer]) {
+        try {
+            let initerObj = mcHooks[_initer];
+            initerObj.func();
+        }
+        catch(e) {
+            console.warn('MC hook error: ', e);
+            console.warn('Hook: ', _initer);
+        }
+    }
+};

+ 756 - 0
js-dev/mc.js

@@ -0,0 +1,756 @@
+window.top.currentMcUrl = '';
+window.top.addEventListener('popstate', function (event) {
+    window.setTimeout(function () {
+        hideMask();
+        hideMoeFormMask();
+        if (!event || (!event.state && event.state !== '')) {
+            // console.error('ALIX No state!', event, event.state);
+            return;
+        }
+        var state = event.state;
+        if (state === '') state = '/';
+        if (state[0] !== '/') state = '/' + state;
+        if (!!state) fastLoad(state, false, true);
+    }, 0);
+});
+$(document).ready(function () {
+
+    var originalLocationPath = window.location.pathname;
+    var params = window.location.search;
+    // TODO make it so if param 'xy' is passed in, it doesn't go to parent
+    var noMcStuffOnLoad = originalLocationPath.indexOf('notes') >= 0;
+
+    if(!window.noMc){
+        if (window.location.pathname === window.top.location.pathname) {
+            window.top.location.href = '/mc' + window.location.pathname + window.location.search;
+            return;
+        }
+    }
+
+    if(window.noMc) return;
+
+    // window.top.ensureRHS();
+    $(document).on('click', '.stag_rhs_toggle', function () {
+        var state = window.top.toggleRHS(),
+            icon = $(this).find('i');
+        if (state === 'collapsed') {
+            icon.removeClass().addClass('fa fa-arrow-left');
+        } else {
+            icon.removeClass().addClass('fa fa-arrow-right');
+        }
+    });
+    var body = $(window.top.document.body),
+        icon = $('.stag_rhs_toggle i');
+    if (body.is('.stag_rhs_collapsed')) {
+        icon.removeClass().addClass('fa fa-arrow-left');
+    }
+    initCreateNote();
+    initQuillEdit();
+    initFastLoad();
+    initPrimaryForm();
+    initPatientPresenceIndicator();
+    runMCInitializers();
+    initFileInputs();
+
+    // if(typeof initializeCalendar !== 'undefined') {
+    //     initializeCalendar();
+    // }
+    // if(typeof initIntakeEvents !== 'undefined') {
+    //     initIntakeEvents();
+    // }
+
+    // populate history on fresh load
+    var target = window.top.location.pathname + window.top.location.search;
+    if (target.indexOf('/mc') === 0) {
+        target = target.split('/mc')[1];
+    }
+    if(noMcStuffOnLoad){
+        target = originalLocationPath;
+    }
+    if(!window.noMc){
+        fastLoad(target, true, false, true);
+    }
+
+
+});
+function enableTimeSpecificFields(_checked, _valueClass, _rangeClass) {
+    if (_valueClass) $('.' + _valueClass).prop('disabled', _checked);
+    if (_rangeClass) $('.' + _rangeClass).prop('disabled', !_checked);
+}
+function toggleDisabledAsNeeded(_el, _targetValue, _enableClass, _disableClass) {
+    if (_el.value === _targetValue) {
+        if (_enableClass) $('.' + _enableClass).prop('disabled', false);
+        if (_disableClass) $('.' + _disableClass).prop('disabled', true);
+    }
+    else {
+        if (_enableClass) $('.' + _enableClass).prop('disabled', true);
+        if (_disableClass) $('.' + _disableClass).prop('disabled', false);
+    }
+}
+function toggleVisibilityAsNeeded(_el, _targetValue, _visibleClass, _hiddenClass) {
+    if (_el.value === _targetValue) {
+        if (_visibleClass) $('.' + _visibleClass).removeClass('d-none');
+        if (_hiddenClass) $('.' + _hiddenClass).addClass('d-none');
+    }
+    else {
+        if (_visibleClass) $('.' + _visibleClass).addClass('d-none');
+        if (_hiddenClass) $('.' + _hiddenClass).removeClass('d-none');
+    }
+}
+var fastCache = {};
+
+function initFastLoad(_parent = false) {
+
+    var allAs = $('a[href]:not([onclick]):not([href="#"]):not([native]):not([open-in-stag-popup])');
+    if (_parent) {
+        allAs = _parent.find('a[href]:not([onclick]):not([href="#"]):not([native]):not([open-in-stag-popup])');
+    }
+
+    // clear cache
+    if (!_parent) {
+        fastCache = {};
+    }
+    else {
+        allAs.each(function () {
+            if (typeof fastCache[this.href] !== 'undefined') {
+                delete fastCache[this.href];
+            }
+        });
+    }
+
+    // find links without event handlers
+    allAs.each(function () {
+        if (!$(this).closest('[moe]').length) {
+            if ($(this).closest('.dropdown-menu').length) {
+                enableFastLoad(this, true);
+            } else {
+                // var handlers = findEventHandlers('click', this);
+                // if (!handlers || !handlers.length) {
+                enableFastLoad(this);
+                // }
+            }
+        }
+    });
+
+    function enableFastLoad(_a, _menuItem = false) {
+        $(_a)
+            .off('click.fast-load')
+            .on('click.fast-load', function () {
+                fastLoad(this.href, true, true);
+                $('.dropdown-menu')
+                    .removeClass('show')
+                    .prev('.dropdown-toggle').attr('aria-expanded', 'false');
+                return false;
+            });
+        // console.info('FastLoad enabled for ' + _a.innerText + ' [' + _a.href + ']');
+    }
+
+    // fast cache
+    // allAs = $('a[href]:not([onclick]):not([href="#"])');
+    // allAs.each(function () {
+    //     var a = this;
+    //     $.get(a.href, function (_data) {
+    //         fastCache[a.href] = _data;
+    //     });
+    // });
+
+}
+
+function onFastLoaded(_data, _href, _history, _target = null) {
+
+    if (!Number.isInteger(_data)) {
+        _data = '<div>' + _data + '</div>';
+
+        // do for each element in _target
+        let responseError = false;
+        let originalTarget = _target;
+        _target = _target ? _target : '.stag-content';
+        _target = _target.split(',').map(_x => $.trim(_x));
+        for (let i = 0; i < _target.length; i++) {
+            let t = _target[i];
+            let targetElement = $(t).first();
+            if(targetElement.length) {
+                let sourceElement = $(_data).find(t).first();
+                if (sourceElement && sourceElement.length) {
+                    targetElement.html(sourceElement.html());
+                    initFastLoad(targetElement);
+                    console.log('ALIX loaded element: ' + t);
+                }
+                else {
+                    responseError = true;
+                }
+            }
+            else {
+                responseError = true;
+            }
+        }
+
+        if (!responseError) {
+            hideMask();
+            hideMoeFormMask();
+            window.setTimeout(function () {
+                initCreateNote();
+                initQuillEdit();
+                initPrimaryForm();
+                initPatientPresenceIndicator();
+                initFileInputs();
+                initMoes();
+                runMCInitializers(originalTarget);
+                if (window.top.currentMcUrl.split('?')[0] !== window.top.location.href.split('?')[0]) {
+                    $(window).scrollTop(0);
+                }
+                window.top.currentMcUrl = window.top.location.href;
+            }, 0);
+        }
+        else {
+            $('.stag-content').first().html('<p class="text-danger p-3 small">Error on page: <b>' + _href + '</b></p>');
+            hideMask();
+            hideMoeFormMask();
+        }
+        appendRedirectUrl();
+    } else {
+        // fallback
+        let msg = 'Unable to open page: ';
+        switch (_data) {
+            case 403:
+                msg = 'You do not have access to this page: ';
+                break;
+            case 404:
+                msg = 'Page not found: ';
+                break;
+            case 500:
+                msg = 'Error on page: ';
+                break;
+            case 0: // not logged in - refresh top level window to go to login
+                window.top.location = '/';
+                break;
+        }
+        console.warn('MC: Target page failed: ' + _href);
+        $('.stag-content').first().html('<p class="text-danger p-3 small"><b>' + _data + '</b> - ' + msg + '<b>' + _href + '</b></p>');
+        hideMask();
+        hideMoeFormMask();
+        appendRedirectUrl();
+    }
+    $('html, body').removeClass('no-scroll');
+}
+
+function appendRedirectUrl(_url) {
+    let targetLocation = window.top.location.pathname + window.top.location.search;
+    if(targetLocation.indexOf('/mc') === 0) {
+        targetLocation = targetLocation.substr(3);
+    }
+    let form = $('.frm-back-to-admin');
+    if(form.length) {
+        form.attr('action', form.attr('data-action') + '?redir=' + targetLocation);
+    }
+}
+
+var fastReload = function(_target = null) {
+    var targetLocation = window.top.location.pathname + window.top.location.search;
+    if(targetLocation.indexOf('/mc') === 0) {
+        targetLocation = targetLocation.substr(3);
+    }
+    if(targetLocation === '' || targetLocation[0] !== '/') targetLocation = '/' + targetLocation;
+    fastLoad(targetLocation, false, false, false, _target);
+    return false;
+}
+
+function fastLoad(_href, _history = true, _useCache = true, _replaceState = false, _target = null) {
+
+    let domPro = $(window.top.document.body).attr('data-pro-uid'),
+        lsPro = window.top.localStorage.currentProUid;
+    if(lsPro && domPro && lsPro !== domPro) {
+        console.warn('ALIX Looks like you have a session as another pro on another tab. Refreshing window.top...');
+        window.top.location.href = _href;
+        return false;
+    }
+
+    showMask();
+
+    if (_href === '') _href = '/';
+
+    // push state
+    if (_history && window.parent === window.top) {
+        var target = _href;
+        if (target.indexOf('//') !== -1) {
+            target = target.split('//')[1];
+            if (target.indexOf('/') !== -1) {
+                target = target.substr(target.indexOf('/') + 1);
+            }
+        }
+        if (target[0] === '/') target = target.substr(1);
+        if (_replaceState) {
+            window.top.history.replaceState(target, null, '/mc/' + target);
+        }
+        else {
+            window.top.history.pushState(target, null, '/mc/' + target);
+        }
+    }
+
+    // dont show top nav if in iframe
+    if(window !== window.top && window.parent !== window.top) {
+        $('body').addClass('in-iframe');
+    }
+
+    if (_useCache && !!fastCache[_href]) {
+        onFastLoaded(fastCache[_href], _href, _history, _target);
+    } else {
+
+        let cleanedHREF = _href;
+        if(cleanedHREF.length > 1 && cleanedHREF[cleanedHREF.length - 1] === '/') {
+            cleanedHREF = cleanedHREF.substr(0, cleanedHREF.length - 1);
+        }
+        if(cleanedHREF.length > 2) {
+            cleanedHREF = cleanedHREF.replace('/?', '?');
+        }
+
+        if(cleanedHREF.length > 0 && cleanedHREF[0] === '?') cleanedHREF = '/' + cleanedHREF;
+
+        $.get(cleanedHREF, function (_data) {
+            onFastLoaded(_data, _href, _history, _target);
+        }).fail(function (_jqXhr) {
+            onFastLoaded(_jqXhr.status, _href, _history, _target);
+        });
+    }
+}
+
+function initPrimaryForm(_form = false) {
+    var primaryForm = _form ? _form : $('.primary-form:visible');
+    if (primaryForm.length) {
+        primaryForm = primaryForm.first();
+        var rte = primaryForm.find('[contenteditable="true"]').first();
+        if (rte.length) {
+            rte.focus().select();
+        }
+        else {
+            if (primaryForm.find('[autofocus]:visible').length) {
+                primaryForm.find('[autofocus]:visible').first().focus().select();
+            }
+            else {
+                primaryForm.find('input:not([type="hidden"]):visible, textarea:visible, select:visible').first().focus().select();
+            }
+        }
+    }
+}
+
+function openInRHS(_url) {
+    window.top.showRHS();
+    var icon = $('.stag_rhs_toggle i');
+    icon.removeClass().addClass('fa fa-arrow-right');
+    window.top.openInRHS(_url);
+    return false;
+}
+
+function initCreateNote() {
+    $(document)
+        .off('click.create-note', '.create-auto-note-trigger')
+        .on('click.create-note', '.create-auto-note-trigger', function () {
+            createNewNote($(this).attr('data-patient-uid'), $(this).attr('data-hcp-uid'), $(this).attr('data-effective-date'));
+        });
+    if ($('select[name="hasMcpDoneOnboardingVisit"]').length) {
+        $('select[name="hasMcpDoneOnboardingVisit"]').trigger('change');
+    }
+}
+
+function createNewNote(_patientUid, _hcpUid, _date) {
+    hideMoeFormMask();
+    showMask();
+    $.post('/api/note/createUsingFreeTextHtml', {
+        clientUid: _patientUid,
+        hcpProUid: _hcpUid,
+        effectiveDateEST: _date,
+    }, function (_data) {
+        hideMask();
+        if (!_data.success) {
+            toastr.error(_data.message);
+        }
+        else {
+            fastLoad('/patients/view/' + _patientUid + '/notes/view/' + _data.data, true, false);
+        }
+    }, 'json');
+}
+
+function initQuillEdit(_selector = '.note-content[auto-edit]') {
+
+    $(document)
+        .off('click.enable-edit', '.note-content:not([auto-edit]):not(.readonly)')
+        .on('click.enable-edit', '.note-content:not([auto-edit]):not(.readonly)', function () {
+            $(this).attr('auto-edit', 1);
+            initQuillEdit();
+            initPrimaryForm();
+            initPatientPresenceIndicator();
+        });
+
+    if (!$(_selector).length) return;
+    var noteUid = $(_selector).attr('data-note-uid');
+    var qe = new Quill(_selector, {
+        theme: 'snow',
+        modules: stagQuillConfig
+    });
+    var toolbar = $(qe.container).prev('.ql-toolbar');
+    var saveButton = $('<button class="btn btn-sm btn-primary w-auto px-3 py-0 text-sm text-white save-note-content">Save</button>');
+    toolbar.append(saveButton);
+    saveButton.on('click', function () {
+        $.post('/api/note/putFreeTextHtml', {
+            uid: noteUid,
+            freeTextHtml: qe.root.innerHTML,
+        }, function (_data) {
+            if (!_data.success) {
+                toastr.error(_data.message);
+            }
+            else {
+                // toastr.success('Note saved');
+                // saveButton.prop('disabled', true);
+                fastLoad(window.top.location.pathname.substr(3), false, false);
+            }
+        }, 'json');
+    });
+
+    // give a unique id to this editor instance
+    var editorID = Math.ceil(Math.random() * 99999);
+
+    // add button for new shortcut
+    var newSCButton = $('<button class="btn btn-sm btn-default w-auto px-2 ml-2 border py-0 ' +
+        'text-sm add-shortcut" data-editor-id="' + editorID + '">+ Shortcut</button>');
+    toolbar.append(newSCButton);
+
+    // qe.on('text-change', function() {
+    //     saveButton.prop('disabled', false);
+    // });
+    $('.ql-editor[contenteditable]')
+        .attr('data-editor-id', editorID)
+        .attr('with-shortcuts', 1);
+}
+
+function initQuillRTE(_selector, _config = false, _shortcuts = false) {
+    if(!_config) _config = stagQuillConfig;
+    $(_selector).each(function() {
+
+        $(this).wrap(
+            $('<div class="border-left border-right rte-holder"/>')
+                .attr('data-shortcuts', '')
+        );
+
+        // give a unique id to this editor instance
+        var editorID = Math.ceil(Math.random() * 99999),
+            fieldName = this.name;
+
+        var ti = $('<input type="hidden" />')
+            .val(this.value)
+            .attr('name', this.name)
+            .insertBefore(this);
+        var ce = $('<div data-editor-id="' + editorID + '" data-field="' + this.name + '"/>')
+            .html(this.value)
+            .insertBefore(this);
+        $(this).remove();
+
+        var qe = new Quill('[data-editor-id="' + editorID + '"]', {
+            theme: 'snow',
+            modules: _config ? _config : stagQuillConfig
+        });
+        var toolbar = $(qe.container).prev('.ql-toolbar');
+
+        // add button for new shortcut
+        if(_shortcuts) {
+            var newSCButton = $('<button class="btn bg-white btn-sm btn-default text-primary w-auto px-2 border py-0 ' +
+                'text-sm add-shortcut" data-editor-id="' + editorID + '">+ Shortcut</button>');
+            toolbar.append(newSCButton);
+        }
+
+        qe.on('text-change', function() {
+            ti.val(qe.root.innerHTML);
+        });
+
+        $(qe.container)
+            .find('.ql-editor[contenteditable]')
+            .attr('data-field', fieldName)
+            .attr('data-editor-id', editorID)
+            .attr('with-shortcuts', 1);
+
+    });
+}
+
+var patientPresenceTimer = false;
+function initFileInputs() {
+    $(document)
+        .off('change', 'input[type="file"]')
+        .on('change', 'input[type="file"]', function(_e) {
+            if(_e.target.files && _e.target.files.length) {
+                $(this).attr('selected-file', _e.target.files[0].name);
+            }
+            else {
+                $(this).attr('selected-file', 'No file chosen');
+            }
+            return false;
+        });
+    $('input[type="file"]').attr('selected-file', 'No file chosen');
+}
+function initPatientPresenceIndicator() {
+    return false;
+    if (patientPresenceTimer !== false) {
+        window.clearInterval(patientPresenceTimer);
+        patientPresenceTimer = false;
+        console.log('Cancelled previous timer!');
+    }
+    var elem = $('.patient-presence-indicator[data-patient-uid]');
+    if (elem.length) {
+        var patientUid = elem.attr('data-patient-uid');
+        patientPresenceTimer = window.setInterval(function () {
+            var elem = $('.patient-presence-indicator[data-patient-uid]');
+            if (elem.length) {
+                var patientUid = elem.attr('data-patient-uid');
+                $.get('/patients/' + patientUid + '/presence', function (_data) {
+                    if (_data.online) {
+                        elem.addClass('online');
+                    }
+                    else {
+                        elem.removeClass('online');
+                    }
+                }, 'json');
+            }
+        }, 15000); // once in 15 seconds
+    }
+}
+
+// not really the place for this!
+// find a better place to put this
+window.fillJsonDataField = function(form, field = "data") {
+    // add [data-name] values to payload
+    if(form.is('[data-field-name]')) {
+        field = form.attr('data-field-name');
+    }
+    let dataField = form.find('[name="' + field + '"]').first();
+    let parsed = null;
+    if(dataField.val()) {
+        parsed = JSON.parse(dataField.val());
+    }
+    form.find('[data-name]').each(function() {
+        if(!parsed) parsed = {};
+
+        let keys = $(this).attr('data-name').split('->');
+        let currentNode = parsed;
+        for (let i = 0; i < keys.length; i++) {
+            if(i !== keys.length - 1) {
+                if(typeof currentNode[keys[i]] === 'undefined') {
+                    currentNode[keys[i]] = {};
+                }
+                currentNode = currentNode[keys[i]];
+            }
+            else {
+                if($(this).is(':radio')) {
+                    if($(this).prop('checked')) {
+                        currentNode[keys[i]] = this.value;
+                    }
+                }
+                else if($(this).is(':checkbox')) {
+                    currentNode[keys[i]] = $(this).prop('checked');
+                }
+                else {
+                    currentNode[keys[i]] = $(this).val();
+                }
+            }
+        }
+
+    });
+    if(parsed) {
+        dataField.val(JSON.stringify(parsed));
+    }
+    return parsed;
+}
+window.refreshSegment = function(_segment) {
+    $('.visit-segment[data-segment-template-name="' + _segment + '"]').find('.refresh-segment').trigger('click');
+};
+window.refreshAffectedSegmentsByType = function(_type) {
+    if(!_type) {
+        console.error('refreshAffectedSegmentsByType: _type cannot be empty!');
+        return;
+    }
+    let segments = window.segmentRefreshConfig.typeToSegments[_type];
+    if(segments && segments.length) {
+        for (let i = 0; i < segments.length; i++) {
+            refreshSegment(segments[i]);
+        }
+    }
+    else {
+        if(!_type) {
+            console.error('refreshAffectedSegmentsByType: no segments to refresh for type:', _type);
+        }
+    }
+};
+window.refreshAffectedSegmentsByPopupKey = function(_key) {
+    let types = [];
+    for(let x in window.segmentRefreshConfig.wizardToTypes) {
+        if(window.segmentRefreshConfig.wizardToTypes.hasOwnProperty(x) && _key.indexOf(x) !== -1) {
+            types.push(window.segmentRefreshConfig.wizardToTypes[x]);
+            break;
+        }
+    }
+    for (let i = 0; i < types.length; i++) {
+        refreshAffectedSegmentsByType(types[i]);
+    }
+    let segments = [];
+    for(let x in window.segmentRefreshConfig.wizardToSegments) {
+        if(window.segmentRefreshConfig.wizardToSegments.hasOwnProperty(x) && _key.indexOf(x) !== -1) {
+            segments = window.segmentRefreshConfig.wizardToSegments[x];
+            break;
+        }
+    }
+    for (let i = 0; i < segments.length; i++) {
+        refreshSegment(segments[i]);
+    }
+};
+window.saveVisitForm = function(_trigger, _silent = false, _close = false, _doneCallback = null) {
+    console.info("saveVisitForm");
+    let form = $(_trigger).closest('form');
+
+    if (!_silent && !form[0].checkValidity()) {
+        form[0].reportValidity();
+        return false;
+    }
+
+    let parsed = fillJsonDataField(form);
+
+    let closeOnSave = false, noteSection = form.closest('.note-section');
+    if($(_trigger).closest('[visit-moe]').is('[close-on-save]')) {
+        closeOnSave = true;
+    }
+
+    // disallow-if-value-same-as
+    let compareWith = false;
+    if(form.find('.disallow-if-value-same-as')) {
+        compareWith = $.trim(form.find('.disallow-if-value-same-as').text());
+        if(compareWith && parsed) {
+            if(!parsed.value) {
+                alert('Value cannot be empty!');
+                return false;
+            }
+            let newValue = $('<div/>').html(parsed.value).text().replace(/[^a-zA-Z0-9]/g, '');
+            if(newValue === '') {
+                alert('Value cannot be empty!');
+                return false;
+            }
+            if(newValue === compareWith) {
+                alert('New value should be different from the previous value!');
+                return false;
+            }
+        }
+    }
+
+    if(!_silent) showMask();
+
+    $.post(form.attr('url'), form.serialize(), _data => {
+        if(!hasResponseError(_data)) {
+            if(typeof window.updateAllSegmentsInResponse !== 'undefined') {
+                window.updateAllSegmentsInResponse(_data, true, _silent);
+            }
+            let parentPopup = form.closest('.stag-popup');
+            let eps = [
+                '/api/visitPoint/upsertChildReview',
+                '/api/visitPoint/upsertChildPlan',
+                '/api/visitPoint/destroyCurrentChildReview',
+                '/api/visitPoint/destroyCurrentChildPlan',
+                '/api/visitPoint/addTopLevelBulkPreExisting'
+            ];
+            if(parentPopup.length && eps.indexOf(form.attr('url')) !== -1) {
+                refreshAffectedSegmentsByPopupKey(parentPopup.attr('stag-popup-key'));
+            }
+            if(typeof window.refreshRHSSidebar !== 'undefined') {
+                window.refreshRHSSidebar();
+            }
+            if(!_silent) {
+                hideMask();
+                if(noteSection.length) {
+                    if (closeOnSave) {
+                        noteSection.removeClass('edit');
+                        let segmentUid = form.find('[name="segmentUid"]').first();
+                        segmentUid = segmentUid.length ? segmentUid.val() : false;
+                        if (segmentUid) {
+                            window.setTimeout(() => {
+                                $('.note-tree-node>a[data-segment-uid="' + segmentUid + '"]').trigger('click');
+                            }, 250);
+                        }
+                    }
+                }
+                if($(_trigger).closest('[visit-moe]').closest('.stag-popup').length) {
+                    refreshDynamicStagPopup();
+                }
+            }
+            if(_close) {
+                closeStagPopup();
+            }
+            if(!!_doneCallback) {
+                _doneCallback();
+            }
+        }
+    }, 'json');
+    return false;
+};
+window.initSegmentMoes = function(_parent) {
+
+    $('body')
+        .off('mousedown.visit-moe-outside-click')
+        .on('mousedown.visit-moe-outside-click', function (e) {
+            if ($(e.target).closest('[visit-moe]').length ||
+                $(e.target).closest('#create-shortcut-form').length ||
+                $(e.target).is('#create-shortcut-form') ||
+                $(e.target).is('.stag-shortcuts .sc') ||
+                $(e.target).closest('.ui-datepicker').length) {
+                return;
+            }
+            $('[visit-moe] [url]:not([show])').hide();
+        });
+
+    _parent.find('[visit-moe] [submit]')
+        .off('click.visit-moe-submit')
+        .on('click.visit-moe-submit', function() {
+            saveVisitForm(this);
+            return false;
+        });
+
+    _parent.find('[visit-moe]>a[start]')
+        .off('click.visit-moe-show')
+        .on('click.visit-moe-show', function () {
+            $('[visit-moe] [url]:not([show])').hide();
+            let form = $(this).closest('[visit-moe]').find('form[url]');
+            form.show();
+            if(!form.is('[no-auto-focus]')) {
+                setTimeout(() => {
+                    form.find('.ql-editor').first().focus();
+                }, 0);
+            }
+            return false;
+        });
+
+    _parent.find('[visit-moe] [cancel]')
+        .off('click.visit-moe-cancel')
+        .on('click.visit-moe-cancel', function() {
+            $(this).closest('[visit-moe]').find('[url]:not([show])').hide();
+            if($(this).closest('[visit-moe]').is('[close-on-cancel]')) {
+                $(this).closest('.note-section').removeClass('edit');
+            }
+            return false;
+        });
+
+    $(document)
+        .off('keydown.visit-moe-escape')
+        .on('keydown.visit-moe-escape', function (e) {
+            if(e.which === 27) {
+                if(!isEventConsumed(e)) {
+                    let visibleMoes = $('[visit-moe] [url]:not([show]):visible');
+                    if (visibleMoes.length) {
+                        visibleMoes.hide();
+                        markEventAsConsumed(e);
+                        return false;
+                    }
+                }
+            }
+        });
+};
+window.isEventConsumed = function(_e) {
+    return _e && _e.originalEvent && _e.originalEvent.stagCosumed
+};
+window.markEventAsConsumed = function(_e) {
+    if(_e && _e.originalEvent) {
+        _e.originalEvent.stagCosumed = true;
+    }
+};

+ 66 - 0
js-dev/option-list.js

@@ -0,0 +1,66 @@
+(function() {
+    function showOptionsList(_input) {
+        let ol = $(_input).next('.data-option-list');
+        if(ol.length && !ol.is(':visible')) {
+            ol.show();
+            return true;
+        }
+        return false;
+    }
+    function hideOptionsList(_input) {
+        let ol = $(_input).next('.data-option-list');
+        if(ol.length && ol.is(':visible')) {
+            ol.hide();
+            return true;
+        }
+        return false;
+    }
+    function init() {
+        $(document)
+            .off('mousedown.option-list', '.data-option-list>div')
+            .on('mousedown.option-list', '.data-option-list>div', function(_e) {
+                _e.stopPropagation();
+                _e.preventDefault();
+                markEventAsConsumed(_e);
+                let elem = $(this).parent().prev('input[data-option-list]'),
+                    text = $(this).text();
+                if(!elem.is('[multi-option-list]')) {
+                    elem.val('');
+                }
+                else {
+                    elem.val($.trim(elem.val()));
+                    elem[0].selectionStart = elem[0].selectionEnd = elem.val().length;
+                    if(elem.val() !== '') text = ', ' + text;
+                }
+                elem.focus();
+                document.execCommand('insertText', false, text);
+                if(!elem.is('[sticky-option-list]')) {
+                    $(this).closest('.data-option-list').hide();
+                }
+                return false;
+            });
+        $(document)
+            .off('click.trigger-option-list', 'input[data-option-list]')
+            .on('click.trigger-option-list', 'input[data-option-list]', function() {
+                showOptionsList(this);
+            })
+            .off('focus.trigger-option-list', 'input[data-option-list]')
+            .on('focus.trigger-option-list', 'input[data-option-list]', function() {
+                showOptionsList(this);
+            })
+            .off('blur.trigger-option-list', 'input[data-option-list]')
+            .on('blur.trigger-option-list', 'input[data-option-list]', function() {
+                hideOptionsList(this);
+            })
+            .off('keydown.discard-option-list', 'input[data-option-list]')
+            .on('keydown.discard-option-list', 'input[data-option-list]', function(_e) {
+                if(_e.which === 27) {
+                    if(hideOptionsList(this)) {
+                        markEventAsConsumed(_e);
+                        return false;
+                    }
+                }
+            })
+    }
+    addMCInitializer('option-list', init);
+})();

+ 189 - 0
js-dev/pro-suggest.js

@@ -0,0 +1,189 @@
+// pro suggest functionality
+(function() {
+
+    let suggestionsOuter = null;
+
+    const debounce = (func, wait) => {
+        let timeout;
+        return function executedFunction(...args) {
+            const later = () => {
+                clearTimeout(timeout);
+                func(...args);
+            };
+            clearTimeout(timeout);
+            timeout = setTimeout(later, wait);
+        };
+    };
+
+    var lastTerm = '';
+    var returnedFunction = debounce(function (elem) {
+        var term = elem.val();
+        if(term === '') {
+            let select = suggestionsOuter.closest('.position-relative')
+                .prev('.pro-suggest-input')
+                .prev('select[provider-search]');
+            select.empty().val('').append($('<option value="" selected/>').text('')).trigger('change');
+            suggestionsOuter.addClass('d-none');
+        }
+        else {
+            if (!!term && lastTerm !== term) {
+                $.get('/pro-suggest?term=' + $.trim(term) + '&type=' + elem.attr('provider-type'), function (_data) {
+                    suggestionsOuter.html(_data).removeClass('d-none');
+                });
+                lastTerm = term;
+            } else {
+                suggestionsOuter.addClass('d-none');
+            }
+        }
+    }, 250);
+
+    function handleKeydown(elem, e) {
+        let term = $.trim(elem.val());
+        let activeItem = suggestionsOuter.find('.suggest-item.active');
+        switch (e.which) {
+            case 27:
+                suggestionsOuter.addClass('d-none');
+                markEventAsConsumed(e);
+                return false;
+            case 38:
+                if (activeItem.prev().length) {
+                    activeItem.prev()
+                        .addClass('active')
+                        .siblings().removeClass('active');
+                    activeItem = suggestionsOuter.find('.suggest-item.active');
+                    if (activeItem.length) {
+                        activeItem[0].scrollIntoView();
+                    }
+                }
+                return false;
+            case 40:
+                if (activeItem.next().length) {
+                    activeItem.next()
+                        .addClass('active')
+                        .siblings().removeClass('active');
+                    activeItem = suggestionsOuter.find('.suggest-item.active');
+                    if (activeItem.length) {
+                        activeItem[0].scrollIntoView();
+                    }
+                }
+                return false;
+            case 13:
+                if (activeItem.length) {
+                    activeItem.first().click();
+                }
+                return false;
+            default:
+                if (!!term) {
+                    suggestionsOuter
+                        .html('<span class="d-block no-suggest-items">Searching...</span>')
+                        .removeClass('d-none');
+                    returnedFunction(elem);
+                } else {
+                    suggestionsOuter.addClass('d-none');
+                }
+                break;
+        }
+    }
+
+    function handleKeypress(elem, e) {
+        var term = $.trim(elem.val());
+        if (!!term) {
+            suggestionsOuter
+                .html('<span class="d-block no-suggest-items">Searching...</span>')
+                .removeClass('d-none');
+            returnedFunction(elem);
+        } else {
+            suggestionsOuter.addClass('d-none');
+        }
+    }
+
+    window.initProSuggest = function() {
+
+        // make select[provider-search] hidden & insert a textbox with pro-suggest
+        $('select[provider-search]:not([pro-suggest-initialized]):not([no-auto-pro-suggest-init])').each(function() {
+            let elem = $(this);
+            elem.next('.pro-suggest-input').remove();
+            elem.next('.pro-suggestions-container').remove();
+            let input = $('<input type="text" placeholder="Pro">').addClass('pro-suggest-input form-control').insertAfter(elem);
+            if($(this).is('.form-control-sm')) input.addClass('form-control-sm');
+            input.attr('provider-type', elem.attr('provider-type'));
+            $('<div class="pro-suggestions-container position-relative">' +
+                '<div class="suggestions-outer pro-suggestions position-absolute d-none"></div>' +
+                '</div>').insertAfter(input);
+            elem.hide();
+
+            if (!!elem.attr('data-pro-uid')) {
+                if (!!localStorage["proDisplayNameCache_" + elem.attr('data-pro-uid')]) {
+                    let name = localStorage["proDisplayNameCache_" + elem.attr('data-pro-uid')];
+                    input.val(name).data('original', name);
+                    elem.empty().append($('<option value="' + elem.attr('data-pro-uid') + '" selected/>').text(name));
+                }
+                else {
+                    $.get('/pro-display-name/' + elem.attr('data-pro-uid'), function (_data) {
+                        localStorage["proDisplayNameCache_" + elem.attr('data-pro-uid')] = _data;
+                        input.val(_data).data('original', _data);
+                        elem.empty().append($('<option value="' + elem.attr('data-pro-uid') + '" selected/>').text(_data));
+                    });
+                }
+            }
+            else {
+                input.val(elem.attr('data-pro-name')).data('original', elem.attr('data-pro-name'));
+            }
+
+            if(elem.is('[required]')) {
+                input.attr('required', 'required');
+            }
+
+            input
+                .off('keydown.pro-suggest')
+                .on('keydown.pro-suggest', function (e) {
+                    suggestionsOuter = $(this).next('.pro-suggestions-container').find('>.suggestions-outer');
+                    return handleKeydown($(this), e);
+                })
+                .off('keypress.pro-suggest')
+                .on('keypress.pro-suggest', function (e) {
+                    suggestionsOuter = $(this).next('.pro-suggestions-container').find('>.suggestions-outer');
+                    return handleKeypress($(this), e);
+                });
+                // .off('blur.pro-suggest')
+                // .on('blur.pro-suggest', function (e) {
+                //     window.setTimeout(() => {
+                //         $(this).next('.pro-suggestions-container').find('>.suggestions-outer').addClass('d-none');
+                //         $(this).val($(this).data('original'));
+                //     }, 50);
+                // });
+
+            $(this).attr('pro-suggest-initialized', 1);
+        });
+
+        $(document).off('click', '.suggest-item.pro-suggest[data-target-uid]');
+        $(document).on('click', '.suggest-item.pro-suggest[data-target-uid]', function () {
+
+            $('.suggestions-outer.pro-suggestions').addClass('d-none');
+
+            let uid = $(this).attr('data-target-uid'),
+                label = $.trim($(this).text());
+
+            // set select value
+            let select = $(this).closest('.position-relative')
+                .prev('.pro-suggest-input')
+                .prev('select[provider-search]');
+            select.empty().append($('<option value="' + uid + '" selected/>').text(label));
+            select.val(uid).trigger('change');
+            select.trigger('pro-changed');
+
+            // set input value
+            $(this).closest('.position-relative')
+                .prev('.pro-suggest-input')
+                .val(label)
+                .data('original', label)
+                .trigger('change');
+
+            return false;
+        });
+
+    }
+    addMCInitializer('pro-suggest', initProSuggest);
+})();
+
+

+ 302 - 0
js-dev/shortcut.js

@@ -0,0 +1,302 @@
+// shortcut suggest functionality
+// auto attaches to all [with-shortcuts] elements
+(function() {
+    let input = null, menu = null, options = [], index = -1;
+    let backtrackAfterApplying = false;
+    let strPart = '';
+    function getCaretPos(win) {
+        win = win || window;
+        let doc = win.document;
+        let sel, range, rects, rect;
+        let x = 0, y = 0;
+        if (win.getSelection) { // won't work if getSelection() isn't available!
+            sel = win.getSelection();
+            if(sel.toString() !== '') return null; // won't work if there isa
+            if (sel.rangeCount) {
+                range = sel.getRangeAt(0).cloneRange();
+                if (range.getClientRects) {
+                    range.collapse(true);
+                    let span = doc.createElement("span");
+                    if (span.getClientRects) {
+                        // Ensure span has dimensions and position by
+                        // adding a zero-width space character
+                        span.appendChild( doc.createTextNode("\u200bXX") );
+                        range.insertNode(span);
+                        rect = span.getClientRects()[0];
+                        x = rect.left;
+                        y = rect.top;
+                        let spanParent = span.parentNode;
+                        spanParent.removeChild(span);
+
+                        // Glue any broken text nodes back together
+                        spanParent.normalize();
+
+                        return [x, y];
+                    }
+                    return null
+                }
+            }
+        }
+        return { x: x, y: y };
+    }
+    function show(_initial = false, _options) {
+        let pos = getCaretPos();
+        // strPart = '';
+        if(pos) {
+            index = -1;
+            options = _options;
+            if(strPart.length > 1) {
+                options = _options.filter(function(_x) {
+                    return _x.name.toLowerCase().indexOf(strPart.substr(1).toLowerCase()) !== -1;
+                });
+            }
+            menu.empty();
+            for(let i = 0; i < options.length; i++) {
+                menu.append(
+                    $('<div/>')
+                        .addClass('sc')
+                        .text(options[i].name)
+                        .attr('title', options[i].value)
+                );
+            }
+            if(_initial) {
+                menu
+                    .css({
+                        left: pos[0] + 'px',
+                        top: (pos[1] + $(window).scrollTop()) + 'px',
+                    })
+                    .show();
+                document.execCommand("insertText", true, '@');
+                document.execCommand("delete", true, null);
+            }
+        }
+    }
+    function discard() {
+        if($('.stag-shortcuts:visible').length) {
+            $('.stag-shortcuts').hide();
+            return false;
+        }
+    }
+    function highlightOption() {
+        menu.find('.sc').removeClass('active');
+        if(options && options.length && index >= 0 && index < options.length) {
+            menu.find('.sc:eq(' + index + ')').addClass('active');
+        }
+    }
+    function apply(_clearReturn = false) {
+        if(input && options && options.length && index >= 0 && index < options.length) {
+            // $(input).focus();
+            if(backtrackAfterApplying) {
+                for (let i = 0; i < strPart.length; i++) {
+                    document.execCommand("delete", true, null);
+                }
+            }
+            // if(_clearReturn) document.execCommand("delete", true, null);
+            document.execCommand("insertText", true, options[index].value);
+            discard();
+        }
+    }
+    function isVisible() {
+        return !!$('.stag-shortcuts:visible').length;
+    }
+    function init() {
+
+        var selectedText = '';
+
+        $('.stag-shortcuts').remove();
+        options = [];
+        menu = $('<div/>')
+            .addClass('stag-shortcuts')
+            .appendTo('body');
+
+        let refreshOptions = false;
+
+        $(document)
+            .off('mousedown.outside-shortcuts')
+            .on('mousedown.outside-shortcuts', function(_e) {
+                if($(_e.target).closest('.stag-shortcuts').length) return;
+                return discard();
+            });
+        $(document)
+            .off('keypress.shortcuts', '[with-shortcuts]')
+            .on('keypress.shortcuts', '[with-shortcuts]', function(_e) {
+                input = this;
+                switch(_e.which) {
+                    case 64:
+                        backtrackAfterApplying = true;
+                        strPart = '@';
+                        let options = [], noteRTE = $(input).closest('[note-rte]');
+                        let scSets = noteRTE.attr('use-shortcuts') ? noteRTE.attr('use-shortcuts').split(',') : ['user']
+                        for (let i = 0; i < scSets.length; i++) {
+                            if(window[$.trim(scSets[i]) + 'Shortcuts']) {
+                                options = options.concat(window[$.trim(scSets[i]) + 'Shortcuts']);
+                            }
+                        }
+                        show(true, options);
+                        break;
+                    default:
+                        if(!isVisible()) return;
+                        let char = String.fromCharCode(_e.which);
+                        if(_e.ctrlKey || _e.metaKey || !char.match(/[a-z0-9 ]/i)) {
+                            return false;
+                        }
+                        break;
+                }
+            })
+            .off('keydown.shortcuts', '[with-shortcuts]')
+            .on('keydown.shortcuts', '[with-shortcuts]', function(_e) {
+                input = this;
+                let consumed = false;
+                refreshOptions = false;
+                switch(_e.which) {
+                    /*
+                    case 32:
+                        if(_e.ctrlKey && !isVisible()) {
+                            backtrackAfterApplying = false;
+                            show(this);
+                            return false;
+                        }
+                        else {
+                            if(!isVisible()) return;
+                            _e.preventDefault();
+                            apply();
+                            consumed = true;
+                        }
+                        break;
+                     */
+                    case 27:
+                        if(!isVisible()) return;
+                        consumed = !discard();
+                        if(consumed) markEventAsConsumed(_e);
+                        break;
+                    case 38:
+                        if(!isVisible()) return;
+                        if(index > 0) index--;
+                        highlightOption();
+                        consumed = true;
+                        break;
+                    case 40:
+                        if(!isVisible()) return;
+                        if(index < options.length - 1) index++;
+                        highlightOption();
+                        consumed = true;
+                        break;
+                    case 13:
+                        if(!isVisible()) return;
+                        apply(true);
+                        consumed = true;
+                        break;
+                    case 8:
+                        if(!isVisible()) break;
+                        if(strPart.length === 1) {
+                            strPart = '';
+                            discard();
+                        }
+                        else {
+                            strPart = strPart.substr(0, strPart.length - 1);
+                            refreshOptions = true;
+                        }
+                        consumed = false;
+                        break;
+                    default:
+                        if(!isVisible()) break;
+                        let char = String.fromCharCode(_e.which);
+                        if(!_e.ctrlKey && !_e.metaKey && char.match(/[a-z0-9 ]/i)) {
+                            strPart += char;
+                            refreshOptions = true;
+                            consumed = false;
+                        }
+                        else {
+                            consumed = true;
+                        }
+                        break;
+                }
+                if(consumed) {
+                    _e.stopImmediatePropagation();
+                    _e.preventDefault();
+                    return false;
+                }
+            })
+            .off('keyup.shortcuts', '[with-shortcuts]')
+            .on('keyup.shortcuts', '[with-shortcuts]', function(_e) {
+                let input = this;
+                let options = window.userShortcuts, noteRTE = $(input).closest('[note-rte]');
+                if(noteRTE.length && noteRTE.is('[use-shortcuts]') && noteRTE.attr('use-shortcuts') && noteRTE.attr('use-shortcuts') !== 'user') {
+                    if(window[noteRTE.attr('use-shortcuts') + 'Shortcuts']) {
+                        options = window[noteRTE.attr('use-shortcuts') + 'Shortcuts'];
+                    }
+                }
+                if(isVisible() && refreshOptions) {
+                    show(false, options);
+                }
+            })
+            .off('paste.shortcuts', '[with-shortcuts]')
+            .on('paste.shortcuts', '[with-shortcuts]', function(_e) {
+                if(isVisible()) return false;
+            });
+        $(document)
+            .off('mousedown.apply-shortcuts', '.stag-shortcuts>.sc')
+            .on('mousedown.apply-shortcuts', '.stag-shortcuts>.sc', function(_e) {
+                index = $(this).index();
+                apply();
+                return false;
+            });
+        $(document)
+            .off('mousedown.add-shortcuts', '.add-shortcut')
+            .on('mousedown.add-shortcuts', '.add-shortcut', function(_e) {
+                let hasFocus = $(document.activeElement).closest('.note-content, .rte-holder').length;
+                if(hasFocus) {
+                    selectedText = window.getSelection().toString();
+                    if(selectedText !== '') return;
+                }
+                return false;
+            })
+            .off('click.add-shortcuts', '.add-shortcut')
+            .on('click.add-shortcuts', '.add-shortcut', function(_e) {
+                // if(selectedText === '') return;
+                $('#selected-sc-text').val(selectedText);
+                $('#create-shortcut-form')
+                    .attr('data-editor-id', $(this).attr('data-editor-id'))
+                    .css({
+                        left: $(this).offset().left + 'px',
+                        top: ($(this).offset().top + $(this).outerHeight()) + 'px'
+                    })
+                    .show();
+                showMoeFormMask();
+                return false;
+            })
+            .off('submit.add-shortcut', '#create-shortcut-form')
+            .on('submit.add-shortcut', '#create-shortcut-form', function(_e) {
+                if(!input) input = $('.note-content [contenteditable][data-editor-id="' + $(this).attr('data-editor-id') + '"]').first();
+                if(!input) return false;
+                var label = $(this).find('[name="shortcut"]').val(),
+                    content = $(this).find('[name="text"]').val();
+                if(!this.checkValidity()) return false;
+                $.post('/api/proTextShortcut/create', $(this).serialize(), function(_data) {
+                    if(_data && _data.success && input) {
+                        window.userShortcuts.push({
+                            name: label,
+                            value: content
+                        });
+                        toastr.success('Shortcut saved');
+                        hideMoeFormMask();
+                        $('#create-shortcut-form').hide();
+                        $(input).focus();
+                    }
+                }, 'json');
+                return false;
+            })
+            .off('reset.add-shortcut', '#create-shortcut-form')
+            .on('reset.add-shortcut', '#create-shortcut-form', function(_e) {
+                if(!input) input = $('.note-content [contenteditable][data-editor-id="' + $(this).attr('data-editor-id') + '"]').first();
+                if(!input) return false;
+                hideMoeFormMask();
+                $('#create-shortcut-form').hide();
+                $(input).focus();
+            });
+
+    }
+    addMCInitializer('shortcut-suggest', init);
+})();
+
+

+ 22 - 0
js-dev/show-on-click.js

@@ -0,0 +1,22 @@
+(function() {
+    function init() {
+        $(document)
+            .off('click.show-on-click', '.show-on-click')
+            .on('click.show-on-click', '.show-on-click', function(_e) {
+                if($(this).text() === $(this).attr('data-value')) {
+                    $(this).text('Click to view');
+                }
+                else {
+                    $(this).text($(this).attr('data-value'));
+
+                    // fire pro event
+                    $.post('/api/proEvent/create', {
+                        proUid: $(this).attr('data-pro-uid'),
+                        event: $(this).attr('data-event'),
+                    }, () => {}, 'json');
+                }
+                return false;
+            });
+    }
+    addMCInitializer('show-on-click', init);
+})();

+ 49 - 0
js-dev/stag-collapsible-card.js

@@ -0,0 +1,49 @@
+(function() {
+    function init() {
+        $('.card[stag-collapsible-card]:not([stag-collapsible-card-initialized])').each(function() {
+            let header = $(this).find('>.card-header').first();
+            if(header.length) {
+                let html = header.html();
+                let newHeader = $('<div class="d-flex align-items-center"></div>');
+                newHeader.append(html);
+                let collapseTrigger = $('<a href="#" class="stag-collapse-trigger ml-auto" />');
+                collapseTrigger.append('<i class="fa fa-chevron-up if-not-collapsed"/>');
+                collapseTrigger.append('<i class="fa fa-chevron-down if-collapsed"/>');
+                newHeader.append(collapseTrigger);
+                header
+                    .empty()
+                    .append(newHeader);
+            }
+            if(!!$(this).attr('stag-collapsible-card')) {
+                let state = localStorage['collapseState_' + $(this).attr('stag-collapsible-card')];
+                if(state === 'collapsed') {
+                    $(this).attr('collapsed', 1);
+                }
+                else if(state === 'not-collapsed') {
+                    $(this).removeAttr('collapsed');
+                }
+            }
+            $(this).attr('stag-collapsible-card-initialized', 1);
+        });
+
+        $(document)
+            .off('click.stag-collapse-toggle', '.card[stag-collapsible-card][stag-collapsible-card-initialized] .stag-collapse-trigger')
+            .on('click.stag-collapse-toggle', '.card[stag-collapsible-card][stag-collapsible-card-initialized] .stag-collapse-trigger', function() {
+                let card = $(this).closest('.card');
+                if(card.is('[collapsed]')) {
+                    card.removeAttr('collapsed');
+                    if(!!card.attr('stag-collapsible-card')) {
+                        localStorage['collapseState_' + card.attr('stag-collapsible-card')] = 'not-collapsed';
+                    }
+                }
+                else {
+                    card.attr('collapsed', 1);
+                    if(!!card.attr('stag-collapsible-card')) {
+                        localStorage['collapseState_' + card.attr('stag-collapsible-card')] = 'collapsed';
+                    }
+                }
+                return false;
+            });
+    }
+    addMCInitializer('stag-collapsible-card', init);
+}).call(window);

+ 472 - 0
js-dev/stag-popup.js

@@ -0,0 +1,472 @@
+window.stagPopupsQueue = [];
+function showStagPopup(_key, _noAutoFocus) {
+    /*$('html, body').addClass('no-scroll');
+    $(window.top.document.body).find('#stag_mcp_lhs').addClass('no-scroll');*/
+    let stagPopup = $('[stag-popup-key="' + _key + '"]');
+    if(stagPopup.is('.show')) return false;
+    else {
+        let zIndex = $('.stag-popup.show[stag-popup-key]').last().css('z-index');
+        if(zIndex) zIndex++; else zIndex = 100;
+        stagPopup.css('z-index', zIndex);
+    }
+    stagPopup.addClass('show');
+    stagPopup.find('[moe][initialized]').removeAttr('initialized');
+    initMoes();
+    initFileInputs();
+    if(!_noAutoFocus) {
+        window.setTimeout(function() {
+            stagPopup.find('input[type="text"]:not([readonly]):visible,select:visible').first().focus();
+        }, 150);
+    }
+    stagPopupsQueue.push(stagPopup);
+    return false;
+}
+function submitStagPopup(_form) {
+    if(!_form[0].checkValidity()) {
+        _form[0].reportValidity();
+        return false;
+    }
+    showMask();
+    $.post(_form.attr('action'), _form.serialize(), function(_data) {
+        stagPopupsQueue = [];
+        fastReload();
+    });
+    return false;
+}
+function closeStagPopup(_noEvent = false) {
+    hideMoeFormMask();
+    if(!stagPopupsQueue.length) return false;
+    let popup = stagPopupsQueue[stagPopupsQueue.length - 1];
+    let closeAll = !!popup.attr('close-all-with-self');
+    popup.removeClass('show');
+    stagPopupsQueue.splice(stagPopupsQueue.length - 1, 1);
+    if(closeAll) {
+        while(stagPopupsQueue.length) {
+            closeStagPopup(true);
+        }
+    }
+    else {
+        if(popup.is('[update-parent]') && !_noEvent) {
+            let hook = popup.attr('update-parent');
+            if(!!$.trim(hook) && $.trim(hook) !== 'true') {
+                let hooks = hook.split(',');
+                for (let i = 0; i < hooks.length; i++) {
+                    hooks[i] = $.trim(hooks[i]);
+                    if(hasMCHook(hooks[i])) {
+                        runMCHook(hooks[i]);
+                    }
+                }
+            }
+            else {
+                if(stagPopupsQueue.length) {
+                    refreshDynamicStagPopup();
+                }
+                else {
+                    fastReload(popup.is('[update-target]') ? popup.attr('update-target') : '');
+                    return false;
+                }
+            }
+        }
+    }
+
+    // remove from the DOM
+    if(popup.is('.dynamic-popup')) popup.remove();
+
+    // if all closed
+    if(!stagPopupsQueue.length) {
+        $('html, body').removeClass('no-scroll');
+        $(window.top.document.body).find('#stag_mcp_lhs').removeClass('no-scroll');
+        if(!_noEvent) {
+            $('body').trigger('stag-popup-closed');
+        }
+    }
+    return false;
+}
+function convertContentLinksForInPopupNavigation(popup) {
+    popup.find('.stag-popup-content-inner').find('a').each(function() {
+        let a = $(this);
+        if(!(!a.attr('href') ||
+            a.is('[open-in-stag-popup]') ||
+            a.is('[native]') ||
+            a.attr('href') === '#' ||
+            a[0].onclick)) {
+            a.attr('replace-in-stag-popup', 1);
+        }
+    });
+}
+function openDynamicStagPopup(_url, initer, title, updateParent, style = '', replace = false, updateTarget = null) {
+    let url = _url;
+    if(url.indexOf('popupmode') === -1) {
+        url += (url.indexOf('?') !== -1 ? '&' : '?') + 'popupmode=1';
+    }
+    // close out any open inline visit-segment
+    $('.note-section.visit-segment.edit').removeClass('edit');
+    showMask();
+    window.noMc = true;
+    $.get(url, (_data) => {
+
+        let popup = null;
+        if(replace) {
+            if(!stagPopupsQueue.length) {
+                console.error('No stag-popup currently visible!');
+                return false;
+            }
+            popup = stagPopupsQueue[stagPopupsQueue.length - 1];
+            if(!popup.is('.dynamic-popup')) {
+                console.error('Topmost stag-popup is not dynamic!');
+                return false;
+            }
+            popup.attr('stag-popup-key', url);
+        }
+        else {
+            popup = $('.dynamic-popup[stag-popup-key="' + url + '"]');
+            if(!popup.length) {
+                $('main.stag-content').append(
+                    '<div class="stag-popup ' + (style ? style : 'stag-popup-lg') + ' dynamic-popup draggable resizable mcp-theme-1" stag-popup-key="' + url + '">' +
+                    '<div class="stag-popup-content p-0">' +
+                    '<h3 class="stag-popup-title mb-0 mt-3 mx-3 pb-0 border-bottom-0"><span></span>' +
+                    '<a href="#" class="ml-auto text-secondary" onclick="return closeStagPopup()"><i class="fa fa-times-circle"></i></a>\n' +
+                    '</h3>' +
+                    '<div class="stag-popup-content-inner"></div>' +
+                    '</div>' +
+                    '</div>'
+                );
+                popup = $('.dynamic-popup[stag-popup-key="' + url + '"]');
+            }
+        }
+
+        popup.attr('mc-initer', initer);
+        popup.find('.stag-popup-title>span').html(title);
+        popup.find('.stag-popup-content-inner').html(_data);
+
+        convertContentLinksForInPopupNavigation(popup);
+
+        if(!replace) {
+            if(updateParent) {
+                popup.attr('update-parent', updateParent);
+            }
+            else {
+                popup.removeAttr('update-parent');
+            }
+            showStagPopup(url, true);
+
+            if(updateTarget) {
+                popup.attr('update-target', updateTarget);
+            }
+        }
+
+        if(initer) runMCInitializer(initer);
+        runMCInitializer('pro-suggest'); // not the place for this! Move to better place.
+        initMoes();
+        hideMask();
+        initFileInputs();
+    }).fail(() => {
+        toastr.error('Unable to open ' + _url);
+        hideMask();
+    });
+}
+function isDynamicStagPopupPresent() {
+    if(!stagPopupsQueue.length) return false;
+    let popup = stagPopupsQueue[stagPopupsQueue.length - 1];
+    if(popup.is('.dynamic-popup')) return true;
+    return false;
+}
+function refreshDynamicStagPopup(_url = false, _target = null) {
+    if(!stagPopupsQueue.length) return false;
+    let popup = stagPopupsQueue[stagPopupsQueue.length - 1];
+    if(popup.is('.dynamic-popup')) {
+        showMask();
+        window.noMc = true;
+        if(_url) {
+            popup.attr('stag-popup-key', _url);
+        }
+        let url = popup.attr('stag-popup-key'),
+            initer = popup.attr('mc-initer');
+        $.get(url, (_data) => {
+            if(_target) {
+                _data = '<div>' + _data + '</div>';
+                _target = _target.split(',').map(_x => $.trim(_x));
+                for (let i = 0; i < _target.length; i++) {
+                    let t = _target[i];
+                    let targetElement = $(t).first();
+                    if(targetElement.length) {
+                        let sourceElement = $(_data).find(t).first();
+                        if (sourceElement && sourceElement.length) {
+                            targetElement.html(sourceElement.html());
+                            initFastLoad(targetElement);
+                            console.log('Replaced ' + t);
+                        }
+                        else {
+                            console.warn(t + ' not found in returned content');
+                        }
+                    }
+                    else {
+                        console.warn(t + ' not found in existing content');
+                    }
+                }
+            }
+            else {
+                popup.find('.stag-popup-content-inner').html(_data);
+            }
+            convertContentLinksForInPopupNavigation(popup);
+            if(initer) runMCInitializer(initer);
+            runMCInitializer('pro-suggest');
+            initMoes();
+            hideMask();
+            initFileInputs();
+        });
+    }
+    return false;
+}
+function hasResponseError(_data) {
+    let msg = 'Unknown error!';
+    if (_data) {
+        if (_data.success) return false;
+        else if (_data.message) msg = _data.message;
+    }
+    toastr.error(msg);
+    return true;
+}
+(function() {
+    window.initStagPopupEvents = function () {
+        $(document)
+            .off('mousedown.stag-popup-discard', '.stag-popup')
+            .on('mousedown.stag-popup-discard', '.stag-popup', function(_e) {
+                if($(_e.target).is('.stag-popup') && !isEventConsumed(_e)) {
+                    closeStagPopup();
+                    return false;
+                }
+            });
+        // catch ESC and discard any visible popups
+        $(document)
+            .off('keydown.stag-popup-escape')
+            .on('keydown.stag-popup-escape', function (e) {
+                if(e.which === 27) {
+                    if(!isEventConsumed(e)) {
+                        if(stagPopupsQueue.length) {
+                            if($('.stag-popup.show [moe] [url]:not([show]):visible').length || $('.stag-popup.show [visit-moe] [url]:not([show]):visible').length) {
+                                return;
+                            }
+                            closeStagPopup();
+                            markEventAsConsumed(e);
+                            return false;
+                        }
+                    }
+                }
+            });
+
+        $(document)
+            .off('click.open-in-stag-popup', '[open-in-stag-popup]')
+            .on('click.open-in-stag-popup', '[open-in-stag-popup]', function() {
+                let trig = $(this);
+                let updateParent = trig.is('[update-parent]');
+                if(updateParent) {
+                    if(!!$.trim(trig.attr('update-parent'))) {
+                        updateParent = trig.attr('update-parent');
+                    }
+                    else {
+                        updateParent = true;
+                    }
+                }
+                openDynamicStagPopup(
+                    trig.attr('href'),
+                    trig.attr('mc-initer'),
+                    trig.attr('title'),
+                    updateParent,
+                    trig.attr('popup-style'),
+                    false,
+                    trig.is('[update-target]') ? trig.attr('update-target') : null
+                );
+                return false;
+            });
+
+        $(document)
+            .off('click.replace-in-stag-popup', '[replace-in-stag-popup]')
+            .on('click.replace-in-stag-popup', '[replace-in-stag-popup]', function() {
+                let trig = $(this);
+                openDynamicStagPopup(
+                    trig.attr('href'),
+                    trig.attr('mc-initer'),
+                    trig.attr('title'),
+                    null, // will be inherited when replacing
+                    null, // will be inherited when replacing
+                    true,
+                    null
+                );
+                return false;
+            });
+
+        $(document)
+            .off('click.close-stag-popup', '.btn-close-stag-popup')
+            .on('click.close-stag-popup', '.btn-close-stag-popup', function() {
+                closeStagPopup();
+                return false;
+            });
+
+        // draggable
+        let dragging = false, dragX, dragY;
+        $(document)
+            .off('mousedown.start-drag', '.stag-popup.dynamic-popup.draggable .stag-popup-title')
+            .on('mousedown.start-drag', '.stag-popup.dynamic-popup.draggable .stag-popup-title', function(_e) {
+                if(_e.which !== 1) return;
+                if(dragging && dragging.length) {
+                    dragging = false;
+                }
+                dragging = $(this).closest('.stag-popup-content');
+                dragX = _e.screenX;
+                dragY = _e.screenY;
+            });
+        $(document)
+            .off('mousemove.drag')
+            .on('mousemove.drag', function(_e) {
+                if(dragging && dragging.length) {
+                    let targetX = dragging.position().left + (_e.screenX - dragX),
+                        targetY = dragging.position().top + (_e.screenY - dragY);
+                    if(targetX >= 0) dragX = _e.screenX;
+                    if(targetY >= 0) dragY = _e.screenY;
+                    if(targetX < 0) targetX = 0;
+                    if(targetY < 0) targetY = 0;
+                    dragging[0].style.left = targetX + 'px';
+                    dragging[0].style.top = targetY + 'px';
+                    dragging[0].style.transform = 'none';
+                    return false;
+                }
+            });
+
+        // resizable
+        let resizeHighlighting = false, resizeDirection = false, resizeAnchor = false, resizing = false, resizeGutter = 8, resizeX, resizeY;
+        $(document)
+            .off('mousemove.highlight-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content')
+            .on('mousemove.highlight-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content', function(_e) {
+                if(dragging && dragging.length) return;
+                if(resizing && resizing.length) return;
+                let mouseX = _e.pageX - $(this).offset().left,
+                    mouseY = _e.pageY - $(this).offset().top;
+                if((mouseX >= 0 && mouseX <= resizeGutter) || (mouseX >= $(this).outerWidth() - resizeGutter && mouseX <= $(this).outerWidth())) {
+                    $(this).addClass('resizing-x');
+                    resizeHighlighting = $(this);
+                    resizeDirection = 'x';
+                    resizeAnchor = (mouseX >= 0 && mouseX <= resizeGutter) ? 'left' : 'right';
+                }
+                else if((mouseY >= 0 && mouseY <= resizeGutter) || (mouseY >= $(this).outerHeight() - resizeGutter && mouseY <= $(this).outerHeight())) {
+                    $(this).addClass('resizing-y');
+                    resizeHighlighting = $(this);
+                    resizeDirection = 'y';
+                    resizeAnchor = (mouseY >= 0 && mouseY <= resizeGutter) ? 'top' : 'bottom';
+                }
+                else {
+                    $(this).removeClass('resizing-x');
+                    $(this).removeClass('resizing-y');
+                    resizeHighlighting = false;
+                }
+            });
+        $(document)
+            .off('mousedown.start-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content')
+            .on('mousedown.start-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content', function(_e) {
+                if(_e.which !== 1) return;
+                if(resizeHighlighting && resizeHighlighting.length) {
+                    if(resizing && resizing.length) {
+                        resizing.removeClass('resizing-x resizing-y');
+                        resizing = false;
+                    }
+                    resizing = $(this);
+                    resizeX = _e.screenX;
+                    resizeY = _e.screenY;
+                }
+            });
+        $(document)
+            .off('mousemove.resize')
+            .on('mousemove.resize', function(_e) {
+                if(resizing && resizing.length) {
+
+                    console.log(resizeDirection);
+                    console.log(resizeAnchor);
+
+                    // x
+                    if(resizeDirection === 'x') {
+
+                        let deltaX = _e.screenX - resizeX;
+
+                        // anchor: left => update left and width of the popup
+                        if(resizeAnchor === 'left') {
+                            resizing[0].style.left = resizing.position().left + deltaX + 'px';
+                            resizing[0].style.width = resizing.outerWidth() - deltaX + 'px';
+                            resizing[0].style.transform = 'none';
+                        }
+
+                        // anchor: right => update width of the popup
+                        else if(resizeAnchor === 'right') {
+                            resizing[0].style.left = resizing.position().left + 'px'
+                            resizing[0].style.width = resizing.outerWidth() + deltaX + 'px';
+                            resizing[0].style.transform = 'none';
+                        }
+                    }
+
+                    // x
+                    if(resizeDirection === 'y') {
+
+                        let deltaY = _e.screenY - resizeY;
+
+                        // anchor: top => update top and height of the popup
+                        if(resizeAnchor === 'top') {
+                            resizing[0].style.top = resizing.position().top + deltaY + 'px';
+                            resizing[0].style.height = resizing.outerHeight() - deltaY + 'px';
+                        }
+
+                        // anchor: bottom => update height of the popup
+                        else if(resizeAnchor === 'bottom') {
+                            resizing[0].style.height = resizing.outerHeight() + deltaY + 'px';
+                        }
+                    }
+
+                    resizeX = _e.screenX;
+                    resizeY = _e.screenY;
+                    return false;
+                }
+            });
+        $(document)
+            .off('mouseleave.stop-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content')
+            .on('mouseleave.stop-resize', '.stag-popup.dynamic-popup.resizable .stag-popup-content', function(_e) {
+                if(resizing && resizing.length) return;
+                if(resizeHighlighting && resizeHighlighting.length) {
+                    resizeHighlighting.removeClass('resizing-x resizing-y');
+                    resizeHighlighting = false;
+                    return false;
+                }
+            });
+
+        // common
+        $(document)
+            .off('mouseleave.stop-drag-resize')
+            .on('mouseleave.stop-drag-resize', function() {
+                if(dragging && dragging.length) {
+                    dragging = false;
+                }
+                if(resizeHighlighting && resizeHighlighting.length) {
+                    resizeHighlighting.removeClass('resizing-x resizing-y');
+                    resizeHighlighting = false;
+                }
+                if(resizing && resizing.length) {
+                    resizing.removeClass('resizing-x resizing-y');
+                    resizing = false;
+                }
+            });
+        $(document)
+            .off('mouseup.stop-drag-resize')
+            .on('mouseup.stop-drag-resize', function() {
+                if(dragging && dragging.length) {
+                    dragging = false;
+                }
+                if(resizeHighlighting && resizeHighlighting.length) {
+                    resizeHighlighting.removeClass('resizing-x resizing-y');
+                    resizeHighlighting = false;
+                }
+                if(resizing && resizing.length) {
+                    resizing.removeClass('resizing-x resizing-y');
+                    resizing = false;
+                }
+            });
+
+    }
+    addMCInitializer('stag-popups', window.initStagPopupEvents);
+})();

+ 307 - 0
js-dev/stag-suggest.js

@@ -0,0 +1,307 @@
+(function () {
+    window.initStagSuggest = function () {
+
+        let suggestionsOuter = null;
+
+        const debounce = (func, wait) => {
+            let timeout;
+            return function executedFunction(...args) {
+                const later = () => {
+                    clearTimeout(timeout);
+                    func(...args);
+                };
+                clearTimeout(timeout);
+                timeout = setTimeout(later, wait);
+            };
+        };
+
+        var lastTerm = '';
+        var returnedFunction = debounce(function (elem) {
+            let term = elem.val();
+            let ep = $(elem).attr('stag-suggest-ep'), extra = $(elem).attr('stag-suggest-extra');
+            if(!!ep) { // remote lookup
+                if (!!term && term.length >= 2) {
+
+                    $.get(ep + '?term=' + $.trim(term) + (!!extra ? '&' + extra : ''), function (_data) {
+
+                        /*
+                        expected return format:
+                        {
+                            success: true,
+                            data: [
+                                {
+                                    x: ...,
+                                    y: ...,
+                                    text: ...    // "text" key is "mandatory"
+                                },
+                                {
+                                    x: ...,
+                                    y: ...,
+                                    text: ...    // "text" key is "mandatory"
+                                },
+                                ...
+                            ]
+                        }
+                         */
+
+                        suggestionsOuter.empty();
+                        if(!hasResponseError(_data) && _data.data && _data.data.length) {
+                            for (let i = 0; i < _data.data.length; i++) {
+                                let item = $('<a native href="#" class="d-block suggest-item stag-suggest text-nowrap"/>');
+                                for(let x in _data.data[i]) {
+                                    if(_data.data[i].hasOwnProperty(x) && x !== 'text') {
+                                        item.attr('data-' + x, _data.data[i][x]);
+                                    }
+                                }
+                                item.data('suggest-data', _data.data[i]);
+                                item.html(_data.data[i].text);
+                                if(_data.data[i].sub_text) {
+                                    item.append($('<span/>')
+                                        .addClass('ml-1 text-sm text-secondary')
+                                        .append(' (')
+                                        .append(_data.data[i].sub_text)
+                                        .append(')')
+                                    );
+                                }
+                                if(_data.data[i].text2) {
+                                    item.append($('<div/>')
+                                        .addClass('text-sm text-secondary')
+                                        .html(_data.data[i].text2)
+                                    );
+                                }
+                                if(_data.data[i].tooltip) {
+                                    item.attr('title', _data.data[i].tooltip);
+                                }
+                                if(i === 0) {
+                                    item.addClass('active');
+                                }
+                                suggestionsOuter.append(item);
+                            }
+                        }
+                        else {
+                            suggestionsOuter.html('<span class="d-block no-suggest-items">No matches!</span>');
+                        }
+
+                        suggestionsOuter.removeClass('d-none');
+                    }, 'json');
+                    lastTerm = term;
+                } else {
+                    suggestionsOuter.addClass('d-none');
+                }
+            }
+            else { // local lookup
+                let optionList = $(elem).next().next('.data-option-list');
+                if(optionList.length) {
+                    let matches = [];
+                    optionList.find('>div').each(function() {
+                        if(!term || $(this).text().toLowerCase().indexOf(term.toLowerCase()) !== -1) {
+                            matches.push($(this).text());
+                        }
+                    });
+                    suggestionsOuter.empty();
+                    if(matches.length) {
+                        for (let i = 0; i < matches.length; i++) {
+                            let item = $('<a native href="#" class="d-block suggest-item stag-suggest text-nowrap"/>');
+                            item.data('suggest-data', {});
+                            item.html(matches[i]);
+                            suggestionsOuter.append(item);
+                        }
+                    }
+                    else {
+                        suggestionsOuter.html('<span class="d-block no-suggest-items">No matches!</span>');
+                    }
+                    suggestionsOuter.removeClass('d-none');
+                }
+            }
+
+        }, 250);
+
+        function handleKeydown(elem, e) {
+            let term = $.trim(elem.val());
+            let activeItem = suggestionsOuter.find('.suggest-item.active');
+            switch (e.which) {
+                case 27:
+                    if(suggestionsOuter.is(':visible')) {
+                        suggestionsOuter.addClass('d-none');
+                        markEventAsConsumed(e);
+                        return false;
+                    }
+                    break;
+                case 38:
+                    if(suggestionsOuter.is(':visible')) {
+                        if (activeItem.prev().length) {
+                            activeItem.prev()
+                                .addClass('active')
+                                .siblings().removeClass('active');
+                            activeItem = suggestionsOuter.find('.suggest-item.active');
+                            if (activeItem.length) {
+                                if(activeItem[0].scrollIntoViewIfNeeded) {
+                                    activeItem[0].scrollIntoViewIfNeeded(false);
+                                }
+                                else {
+                                    activeItem[0].scrollIntoView({
+                                        behavior: "auto",
+                                        block: "start",
+                                        inline: "start"
+                                    });
+                                }
+                            }
+                        }
+                        return false;
+                    }
+                    break;
+                case 40:
+                    if(suggestionsOuter.is(':visible')) {
+                        if (activeItem.next().length) {
+                            activeItem.next()
+                                .addClass('active')
+                                .siblings().removeClass('active');
+                            activeItem = suggestionsOuter.find('.suggest-item.active');
+                            if (activeItem.length) {
+                                if(activeItem[0].scrollIntoViewIfNeeded) {
+                                    activeItem[0].scrollIntoViewIfNeeded(false);
+                                }
+                                else {
+                                    activeItem[0].scrollIntoView({
+                                        behavior: "auto",
+                                        block: "end",
+                                        inline: "end"
+                                    });
+                                }
+                            }
+                        }
+                        return false;
+                    }
+                    break;
+                case 13:
+                    if(suggestionsOuter.is(':visible')) {
+                        if (activeItem.length) {
+                            activeItem.first().trigger('mousedown');
+                        }
+                        return false;
+                    }
+                    break;
+                default:
+                    if (!!term) {
+                        suggestionsOuter
+                            .html('<span class="d-block no-suggest-items">Searching...</span>')
+                            .removeClass('d-none');
+                        returnedFunction(elem);
+                    } else {
+                        suggestionsOuter.addClass('d-none');
+                    }
+                    break;
+            }
+        }
+
+        function handleKeypress(elem, e) {
+            var term = $.trim(elem.val());
+            if (!!term || !$(elem).is('[stag-suggest-ep]')) {
+                suggestionsOuter
+                    .html('<span class="d-block no-suggest-items">Searching...</span>')
+                    .removeClass('d-none');
+                returnedFunction(elem);
+            } else {
+                suggestionsOuter.addClass('d-none');
+            }
+        }
+
+        $('[stag-suggest]:not([stag-suggest-initialized])').each(function () {
+            let elem = $(this);
+            elem.next('.stag-suggestions-container').remove();
+            $('<div class="stag-suggestions-container position-relative">' +
+                '<div class="suggestions-outer stag-suggestions position-absolute d-none"></div>' +
+                '</div>').insertAfter(elem);
+
+            elem
+                .off('focus.stag-suggest')
+                .on('focus.stag-suggest', function (e) {
+                    if(!$(this).is('[stag-suggest-ep]')) {
+                        suggestionsOuter = $(this).next('.stag-suggestions-container').find('>.suggestions-outer');
+                        return handleKeypress($(this), e);
+                    }
+                })
+                .off('keydown.stag-suggest')
+                .on('keydown.stag-suggest', function (e) {
+                    suggestionsOuter = $(this).next('.stag-suggestions-container').find('>.suggestions-outer');
+                    return handleKeydown($(this), e);
+                })
+                .off('paste.stag-suggest')
+                .on('paste.stag-suggest', function (e) {
+                    window.setTimeout(() => {
+                        suggestionsOuter = $(this).next('.stag-suggestions-container').find('>.suggestions-outer');
+                        return handleKeypress($(this), e);
+                    }, 100);
+                })
+                .off('keypress.stag-suggest')
+                .on('keypress.stag-suggest', function (e) {
+                    suggestionsOuter = $(this).next('.stag-suggestions-container').find('>.suggestions-outer');
+                    return handleKeypress($(this), e);
+                });
+
+            $(this).attr('stag-suggest-initialized', 1);
+        });
+
+        // on auto-suggest selection
+        $(document).off('mousedown.stag-suggest', '.suggest-item.stag-suggest');
+        $(document).on('mousedown.stag-suggest', '.suggest-item.stag-suggest', function () {
+
+            $('.suggestions-outer.stag-suggestions').addClass('d-none');
+
+            let data = $(this).data('suggest-data'),
+                label = $.trim($(this).text());
+
+            // set value
+            let input = $(this).closest('.position-relative').prev('[stag-suggest]');
+
+            // if input is [stag-suggest-text-only] - use only the text bit in label
+            if(input.is('[stag-suggest-text-only]')) {
+                label = data.text;
+            }
+
+            input.val(label);
+            input.data('suggest-data', data);
+
+            let scope = input.attr('stag-suggest-scope');
+            if(!scope) scope = 'form';
+            scope = $(scope);
+
+            for(let x in data) {
+                if(data.hasOwnProperty(x)) {
+                    input.attr('data-' + x, data[x]);
+
+                    // auto-populate if there's a field matching data-name="x" in the scope
+                    if(scope.find('[data-name="' + x + '"]').length) {
+                        scope.find('[data-name="' + x + '"]').val(data[x]).trigger('change');
+                    }
+
+                }
+            }
+            input.trigger('input');
+            input.trigger('change');
+
+            input.trigger('stag-suggest-selected', [input, data]);
+
+            return false;
+        });
+
+        // outside click
+        $(document)
+            .off('mousedown.stag-suggest-outer-click')
+            .on('mousedown.stag-suggest-outer-click', function (_e) {
+                let elem = $(_e.target);
+                // if mousedown is on the input whose stag-suggest is on display, ignore
+                if(elem.is('[stag-suggest]') && elem.next('.stag-suggestions-container').find('>.suggestions-outer').is(':visible')) {
+                    return false;
+                }
+                if(!elem.is('.stag-suggestions-container') && !elem.closest('.stag-suggestions-container').length) {
+                    if($('.stag-suggestions-container .suggestions-outer:not(.d-none)').length) {
+                        $('.stag-suggestions-container .suggestions-outer').addClass('d-none');
+                        return false;
+                    }
+                }
+            });
+
+    }
+    addMCInitializer('stag-suggest', window.initStagSuggest);
+})();

+ 66 - 0
js-dev/stag-table-filter.js

@@ -0,0 +1,66 @@
+(function () {
+    window.initStagTableFilters = function () {
+
+        const debounce = (func, wait) => {
+            let timeout;
+            return function executedFunction(...args) {
+                const later = () => {
+                    clearTimeout(timeout);
+                    func(...args);
+                };
+                clearTimeout(timeout);
+                timeout = setTimeout(later, wait);
+            };
+        };
+
+        var returnedFunction = debounce(function (_elem) {
+            let term = $.trim(_elem.val()).toLowerCase(),
+                columnIndex = _elem.closest('td, th').index(),
+                trs = _elem.closest('table').find('tbody').find('tr');
+            trs.removeClass('stag-filter-hide');
+            trs.find('.stag-filter-highlight').replaceWith(function() {
+                return $(this).text();
+            });
+            _elem.closest('td, th').siblings().find('input[stag-table-filter]').val('');
+            if(!!term) {
+                trs.each(function () {
+                    let td = $(this).find('td:eq(' + columnIndex + ')'),
+                        text = td.text();
+                    if (text.toLowerCase().indexOf(term) === -1) {
+                        $(this).addClass('stag-filter-hide');
+                    }
+                    /*else {
+                        let re = new RegExp('(' + term + ')', 'ig');
+                        text = text.replace(re, '<span class="stag-filter-highlight">$&</span>');
+                        td.html(text);
+                    }*/
+                });
+            }
+        }, 100);
+
+        function applyFilter(_elem) {
+            returnedFunction(_elem);
+        }
+
+        $(document)
+            .off('input.stag-table-filter').on('input.stag-table-filter', 'input[stag-table-filter]', function() { applyFilter($(this)); })
+            .off('change.stag-table-filter').on('change.stag-table-filter', 'input[stag-table-filter]', function() { applyFilter($(this)); })
+            .off('paste.stag-table-filter').on('paste.stag-table-filter', 'input[stag-table-filter]', function() { applyFilter($(this)); })
+
+        $(document)
+            .off('keyup.stag-table-filter')
+            .on('keyup.stag-table-filter', 'input[stag-table-filter]', function(_e) {
+                if(_e.which === 27) {
+                    if(!isEventConsumed(e)) {
+                        if ($(this).val() !== '') {
+                            $(this).val('');
+                            applyFilter($(this));
+                            markEventAsConsumed(_e);
+                            return false;
+                        }
+                    }
+                }
+            })
+    }
+    addMCInitializer('stag-table-filter', window.initStagTableFilters);
+})();

+ 77 - 0
js-dev/tsvToArray.js

@@ -0,0 +1,77 @@
+var tsvToArray = null;
+(function ($) {
+    tsvToArray = {
+        file: 'cells.txt',
+        text: null,
+        json: null,
+
+        initLoadText: function (text) {
+            this.text = text;
+            return this.generateJSON();
+        },        
+        numberOfTabs: function (text) {
+            var count = 0;
+            var index = 0;
+            while (text.charAt(index++) === "\t") {
+                count++;
+            }
+            return count;
+        },
+        generateJSON: function () {
+            var self = this;
+            var text = self.text;
+            var lines = text.split(/\r\n|\r|\n/);
+            self.generatedArray = [];
+            var previousTabPosition = 0;
+            var currentContent = null;
+            var previousContent = null;
+            $.each(lines, function (lineNumber, line) {
+                var line = this;
+                var content = line.replace(/\t/g, '');
+                var tabPosition = self.numberOfTabs(line);
+                currentContent = content.length ? content : currentContent;
+
+                if (!self.generatedArray[lineNumber]) {
+                    self.generatedArray[lineNumber] = [];
+                }
+
+                if (tabPosition > previousTabPosition) {
+                    self.generatedArray[lineNumber] = self.autoFillArray(self.generatedArray[lineNumber], lineNumber, previousTabPosition, tabPosition, previousContent, currentContent);
+                } else {
+                    self.generatedArray[lineNumber].push(content);
+                    previousTabPosition = tabPosition;
+                    previousContent = content;
+                }
+
+            });
+
+            return self.generatedArray;
+        },
+        autoFillArray: function (array, lineNumber, previousTabPosition, currentTabPosition, previousContent, currentContent) {
+            var self = this;
+            var currentElementArray = [currentContent];
+            var previousLineArray = self.generatedArray[lineNumber - 1];
+            var pluckedArray = previousLineArray.slice(0, currentTabPosition);
+            var newArray = pluckedArray.concat(currentElementArray);
+            return newArray;
+        },
+        convertArrayToTabContentString: function(array){
+            var newLines = [];
+            for(var i = 0; i < array.length; i++){
+                var lineArray = array[i];
+                var lineArrayString = lineArray.join('\t');
+                newLines.push(lineArrayString);
+            }
+            return newLines.join('\n');
+        },
+        getAutoFilledTabContent: function(text){
+            var array = this.initLoadText(text);
+            var string = this.convertArrayToTabContentString(array);
+            return string;
+        },
+        init: function () {
+            
+        }
+    };
+    tsvToArray.init();
+})(jQuery);

+ 1146 - 0
js-dev/yemi.js

@@ -0,0 +1,1146 @@
+if (typeof focusOn == 'undefined') {
+    var focusOn = 'globalSearch';
+}
+
+var ajaxGoing = false;
+
+var showMask = function (_text = '') {
+    $('body').css('opacity', 0.6);
+    $('#mask').show();
+    if(!!_text) {
+        $('<div class="mask-text-addition" />').text('Initializing note. Please wait...').appendTo('body');
+    }
+}
+
+var hideMask = function () {
+    $('body').css('opacity', 1);
+    $('#mask').hide();
+    $('.mask-text-addition').remove();
+}
+
+var showMoeFormMask = function (_additionalClass = false) {
+    if(_additionalClass) {
+        $('#moe-form-mask').addClass(_additionalClass);
+    }
+    $('#moe-form-mask').show();
+}
+
+var hideMoeFormMask = function () {
+    if($('body').is('.blocking-mode')) return false;
+    $('#moe-form-mask').hide().removeClass();
+    $('#create-shortcut-form').hide();
+}
+
+$(document).ready(function () {
+    hideMask();
+});
+
+$(document).ready(function () {
+    $("input[type=number]").keydown(function (e) {
+        // Allow: backspace, delete, tab, escape, enter and .
+        if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110, 190]) !== -1 ||
+            // Allow: Ctrl+A, Command+A
+            (e.keyCode == 65 && (e.ctrlKey === true || e.metaKey === true)) ||
+            // Allow: home, end, left, right, down, up
+            (e.keyCode >= 35 && e.keyCode <= 40)) {
+            // let it happen, don't do anything
+            return;
+        }
+        // Ensure that it is a number and stop the keypress
+        if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
+            e.preventDefault();
+        }
+    });
+});
+
+$(function () {
+    $('input[type=checkbox][forceCb]').on('click', function () {
+        var name = $(this).attr('forceCb');
+        var code = $(this).attr('code');
+        var form = $(this).closest('form');
+        var hiddenField = $(form).find('input[code=\'' + code + '\']');
+        var value = $(this).prop('checked') ? 'on' : 'off';
+        console.log('name', name, 'code', code, 'value', value);
+        $(hiddenField).val(value);
+    });
+});
+
+var doAjax = function (url, data, pre, post, onSuccess, onFailure, suppressErrorMessage, onHttpFailure, shouldHideMask, immediatelyHideMaskOnReply) {
+    console.log(data);
+    if (ajaxGoing) {
+        console.log('ajax stopped!');
+        //return; TODO: fix and re-enable return
+    }
+    ajaxGoing = true;
+    if (!shouldHideMask) {
+        showMask();
+    }
+    jQuery.ajax(url, {
+        dataType: 'json',
+        data: data,
+        type: 'POST',
+        beforeSend: function () {
+            if (pre) {
+                pre();
+            }
+        }
+    })
+        .done(function (response, b) {
+            console.log(response);
+            var success = response.success;
+            if (success) {
+                if (onSuccess) {
+                    onSuccess(response.data);
+                }
+            } else {
+                if (onFailure) {
+                    onFailure(response.message);
+                }
+                if (!suppressErrorMessage) {
+                    //toast the error message
+                    //alert(response.message);
+                    toastr.error(response.message); // , toastr.success("message") ... .warning(), .error()
+                }
+                hideMask();
+            }
+            if (immediatelyHideMaskOnReply) {
+                hideMask();
+            }
+            ajaxGoing = false;
+        })
+        .fail(function (jqXHR, textStatus) {
+            hideMask();
+            toastr.error('Unable to process');
+            if (onHttpFailure) {
+                onHttpFailure(textStatus);
+            }
+            ajaxGoing = false;
+        })
+        .always(function () {
+            if (post) {
+                post();
+            }
+            ajaxGoing = false;
+        });
+};
+
+var doAjaxFormData = function (url, data, pre, post, onSuccess, onFailure, suppressErrorMessage, onHttpFailure, shouldHideMask, immediatelyHideMaskOnReply) {
+    console.log(data);
+    if (ajaxGoing) {
+        console.log('ajax stopped!');
+        //return; TODO: fix and re-enable return
+    }
+    ajaxGoing = true;
+    if (!shouldHideMask) {
+        showMask();
+    }
+    jQuery.ajax(url, {
+        dataType: 'json',
+        data: data,
+        processData: false,
+        contentType: false,
+        type: 'POST',
+        beforeSend: function () {
+            if (pre) {
+                pre();
+            }
+        }
+    })
+        .done(function (response, b) {
+            console.log(response);
+            var success = response.success;
+            if (success) {
+                if (onSuccess) {
+                    onSuccess(response.data);
+                }
+            } else {
+                if (onFailure) {
+                    onFailure(response.message);
+                }
+                if (!suppressErrorMessage) {
+                    //toast the error message
+                    //alert(response.message);
+                    toastr.error(response.message); // , toastr.success("message") ... .warning(), .error()
+                }
+                hideMask();
+            }
+            if (immediatelyHideMaskOnReply) {
+                hideMask();
+            }
+            ajaxGoing = false;
+        })
+        .fail(function (jqXHR, textStatus) {
+            hideMask();
+            toastr.error('Unable to process');
+            if (onHttpFailure) {
+                onHttpFailure(textStatus);
+            }
+            ajaxGoing = false;
+        })
+        .always(function () {
+            if (post) {
+                post();
+            }
+            ajaxGoing = false;
+        });
+};
+
+var justLog = false; //THIS IS FOR TEST MODE, FORMS WILL NOT TRIGGER REFRESH/REDIR
+
+var pageReload = function (_target) {
+    setTimeout(function () {
+        hideMoeFormMask();
+        fastReload(_target);
+    }, 500);
+};
+
+if (typeof String.prototype.startsWith != 'function') {
+    // see below for better implementation!
+    String.prototype.startsWith = function (str) {
+        return this.indexOf(str) === 0;
+    };
+}
+
+$(function () {
+    $('[addressLine1]').each(function () {
+        var moe = $(this).closest('[moe]');
+        var a = {};
+        a.addressLine1 = $(this);
+        a.addressLine2 = $(moe).find('[addressLine2]');
+        a.addressCity = $(moe).find('[addressCity]');
+        a.addressState = $(moe).find('[addressState]');
+        a.addressPostcode = $(moe).find('[addressPostcode]');
+        var getAddress = function () {
+            var address = {};
+            for (var prop in a) {
+                var val = $(a[prop]).val();
+                address[prop] = val;
+            }
+            return address;
+        }
+        var getFormattedAddress = function (address) {
+            var x = '<p>';
+            x += address.addressLine1 + (address.addressLine2 ? ', ' + address.addressLine2 : '') + '<br/>' + address.addressCity + ', ' + address.addressState + ' ' + address.addressPostcode;
+            x += '</p>';
+            return x;
+        }
+        var suggestAddress = function () {
+            var address = getAddress();
+            //var doAjax = function (url, data, pre, post, onSuccess, onFailure, suppressErrorMessage, onHttpFailure, shouldHideMask)
+            var onSuccess = function (data) {
+                console.log('SUCCESS!!!', data);
+            }
+            var onFailure = function (message) {
+                if (message.startsWith('Invalid:: INVALID ADDRESS - SUGGESTED:')) {
+                    var suggestionText = message.substring(message.indexOf('{'));
+                    var suggestion = JSON.parse(suggestionText);
+                    console.log('SUGGESTION!!!', suggestion);
+                    $('#myModal').attr('title', 'Address suggestion');
+                    $('#myModal').html('<h3>Currently set address:</h3>' + getFormattedAddress(address) + '<h3>Suggestion:</h3>' + getFormattedAddress(suggestion));
+                    $('#myModal').dialog({
+                        height: 400,
+                        width: 500,
+                        modal: true,
+                        buttons: [{
+                            text: 'Use suggestion',
+                            click: function () {
+                                for (var prop in a) {
+                                    $(a[prop]).val(suggestion[prop]);
+                                }
+                                $(this).dialog('close');
+                            }
+                        },
+                            {
+                                text: 'Keep original',
+                                click: function () {
+                                    $(this).dialog('close');
+                                }
+                            }
+                        ]
+                    });
+                } else if (message.startsWith('Invalid:: INVALID ADDRESS')) {
+                    console.log('NO SUGGESTION!!!');
+                    $('#myModal').attr('title', 'No address found');
+                    $('#myModal').html('<h3>Currently set address:</h3>' + getFormattedAddress(address) + '<h3>No suggestion!</h3>');
+                    $('#myModal').dialog({
+                        height: 400,
+                        width: 500,
+                        modal: true,
+                        buttons: [{
+                            text: 'Erase address fields',
+                            click: function () {
+                                for (var prop in a) {
+                                    $(a[prop]).val('');
+                                }
+                                $(this).dialog('close');
+                            }
+                        },
+                            {
+                                text: 'Keep original',
+                                click: function () {
+                                    $(this).dialog('close');
+                                }
+                            }
+                        ]
+                    });
+                }
+            }
+            doAjax('/api/service/verifyAddress', address, null, null, onSuccess, onFailure, true, null, false, true);
+        }
+        var isAddressComplete = function () {
+            var address = getAddress();
+            return address.addressLine1 && ((address.addressCity && address.addressState) || address.addressPostcode) ? true : false;
+        }
+        for (var prop in a) {
+            var part = a[prop];
+            $(part).on('change', function () {
+                console.log(getAddress());
+                var isComplete = isAddressComplete();
+                if (isComplete) {
+                    suggestAddress();
+                }
+            });
+            $(part).attr('autocomplete', 'off');
+        }
+    });
+});
+
+var initMoes = function() {
+    $('[moe]').each(function () {
+
+        if($(this).is('[initialized]')) { // skip to next moe
+            return true;
+        }
+
+        var moe = $(this);
+        moe.isProcessing = false;
+        var info = moe.find('[info]')[0]; // OPTIONAL
+        var start = moe.find('[start]')[0]; // OPTIONAL
+        var form = moe.find('[url]')[0]; // REQUIRED
+        var url = $(form).attr('url'); // REQUIRED
+        var redir = $(form).attr('redir'); // OPTIONAL
+        var target = $(form).attr('target'); // OPTIONAL
+        var noreload = $(form).is('[noreload]'); // OPTIONAL
+        var hook = $(form).attr('hook'); // OPTIONAL
+        var submit = moe.find('[submit]'); // REQUIRED
+        var cancel = moe.find('[cancel]')[0]; // OPTIONAL
+
+        let moeRefreshContainer = moe.closest('[moe-refresh-container][id]');
+        if(!target && moeRefreshContainer.length) {
+            target = '#' + moeRefreshContainer.attr('id');
+        }
+
+        // ajax load - OPTIONAL
+        var moeParent = $(form).closest('[moe-parent][url]');
+
+        if ($(this).attr('formOff') != null) {
+            $(form).find(':input').attr('disabled', true);
+            var formOn = $(this).find('[formOn]');
+            $(formOn).attr('disabled', false);
+            $(submit).hide();
+            $(formOn).click(function () {
+                $(form).find(':input').attr('disabled', false);
+                $(submit).show();
+                $(formOn).hide();
+                return false;
+            });
+        }
+
+        var realForm = form;
+
+        //init set display inline so toggle remembers inline state
+        var formToggle = false;
+        var infoToggle = false;
+
+        if (start) {
+            $(start).off('click.moe');
+            $(start).on('click.moe', function () {
+
+                // if any div based moes are visible, hide first
+                $('[moe]>div[url]:visible').hide();
+
+                $('.dropdown-menu[aria-labelledby="practice-management"]')
+                    .removeClass('show')
+                    .prev('.dropdown-toggle').attr('aria-expanded', 'false');
+                if ($(realForm).attr('show') == null) {
+                    if (!formToggle && $(realForm).attr('liner') != null) {
+                        $(realForm).css('display', 'inline');
+                        formToggle = true;
+                    } else {
+                        var isRealFormVisible = $(realForm).is(':visible');
+                        if(isRealFormVisible){
+                            hideMoeFormMask();
+                            $(realForm).toggle(100);
+                        }else{
+                            // keep data in moes, don't force reset
+                            // if($(realForm).is('form')) $(realForm)[0].reset();
+                            if(!$(realForm).closest('[moe]').is('[no-mask]')) {
+                                showMoeFormMask();
+                            }
+                            setTimeout(function() {
+                                $('[moe]>[url]:not([show]):visible').hide();
+                                $(realForm).toggle(100);
+                                initPrimaryForm($(realForm));
+                                setTimeout(function() {
+                                    let submitButton = $(realForm).find('[submit]');
+                                    if(submitButton.length) submitButton[0].scrollIntoView({behavior : "smooth", block: "nearest"});
+
+                                    // if any callback, trigger it
+                                    if($(realForm).is('[onshow]')) {
+                                        window[$(realForm).attr('onshow')].call($(realForm)[0]);
+                                    }
+
+                                }, 150);
+                            }, 100);
+                        }
+                    }
+                }
+                if (!infoToggle && info && $(info).attr('show') == null) {
+                    if ($(info).attr('liner') != null) {
+                        $(info).css('display', 'inline');
+                        infoToggle = true;
+                    } else {
+                        $(info).toggle(100);
+                    }
+                }
+                if ($(start).attr('show') == null) {
+                    $(start).toggle(100);
+                }
+                var focusOnStart = $(realForm).find('[focusOnStart]');
+                if (focusOnStart) {
+                    $(focusOnStart).focus();
+                }
+                return false;
+            });
+            $(start).attr('href', '#');
+        }
+        if (cancel) {
+            $(cancel).off('click.moe');
+            $(cancel).on('click.moe', function (e) {
+                e.preventDefault();
+                e.stopImmediatePropagation();
+                if ($(realForm).attr('show') == null) {
+                    $(realForm).hide(100);
+                }
+                if (info && $(info).attr('show') == null) {
+                    $(info).show(100);
+                }
+                if (start && $(start).attr('show') == null) {
+                    $(start).show(100);
+                }
+                hideMoeFormMask();
+            });
+        }
+        $(submit).off('click.moe');
+        $(submit).on('click.moe', function (e) {
+            e.preventDefault();
+            e.stopImmediatePropagation();
+            if (moe.isProcessing) {
+                return false;
+            }
+            if ($(submit).attr('confirm')) {
+                var question = $(submit).attr('confirm');
+                var cont = confirm(question);
+                if (cont) {} else {
+                    console.log("ABORTED!");
+                    return;
+                }
+            }
+
+            if($(form).is('form')) {
+
+                // trigger validation
+                if (!$(form)[0].checkValidity()) {
+                    $(form)[0].reportValidity();
+                    return;
+                }
+
+                // check and trigger onbeforesubmit
+                if($(form).is('[onbeforesubmit]')) {
+                    window[$(form).attr('onbeforesubmit')].call($(realForm)[0]);
+                }
+
+                // submit
+                moe.isProcessing = true;
+                var data = {};
+                var formData = $(form).serializeArray();
+                formData.forEach(function (field) {
+                    if (data[field.name]) {
+                        if (data[field.name] instanceof Array) {
+                            data[field.name].push(field.value);
+                        } else {
+                            var arr = [];
+                            arr.push(data[field.name]);
+                            arr.push(field.value);
+                            data[field.name] = arr;
+                        }
+                    } else {
+                        data[field.name] = field.value;
+                    }
+                });
+                console.log(data);
+                //var doAjax = function (url, data, pre, post, onSuccess, onFailure, suppressErrorMessage, onHttpFailure, shouldHideMask, immediatelyHideMaskOnReply)
+
+                // override with FormData if the form has any files
+                let useFormData = false;
+                if($(form).find('input[type="file"]').length) {
+                    let formData = new FormData();
+                    for(let x in data) {
+                        if(data.hasOwnProperty(x)) {
+                            formData.set(x, data[x]);
+                        }
+                    }
+                    $(form).find('input[type="file"]').each(function() {
+                        let fieldName = this.name;
+                        if(this.files && this.files.length) {
+                            formData.append(fieldName, this.files[0]);
+                        }
+                    });
+                    data = formData;
+                    useFormData = true;
+                }
+
+                if(!useFormData) {
+                    doAjax(url, data, null, function () {
+                        moe.isProcessing = false;
+                    }, function (data) {
+                        if(noreload) {
+                            $(cancel).trigger('click.moe');
+                            hideMoeFormMask();
+                            hideMask();
+                            toastr.success('Done');
+                            return;
+                        }
+                        if (justLog) { // this is to test!
+                            console.log('RETURNED', data);
+                        } else if (hook) {
+                            $(cancel).trigger('click.moe');
+                            hideMoeFormMask();
+                            hideMask();
+                            runMCHook(hook);
+                        } else if(typeof isDynamicStagPopupPresent !== 'undefined' && isDynamicStagPopupPresent()) {
+                            let targetUrl = false;
+                            if (redir) {
+                                if (redir.indexOf('[data]') > -1) {
+                                    targetUrl = redir.replace('[data]', data);
+                                }
+                            }
+                            refreshDynamicStagPopup(targetUrl, target);
+                        } else if (redir) {
+                            if (redir == "back") {
+                                window.top.history.back();
+                            } else {
+                                if (redir.indexOf('[data]') > -1) {
+                                    redir = redir.replace('[data]', data);
+                                }
+                                fastLoad(redir, true, false);
+                            }
+                        } else if (moeParent.length) {
+                            showMask();
+                            $.get(moeParent.attr('url'), function (_data) {
+                                moeParent.html(_data);
+                                hideMask();
+                                hideMoeFormMask();
+                                initMoes();
+                                initFastLoad(moeParent);
+                                initAutoRxAndICDComplete();
+                            });
+                        } else {
+                            pageReload(target);
+                        }
+                    }, function (errorMessage) {
+
+                    }, false);
+                }
+                else {
+                    doAjaxFormData(url, data, null, function () {
+                        moe.isProcessing = false;
+                    }, function (data) {
+                        if(noreload) {
+                            $(cancel).trigger('click.moe');
+                            hideMoeFormMask();
+                            hideMask();
+                            toastr.success('Done');
+                            return;
+                        }
+                        if (justLog) { // this is to test!
+                            console.log('RETURNED', data);
+                        } else if (hook) {
+                            $(cancel).trigger('click.moe');
+                            hideMoeFormMask();
+                            hideMask();
+                            runMCHook(hook);
+                        } else if(typeof isDynamicStagPopupPresent !== 'undefined' && isDynamicStagPopupPresent()) {
+                            let targetUrl = false;
+                            if (redir) {
+                                if (redir.indexOf('[data]') > -1) {
+                                    targetUrl = redir.replace('[data]', data);
+                                }
+                            }
+                            refreshDynamicStagPopup(targetUrl);
+                        } else if (redir) {
+                            if (redir == "back") {
+                                window.top.history.back();
+                            } else {
+                                if (redir.indexOf('[data]') > -1) {
+                                    redir = redir.replace('[data]', data);
+                                }
+                                fastLoad(redir, true, false);
+                            }
+                        } else if (moeParent.length) {
+                            showMask();
+                            $.get(moeParent.attr('url'), function (_data) {
+                                moeParent.html(_data);
+                                hideMask();
+                                hideMoeFormMask();
+                                initMoes();
+                                initFastLoad(moeParent);
+                                initAutoRxAndICDComplete();
+                            });
+                        } else {
+                            pageReload(target);
+                        }
+                    }, function (errorMessage) {
+
+                    }, false);
+                }
+
+            }
+        });
+
+        moe.attr('initialized', 1); // mark as initialized
+
+    });
+}
+
+jQuery(document).ready(function () {
+    var $ = jQuery;
+    $('body').mousedown(function(e){
+        if($(e.target).closest('[moe]').length ||
+            $(e.target).closest('#create-shortcut-form').length ||
+            $(e.target).is('#create-shortcut-form') ||
+            $(e.target).is('.stag-shortcuts .sc') ||
+            $(e.target).closest('.ui-datepicker').length) {
+            return;
+        }
+        $('[moe] [url]:not([show])').hide();
+        hideMoeFormMask();
+    });
+
+    initMoes();
+
+    $('table[info] input').each(function () {
+        $(this).prop('readonly', true);
+    });
+
+    //...for checkboxes readonly
+    $('input[type=checkbox][readonly],input[type=radio][readonly]').each(function () {
+        var x = this;
+        var isChecked = $(x).attr('checked');
+        $(x).change(function () {
+            $(x).attr('checked', isChecked);
+        });
+    });
+
+    $('[show-if]').each(function () { //TODO show-if="isOpen"    show-if="isTimeSpecific"    show-if="refillFrequency=MONTH"
+        var x = this;
+        var sel = $(x).attr('show-if');
+        var selParts = sel.split('=');
+        var selName = selParts[0];
+        var selValue = selParts[1];
+        var useOpposite = selName[0] == '!';
+        if (useOpposite) {
+            selName = selName.slice(1);
+        }
+        var form = $(x).closest('form');
+        var conditionFields = $(form).find('[name=' + selName + ']');
+
+        function hideX() {
+            $(x).hide();
+        }
+
+        function showX() {
+            $(x).show();
+        }
+        var go = function () {
+            if (selValue) {
+                var value = $(conditionFields).val();
+                if (value == selValue) {
+                    if (useOpposite) {
+                        hideX()
+                    } else {
+                        showX()
+                    }
+                } else {
+                    if (useOpposite) {
+                        showX()
+                    } else {
+                        hideX()
+                    }
+                }
+            } else {
+                var isChecked = $(conditionFields).prop('checked');
+                if (isChecked) {
+                    if (useOpposite) {
+                        hideX()
+                    } else {
+                        showX()
+                    }
+                } else {
+                    if (useOpposite) {
+                        showX()
+                    } else {
+                        hideX()
+                    }
+                }
+            }
+        };
+        go();
+        $(conditionFields).change(function () {
+            go();
+        });
+    });
+
+});
+
+//now goTo is a plugin...
+(function ($) {
+    $.fn.goTo = function (x) {
+        $('html, body').animate({
+            scrollTop: ($(this).offset().top - x) + 'px'
+        }, 1);
+        return this; // for chaining...
+    };
+})(jQuery);
+
+$(document).ready(function () {
+    $(".expander").on("click", function () {
+        var expandedID = $(this).attr("id");
+        if ($(this).text() == "-") {
+            $(this).text("+");
+        } else {
+            $(this).text("-");
+        }
+        $("." + expandedID).toggle();
+        return false;
+    });
+});
+
+
+
+$(document).ready(function () {
+    $('[showMap]').each(function () {
+        var mapper = $(this);
+        var adr = mapper.attr('showMap');
+        mapper.on('click', function () {
+            showAddr(adr);
+            return false;
+        });
+    });
+});
+
+
+$(document).ready(function () {
+    $('[dateRanger]').each(function () {
+        var dr = $(this);
+        var rangeTypeSelect = dr.find('select')[0];
+        var date1Input = dr.find('[date1]')[0];
+        var date2Input = dr.find('[date2]')[0];
+        var d1Val = '';
+        var d2Val = '';
+        var d1 = function (enable) {
+            if (enable) {
+                var hasVal = $(date1Input).val();
+                if (!hasVal) {
+                    $(date1Input).val(d1Val);
+                }
+                $(date1Input).show();
+            } else {
+                d1Val = $(date1Input).val();
+                $(date1Input).val('');
+                $(date1Input).hide();
+            }
+        };
+        var d2 = function (enable) {
+            if (enable) {
+                var hasVal = $(date2Input).val();
+                if (!hasVal) {
+                    $(date2Input).val(d2Val);
+                }
+                $(date2Input).show();
+            } else {
+                d2Val = $(date2Input).val();
+                $(date2Input).val('');
+                $(date2Input).hide();
+            }
+        };
+        var adjustFields = function () {
+            var rangeType = $(rangeTypeSelect).val();
+            if (rangeType == 'all') {
+                d1();
+                d2();
+            } else if (rangeType == 'on-or-before') {
+                d1(true);
+                d2();
+            } else if (rangeType == 'on-or-after') {
+                d1(true);
+                d2();
+            } else if (rangeType == 'between') {
+                d1(true);
+                d2(true);
+            } else if (rangeType == 'on') {
+                d1(true);
+                d2();
+            } else if (rangeType == 'not-on') {
+                d1(true);
+                d2();
+            } else if (rangeType == 'not-in-between') {
+                d1(true);
+                d2(true);
+            }
+        };
+        adjustFields();
+        $(rangeTypeSelect).change(function () {
+            adjustFields();
+        });
+    });
+    $('[numRanger]').each(function () {
+        var nr = $(this);
+        var rangeTypeSelect = nr.find('select')[0];
+        var num1Input = nr.find('[num1]')[0];
+        var num2Input = nr.find('[num2]')[0];
+        var n1 = function (enable) {
+            if (enable) {
+                $(num1Input).show();
+            } else {
+                $(num1Input).hide();
+            }
+        };
+        var n2 = function (enable) {
+            if (enable) {
+                $(num2Input).show();
+            } else {
+                $(num2Input).hide();
+            }
+        };
+        var adjustFields = function () {
+            var rangeType = $(rangeTypeSelect).val();
+            if (rangeType == 'all') {
+                n1();
+                n2();
+            } else if (rangeType == 'less-than') {
+                n1(true);
+                n2();
+            } else if (rangeType == 'greater-than') {
+                n1(true);
+                n2();
+            } else if (rangeType == 'equal-to') {
+                n1(true);
+                n2();
+            } else if (rangeType == 'between') {
+                n1(true);
+                n2(true);
+            } else if (rangeType == 'not-equal-to') {
+                n1(true);
+                n2();
+            } else if (rangeType == 'not-in-between') {
+                n1(true);
+                n2(true);
+            }
+        };
+        adjustFields('all');
+        $(rangeTypeSelect).change(function () {
+            adjustFields();
+        });
+    });
+});
+$(document).ready(function () {
+    $('[minzero]').on('change', function () {
+        var val = $(this).val();
+        val = parseFloat(val);
+        if (val < 0) {
+            alert('This number cannot be less than zero.');
+            $(this).val('');
+            $(this).focus();
+        }
+    });
+});
+
+var showAddr = function (adr) {
+    window.open('http://192.241.155.210/geo.php?adr=' + adr, new Date().getTime(), "height=400,width=520");
+};
+
+$(document).ready(function () {
+    var globalSearch = function () {
+        var substring = $('#globalSearch').val();
+        console.log("SUBSTRING", substring);
+        if (substring.length > 2) {
+            $("#results").show();
+            $("#results").load("/global-search?substring=" + encodeURIComponent(substring));
+        } else {
+            $("#results").hide();
+        }
+    };
+    $("#globalSearch").on('keyup', function (evnt) {
+        globalSearch();
+    });
+    $("#globalSearch").on('focus', function (evnt) {
+        globalSearch();
+    });
+    $("#globalSearch").on('blur', function (evt) {
+        setTimeout(function () {
+            $("#results").hide();
+        }, 500);
+    });
+});
+
+$('a[aller]').attr('href', '#');
+var selectAll = true;
+$('a[aller]').click(function () {
+    $('input[type=checkbox][aller]').each(function () {
+        if (!$(this).is(':disabled')) {
+            $(this).prop('checked', selectAll);
+        }
+    });
+    selectAll = !selectAll;
+    return false;
+});
+
+$(function () {
+    $('.showOnLoad').show();
+});
+
+$(function () {
+    var i = 0;
+    function pulsate() {
+        $(".urgentIndicator").
+        animate({
+            opacity: 0.2
+        }, 200, 'linear').
+        animate({
+            opacity: 1
+        }, 200, 'linear', pulsate);
+    }
+    pulsate();
+});
+
+$(function () {
+    $('[remote-searcher]').each(function () {
+
+        var me = this;
+
+        $(me).hide();
+
+        var selections = [];
+
+        var isMulti = typeof $(me).attr('multiple') == 'string';
+
+        $(me).find('[rid]').each(function () {
+            selections.push({
+                id: $(this).attr('rid'),
+                display: $(this).attr('display')
+            });
+        });
+
+        if (!isMulti && selections[0]) {
+            selections = [selections[0]];
+        }
+
+        $(me).html('');
+
+        var url = $(me).attr('remote-searcher');
+        var charMin = $(me).attr('char-min');
+        var name = $(me).attr('name');
+
+        $(me).append('<select multiple style="display:none;" name="' + name + '"></select><span choices></span><input type="text" style="border:none;margin:5px;width:100%;outline:none;display:none;"/></span>');
+        $(me).append('<div style="margin-top:2px;background:white;border:1px lightgray solid;display:none;width:99%;position:absolute;z-index:999"></div>');
+
+        var choices = $(me).find('span[choices]');
+
+        var selectField = $(me).find('select');
+        var textField = $(me).find('input[type=text]');
+        var resultDiv = $(me).find('div');
+
+        var setResultMask = function () {
+            $(resultDiv).html('<div style="background-image: url(/icons/vanillaspin.gif); background-repeat: no-repeat; width:100%; height:60px;background-position: center;"></div>');
+        }
+
+        var fillSelected = function (selected) {
+            $(selectField).html('');
+            $(choices).html('');
+            selected.forEach(function (choice, index) {
+                if (isMulti || (!isMulti && index == 0)) {
+                    $(selectField).append('<option selected value="' + choice.id + '">' + choice.display + '</option>');
+                    $(choices).append('<button style="margin:2px;" rid="' + choice.id + '" index="' + index + '">' + choice.display + ' x</button>');
+                }
+            });
+            $(choices).find('button').on('click', function () {
+                var btn = this;
+                var rid = $(btn).attr('rid');
+                var index = $(btn).attr('index');
+                selections.splice(index, 1);
+                fillSelected(selected);
+                return false;
+            });
+        }
+
+        fillSelected(selections);
+
+        var setValue = function (val, display) {
+            if (!isMulti) {
+                selections = [];
+            }
+            // get rid of earliers
+            for (var i = 0; i < selections.length; i++) {
+                var sel = selections[i];
+                if (sel.id == parseInt(val)) {
+                    selections.splice(i, 1);
+                }
+            }
+            selections.push({
+                id: val,
+                display: display
+            });
+            fillSelected(selections);
+            $(textField).val('');
+            $(textField).hide();
+        }
+
+        var getMatches = function () {
+            var substring = $(textField).val();
+            if (charMin > substring.length) {
+                return;
+            }
+            setResultMask();
+            $(resultDiv).show();
+            //url, data, pre, post, onSuccess, onFailure, suppressErrorMessage, onHttpFailure, shouldHideMask
+            doAjax(url, {
+                substring: substring
+            }, null, null, function (matches) {
+                $(resultDiv).find('[rid]').each(function () {
+                    $(this).off()
+                });
+                $(resultDiv).html('');
+                matches.forEach(function (match) {
+                    if (typeof match == 'string') {
+                        match = {
+                            id: match,
+                            display: match
+                        }
+                    }
+                    if (typeof match == 'object' && !match.id) {
+                        match.id = match.display;
+                    }
+                    $(resultDiv).append('<a href="#" class="searcher-result" display="' + match.display + '" rid="' + match.id + '">' + match.display + '</a>');
+                });
+                $(resultDiv).find('[rid]').each(function () {
+                    var result = this;
+                    $(result).mousedown('click', function () {
+                        var val = $(result).attr('rid');
+                        var display = $(result).attr('display');
+                        setValue(val, display);
+                        //$(textField).hide();
+                        return false;
+                    });
+                });
+            }, null, true, null, true);
+        };
+
+        $(textField).on('keyup', function () {
+            getMatches();
+        });
+
+        $(textField).on('blur', function () {
+            $(textField).val('');
+            $(textField).hide();
+            if ($(resultDiv).is(':visible')) {
+                $(resultDiv).hide();
+            };
+        });
+
+        $(textField).on('focus', function () {
+            getMatches();
+        });
+
+        $(me).on('click', function () {
+            $(textField).show();
+            $(textField).focus();
+        });
+
+        $(me).show();
+    });
+});
+
+$(document).ready(function () {
+    // setInterval(function () {
+    //     doAjax('/api/session/test', null, null, null, null, function () {
+    //         window.location.reload(true);
+    //     }, true, null, true);
+    // }, 10000);
+});
+
+$(document).ready(function () {
+    if (focusOn) {
+        $('#' + focusOn).focus();
+    }
+});
+
+$(function () {
+    $('[setMaskOnClick]').click(function () {
+        showMask();
+    });
+});
+
+$(function () {
+    $('input[type=file][ajaxload]').each(function () {
+        var me = this;
+        var name = $(me).attr('ajaxload');
+        $(me).wrap('<span class="ajaxload"></span>');
+        $(me).closest('span').append('<input type="hidden" name="' + name + '"/>');
+        $(me).on('change', function (event) {
+            console.log("file received.");
+            var fileField = me;
+            var files = event.target.files;
+            var data = new FormData();
+            $.each(files, function (key, value) {
+                data.append(key, value);
+            });
+            $.ajax({
+                url: '/api/systemFile/upload',
+                type: 'POST',
+                data: data,
+                cache: false,
+                dataType: 'json',
+                processData: false, // Don't process the files
+                contentType: false, // Set content type to false as jQuery will tell the server its a query string request
+                success: function (data, textStatus, jqXHR) {
+                    var systemFileID = data.data;
+                    console.log("UPLOAD WORKED::", data);
+                    $(me).closest('span').find('input[type=hidden]').val(systemFileID);
+                },
+                error: function (jqXHR, textStatus, errorThrown) {
+                    console.log('ERRORS: ' + textStatus);
+                }
+            });
+        });
+    });
+});
+
+// catch ESC and discard any visible moes
+$(document).ready(function () {
+    $(document)
+        .off('keydown.moe-escape')
+        .on('keydown.moe-escape', function (e) {
+            if(e.which === 27) {
+                if(isEventConsumed(e)) return;
+                let visibleMoes = $('[moe] [url]:not([show]):visible');
+                if (visibleMoes.length) {
+                    hideMoeFormMask();
+                    visibleMoes.hide();
+                    window.moeClosedAt = (new Date()).getTime();
+                    markEventAsConsumed(e);
+                    return false;
+                }
+            }
+        });
+});

BIN
public/img/behavior-rx.png


BIN
public/img/behavior-rx/cravings.png


BIN
public/img/behavior-rx/food-log.png


BIN
public/img/behavior-rx/phone-tracker.png


BIN
public/img/behavior-rx/relaxation.png


BIN
public/img/behavior-rx/reward.png


BIN
public/img/behavior-rx/sleep.png


BIN
public/img/behavior-rx/social.png


BIN
public/img/behavior-rx/stress.png


BIN
public/img/behavior-rx/work.png


BIN
public/img/exercise-rx.png


BIN
public/img/exercise-rx/bike.png


BIN
public/img/exercise-rx/elliptical.png


BIN
public/img/exercise-rx/jog.png


BIN
public/img/exercise-rx/strength.png


BIN
public/img/exercise-rx/swim.png


BIN
public/img/exercise-rx/walk.png


BIN
public/img/node.png


BIN
public/img/nutrition-rx.png


BIN
public/img/nutrition-rx/hs.png


BIN
public/img/nutrition-rx/hsb.png


BIN
public/img/nutrition-rx/ig.png


BIN
public/img/nutrition-rx/us.png


BIN
public/img/nutrition-rx/vc.png


BIN
public/img/nutrition-rx/wi.png


BIN
public/img/p-phone.png


BIN
public/img/pdf.png


+ 14 - 0
public/js/.gitignore

@@ -0,0 +1,14 @@
+click-to-copy.js
+dq.js
+mc.js
+mc-init.js
+option-list.js
+pro-suggest.js
+shortcut.js
+show-on-click.js
+stag-collapsible-card.js
+stag-popup.js
+stag-suggest.js
+stag-table-filter.js
+tsvToArray.js
+yemi.js

+ 32 - 0
public/js/icd-autocomplete.js

@@ -0,0 +1,32 @@
+(function() {
+
+    function init() {
+        let self = this;
+        $('[icd-autocomplete-code]:not([ac-initialized])').each(function() {
+            let elem = this, dynID = 'icd-' + Math.ceil(Math.random() * 1000000),
+                codeElem = $(this), descElem = $(this).closest('form, tr').first().find('[icd-autocomplete-description]');
+            var targetDescElem = $(this).data('target');
+            if(targetDescElem){
+                descElem = $(this).closest('form').find(targetDescElem);
+            }
+            $(elem).attr('id', dynID);
+            new window.Def.Autocompleter.Search(dynID,
+                'https://clinicaltables.nlm.nih.gov/api/icd10cm/v3/search?sf=code,name&ef=name', {
+                    tableFormat: true,
+                    valueCols: [0],
+                    colHeaders: ['Code', 'Name'],
+                }
+            );
+            window.Def.Autocompleter.Event.observeListSelections(dynID, function() {
+                let autocomp = elem.autocomp, acData = autocomp.getSelectedItemData();
+                codeElem.val(acData[0].code).trigger('change');
+                descElem.val(acData[0].data['name']).attr('title', acData[0].data['name']).trigger('change');
+                return false;
+            });
+            $(elem).attr('ac-initialized', 1);
+        });
+    }
+
+    addMCInitializer('icd-autocomplete', init);
+
+}).call(window);

+ 177 - 0
public/js/pdfjs-2.12.313/LICENSE

@@ -0,0 +1,177 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS

+ 15955 - 0
public/js/pdfjs-2.12.313/build/pdf.js

@@ -0,0 +1,15955 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * Javascript code in this page
+ *
+ * Copyright 2021 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * Javascript code in this page
+ */
+
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("pdfjs-dist/build/pdf", [], factory);
+	else if(typeof exports === 'object')
+		exports["pdfjs-dist/build/pdf"] = factory();
+	else
+		root["pdfjs-dist/build/pdf"] = root.pdfjsLib = factory();
+})(this, function() {
+return /******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ([
+/* 0 */,
+/* 1 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.StatTimer = exports.RenderingCancelledException = exports.PixelsPerInch = exports.PageViewport = exports.PDFDateString = exports.LinkTarget = exports.DOMStandardFontDataFactory = exports.DOMSVGFactory = exports.DOMCanvasFactory = exports.DOMCMapReaderFactory = void 0;
+exports.addLinkAttributes = addLinkAttributes;
+exports.deprecated = deprecated;
+exports.getFilenameFromUrl = getFilenameFromUrl;
+exports.getPdfFilenameFromUrl = getPdfFilenameFromUrl;
+exports.getXfaPageViewport = getXfaPageViewport;
+exports.isDataScheme = isDataScheme;
+exports.isPdfFile = isPdfFile;
+exports.isValidFetchUrl = isValidFetchUrl;
+exports.loadScript = loadScript;
+
+var _util = __w_pdfjs_require__(2);
+
+var _base_factory = __w_pdfjs_require__(5);
+
+const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
+const SVG_NS = "http://www.w3.org/2000/svg";
+const PixelsPerInch = {
+  CSS: 96.0,
+  PDF: 72.0,
+
+  get PDF_TO_CSS_UNITS() {
+    return (0, _util.shadow)(this, "PDF_TO_CSS_UNITS", this.CSS / this.PDF);
+  }
+
+};
+exports.PixelsPerInch = PixelsPerInch;
+
+class DOMCanvasFactory extends _base_factory.BaseCanvasFactory {
+  constructor({
+    ownerDocument = globalThis.document
+  } = {}) {
+    super();
+    this._document = ownerDocument;
+  }
+
+  _createCanvas(width, height) {
+    const canvas = this._document.createElement("canvas");
+
+    canvas.width = width;
+    canvas.height = height;
+    return canvas;
+  }
+
+}
+
+exports.DOMCanvasFactory = DOMCanvasFactory;
+
+async function fetchData(url, asTypedArray = false) {
+  if (isValidFetchUrl(url, document.baseURI)) {
+    const response = await fetch(url);
+
+    if (!response.ok) {
+      throw new Error(response.statusText);
+    }
+
+    return asTypedArray ? new Uint8Array(await response.arrayBuffer()) : (0, _util.stringToBytes)(await response.text());
+  }
+
+  return new Promise((resolve, reject) => {
+    const request = new XMLHttpRequest();
+    request.open("GET", url, true);
+
+    if (asTypedArray) {
+      request.responseType = "arraybuffer";
+    }
+
+    request.onreadystatechange = () => {
+      if (request.readyState !== XMLHttpRequest.DONE) {
+        return;
+      }
+
+      if (request.status === 200 || request.status === 0) {
+        let data;
+
+        if (asTypedArray && request.response) {
+          data = new Uint8Array(request.response);
+        } else if (!asTypedArray && request.responseText) {
+          data = (0, _util.stringToBytes)(request.responseText);
+        }
+
+        if (data) {
+          resolve(data);
+          return;
+        }
+      }
+
+      reject(new Error(request.statusText));
+    };
+
+    request.send(null);
+  });
+}
+
+class DOMCMapReaderFactory extends _base_factory.BaseCMapReaderFactory {
+  _fetchData(url, compressionType) {
+    return fetchData(url, this.isCompressed).then(data => {
+      return {
+        cMapData: data,
+        compressionType
+      };
+    });
+  }
+
+}
+
+exports.DOMCMapReaderFactory = DOMCMapReaderFactory;
+
+class DOMStandardFontDataFactory extends _base_factory.BaseStandardFontDataFactory {
+  _fetchData(url) {
+    return fetchData(url, true);
+  }
+
+}
+
+exports.DOMStandardFontDataFactory = DOMStandardFontDataFactory;
+
+class DOMSVGFactory extends _base_factory.BaseSVGFactory {
+  _createSVG(type) {
+    return document.createElementNS(SVG_NS, type);
+  }
+
+}
+
+exports.DOMSVGFactory = DOMSVGFactory;
+
+class PageViewport {
+  constructor({
+    viewBox,
+    scale,
+    rotation,
+    offsetX = 0,
+    offsetY = 0,
+    dontFlip = false
+  }) {
+    this.viewBox = viewBox;
+    this.scale = scale;
+    this.rotation = rotation;
+    this.offsetX = offsetX;
+    this.offsetY = offsetY;
+    const centerX = (viewBox[2] + viewBox[0]) / 2;
+    const centerY = (viewBox[3] + viewBox[1]) / 2;
+    let rotateA, rotateB, rotateC, rotateD;
+    rotation %= 360;
+
+    if (rotation < 0) {
+      rotation += 360;
+    }
+
+    switch (rotation) {
+      case 180:
+        rotateA = -1;
+        rotateB = 0;
+        rotateC = 0;
+        rotateD = 1;
+        break;
+
+      case 90:
+        rotateA = 0;
+        rotateB = 1;
+        rotateC = 1;
+        rotateD = 0;
+        break;
+
+      case 270:
+        rotateA = 0;
+        rotateB = -1;
+        rotateC = -1;
+        rotateD = 0;
+        break;
+
+      case 0:
+        rotateA = 1;
+        rotateB = 0;
+        rotateC = 0;
+        rotateD = -1;
+        break;
+
+      default:
+        throw new Error("PageViewport: Invalid rotation, must be a multiple of 90 degrees.");
+    }
+
+    if (dontFlip) {
+      rotateC = -rotateC;
+      rotateD = -rotateD;
+    }
+
+    let offsetCanvasX, offsetCanvasY;
+    let width, height;
+
+    if (rotateA === 0) {
+      offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
+      offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
+      width = Math.abs(viewBox[3] - viewBox[1]) * scale;
+      height = Math.abs(viewBox[2] - viewBox[0]) * scale;
+    } else {
+      offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
+      offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
+      width = Math.abs(viewBox[2] - viewBox[0]) * scale;
+      height = Math.abs(viewBox[3] - viewBox[1]) * scale;
+    }
+
+    this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY];
+    this.width = width;
+    this.height = height;
+  }
+
+  clone({
+    scale = this.scale,
+    rotation = this.rotation,
+    offsetX = this.offsetX,
+    offsetY = this.offsetY,
+    dontFlip = false
+  } = {}) {
+    return new PageViewport({
+      viewBox: this.viewBox.slice(),
+      scale,
+      rotation,
+      offsetX,
+      offsetY,
+      dontFlip
+    });
+  }
+
+  convertToViewportPoint(x, y) {
+    return _util.Util.applyTransform([x, y], this.transform);
+  }
+
+  convertToViewportRectangle(rect) {
+    const topLeft = _util.Util.applyTransform([rect[0], rect[1]], this.transform);
+
+    const bottomRight = _util.Util.applyTransform([rect[2], rect[3]], this.transform);
+
+    return [topLeft[0], topLeft[1], bottomRight[0], bottomRight[1]];
+  }
+
+  convertToPdfPoint(x, y) {
+    return _util.Util.applyInverseTransform([x, y], this.transform);
+  }
+
+}
+
+exports.PageViewport = PageViewport;
+
+class RenderingCancelledException extends _util.BaseException {
+  constructor(msg, type) {
+    super(msg, "RenderingCancelledException");
+    this.type = type;
+  }
+
+}
+
+exports.RenderingCancelledException = RenderingCancelledException;
+const LinkTarget = {
+  NONE: 0,
+  SELF: 1,
+  BLANK: 2,
+  PARENT: 3,
+  TOP: 4
+};
+exports.LinkTarget = LinkTarget;
+
+function addLinkAttributes(link, {
+  url,
+  target,
+  rel,
+  enabled = true
+} = {}) {
+  (0, _util.assert)(url && typeof url === "string", 'addLinkAttributes: A valid "url" parameter must provided.');
+  const urlNullRemoved = (0, _util.removeNullCharacters)(url);
+
+  if (enabled) {
+    link.href = link.title = urlNullRemoved;
+  } else {
+    link.href = "";
+    link.title = `Disabled: ${urlNullRemoved}`;
+
+    link.onclick = () => {
+      return false;
+    };
+  }
+
+  let targetStr = "";
+
+  switch (target) {
+    case LinkTarget.NONE:
+      break;
+
+    case LinkTarget.SELF:
+      targetStr = "_self";
+      break;
+
+    case LinkTarget.BLANK:
+      targetStr = "_blank";
+      break;
+
+    case LinkTarget.PARENT:
+      targetStr = "_parent";
+      break;
+
+    case LinkTarget.TOP:
+      targetStr = "_top";
+      break;
+  }
+
+  link.target = targetStr;
+  link.rel = typeof rel === "string" ? rel : DEFAULT_LINK_REL;
+}
+
+function isDataScheme(url) {
+  const ii = url.length;
+  let i = 0;
+
+  while (i < ii && url[i].trim() === "") {
+    i++;
+  }
+
+  return url.substring(i, i + 5).toLowerCase() === "data:";
+}
+
+function isPdfFile(filename) {
+  return typeof filename === "string" && /\.pdf$/i.test(filename);
+}
+
+function getFilenameFromUrl(url) {
+  const anchor = url.indexOf("#");
+  const query = url.indexOf("?");
+  const end = Math.min(anchor > 0 ? anchor : url.length, query > 0 ? query : url.length);
+  return url.substring(url.lastIndexOf("/", end) + 1, end);
+}
+
+function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") {
+  if (typeof url !== "string") {
+    return defaultFilename;
+  }
+
+  if (isDataScheme(url)) {
+    (0, _util.warn)('getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.');
+    return defaultFilename;
+  }
+
+  const reURI = /^(?:(?:[^:]+:)?\/\/[^/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
+  const reFilename = /[^/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
+  const splitURI = reURI.exec(url);
+  let suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]);
+
+  if (suggestedFilename) {
+    suggestedFilename = suggestedFilename[0];
+
+    if (suggestedFilename.includes("%")) {
+      try {
+        suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0];
+      } catch (ex) {}
+    }
+  }
+
+  return suggestedFilename || defaultFilename;
+}
+
+class StatTimer {
+  constructor() {
+    this.started = Object.create(null);
+    this.times = [];
+  }
+
+  time(name) {
+    if (name in this.started) {
+      (0, _util.warn)(`Timer is already running for ${name}`);
+    }
+
+    this.started[name] = Date.now();
+  }
+
+  timeEnd(name) {
+    if (!(name in this.started)) {
+      (0, _util.warn)(`Timer has not been started for ${name}`);
+    }
+
+    this.times.push({
+      name,
+      start: this.started[name],
+      end: Date.now()
+    });
+    delete this.started[name];
+  }
+
+  toString() {
+    const outBuf = [];
+    let longest = 0;
+
+    for (const time of this.times) {
+      const name = time.name;
+
+      if (name.length > longest) {
+        longest = name.length;
+      }
+    }
+
+    for (const time of this.times) {
+      const duration = time.end - time.start;
+      outBuf.push(`${time.name.padEnd(longest)} ${duration}ms\n`);
+    }
+
+    return outBuf.join("");
+  }
+
+}
+
+exports.StatTimer = StatTimer;
+
+function isValidFetchUrl(url, baseUrl) {
+  try {
+    const {
+      protocol
+    } = baseUrl ? new URL(url, baseUrl) : new URL(url);
+    return protocol === "http:" || protocol === "https:";
+  } catch (ex) {
+    return false;
+  }
+}
+
+function loadScript(src, removeScriptElement = false) {
+  return new Promise((resolve, reject) => {
+    const script = document.createElement("script");
+    script.src = src;
+
+    script.onload = function (evt) {
+      if (removeScriptElement) {
+        script.remove();
+      }
+
+      resolve(evt);
+    };
+
+    script.onerror = function () {
+      reject(new Error(`Cannot load script at: ${script.src}`));
+    };
+
+    (document.head || document.documentElement).appendChild(script);
+  });
+}
+
+function deprecated(details) {
+  console.log("Deprecated API usage: " + details);
+}
+
+let pdfDateStringRegex;
+
+class PDFDateString {
+  static toDateObject(input) {
+    if (!input || !(0, _util.isString)(input)) {
+      return null;
+    }
+
+    if (!pdfDateStringRegex) {
+      pdfDateStringRegex = new RegExp("^D:" + "(\\d{4})" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "([Z|+|-])?" + "(\\d{2})?" + "'?" + "(\\d{2})?" + "'?");
+    }
+
+    const matches = pdfDateStringRegex.exec(input);
+
+    if (!matches) {
+      return null;
+    }
+
+    const year = parseInt(matches[1], 10);
+    let month = parseInt(matches[2], 10);
+    month = month >= 1 && month <= 12 ? month - 1 : 0;
+    let day = parseInt(matches[3], 10);
+    day = day >= 1 && day <= 31 ? day : 1;
+    let hour = parseInt(matches[4], 10);
+    hour = hour >= 0 && hour <= 23 ? hour : 0;
+    let minute = parseInt(matches[5], 10);
+    minute = minute >= 0 && minute <= 59 ? minute : 0;
+    let second = parseInt(matches[6], 10);
+    second = second >= 0 && second <= 59 ? second : 0;
+    const universalTimeRelation = matches[7] || "Z";
+    let offsetHour = parseInt(matches[8], 10);
+    offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0;
+    let offsetMinute = parseInt(matches[9], 10) || 0;
+    offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0;
+
+    if (universalTimeRelation === "-") {
+      hour += offsetHour;
+      minute += offsetMinute;
+    } else if (universalTimeRelation === "+") {
+      hour -= offsetHour;
+      minute -= offsetMinute;
+    }
+
+    return new Date(Date.UTC(year, month, day, hour, minute, second));
+  }
+
+}
+
+exports.PDFDateString = PDFDateString;
+
+function getXfaPageViewport(xfaPage, {
+  scale = 1,
+  rotation = 0
+}) {
+  const {
+    width,
+    height
+  } = xfaPage.attributes.style;
+  const viewBox = [0, 0, parseInt(width), parseInt(height)];
+  return new PageViewport({
+    viewBox,
+    scale,
+    rotation
+  });
+}
+
+/***/ }),
+/* 2 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.VerbosityLevel = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.UNSUPPORTED_FEATURES = exports.TextRenderingMode = exports.StreamType = exports.RenderingIntentFlag = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.PageActionEventType = exports.OPS = exports.MissingPDFException = exports.IsLittleEndianCached = exports.IsEvalSupportedCached = exports.InvalidPDFException = exports.ImageKind = exports.IDENTITY_MATRIX = exports.FormatError = exports.FontType = exports.FONT_IDENTITY_MATRIX = exports.DocumentActionEventType = exports.CMapCompressionType = exports.BaseException = exports.AnnotationType = exports.AnnotationStateModelType = exports.AnnotationReviewState = exports.AnnotationReplyType = exports.AnnotationMode = exports.AnnotationMarkedState = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.AnnotationActionEventType = exports.AbortException = void 0;
+exports.arrayByteLength = arrayByteLength;
+exports.arraysToBytes = arraysToBytes;
+exports.assert = assert;
+exports.bytesToString = bytesToString;
+exports.createObjectURL = createObjectURL;
+exports.createPromiseCapability = createPromiseCapability;
+exports.createValidAbsoluteUrl = createValidAbsoluteUrl;
+exports.escapeString = escapeString;
+exports.getModificationDate = getModificationDate;
+exports.getVerbosityLevel = getVerbosityLevel;
+exports.info = info;
+exports.isArrayBuffer = isArrayBuffer;
+exports.isArrayEqual = isArrayEqual;
+exports.isAscii = isAscii;
+exports.isBool = isBool;
+exports.isNum = isNum;
+exports.isSameOrigin = isSameOrigin;
+exports.isString = isString;
+exports.objectFromMap = objectFromMap;
+exports.objectSize = objectSize;
+exports.removeNullCharacters = removeNullCharacters;
+exports.setVerbosityLevel = setVerbosityLevel;
+exports.shadow = shadow;
+exports.string32 = string32;
+exports.stringToBytes = stringToBytes;
+exports.stringToPDFString = stringToPDFString;
+exports.stringToUTF16BEString = stringToUTF16BEString;
+exports.stringToUTF8String = stringToUTF8String;
+exports.unreachable = unreachable;
+exports.utf8StringToString = utf8StringToString;
+exports.warn = warn;
+
+__w_pdfjs_require__(3);
+
+const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
+exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
+const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
+exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX;
+const RenderingIntentFlag = {
+  ANY: 0x01,
+  DISPLAY: 0x02,
+  PRINT: 0x04,
+  ANNOTATIONS_FORMS: 0x10,
+  ANNOTATIONS_STORAGE: 0x20,
+  ANNOTATIONS_DISABLE: 0x40,
+  OPLIST: 0x100
+};
+exports.RenderingIntentFlag = RenderingIntentFlag;
+const AnnotationMode = {
+  DISABLE: 0,
+  ENABLE: 1,
+  ENABLE_FORMS: 2,
+  ENABLE_STORAGE: 3
+};
+exports.AnnotationMode = AnnotationMode;
+const PermissionFlag = {
+  PRINT: 0x04,
+  MODIFY_CONTENTS: 0x08,
+  COPY: 0x10,
+  MODIFY_ANNOTATIONS: 0x20,
+  FILL_INTERACTIVE_FORMS: 0x100,
+  COPY_FOR_ACCESSIBILITY: 0x200,
+  ASSEMBLE: 0x400,
+  PRINT_HIGH_QUALITY: 0x800
+};
+exports.PermissionFlag = PermissionFlag;
+const TextRenderingMode = {
+  FILL: 0,
+  STROKE: 1,
+  FILL_STROKE: 2,
+  INVISIBLE: 3,
+  FILL_ADD_TO_PATH: 4,
+  STROKE_ADD_TO_PATH: 5,
+  FILL_STROKE_ADD_TO_PATH: 6,
+  ADD_TO_PATH: 7,
+  FILL_STROKE_MASK: 3,
+  ADD_TO_PATH_FLAG: 4
+};
+exports.TextRenderingMode = TextRenderingMode;
+const ImageKind = {
+  GRAYSCALE_1BPP: 1,
+  RGB_24BPP: 2,
+  RGBA_32BPP: 3
+};
+exports.ImageKind = ImageKind;
+const AnnotationType = {
+  TEXT: 1,
+  LINK: 2,
+  FREETEXT: 3,
+  LINE: 4,
+  SQUARE: 5,
+  CIRCLE: 6,
+  POLYGON: 7,
+  POLYLINE: 8,
+  HIGHLIGHT: 9,
+  UNDERLINE: 10,
+  SQUIGGLY: 11,
+  STRIKEOUT: 12,
+  STAMP: 13,
+  CARET: 14,
+  INK: 15,
+  POPUP: 16,
+  FILEATTACHMENT: 17,
+  SOUND: 18,
+  MOVIE: 19,
+  WIDGET: 20,
+  SCREEN: 21,
+  PRINTERMARK: 22,
+  TRAPNET: 23,
+  WATERMARK: 24,
+  THREED: 25,
+  REDACT: 26
+};
+exports.AnnotationType = AnnotationType;
+const AnnotationStateModelType = {
+  MARKED: "Marked",
+  REVIEW: "Review"
+};
+exports.AnnotationStateModelType = AnnotationStateModelType;
+const AnnotationMarkedState = {
+  MARKED: "Marked",
+  UNMARKED: "Unmarked"
+};
+exports.AnnotationMarkedState = AnnotationMarkedState;
+const AnnotationReviewState = {
+  ACCEPTED: "Accepted",
+  REJECTED: "Rejected",
+  CANCELLED: "Cancelled",
+  COMPLETED: "Completed",
+  NONE: "None"
+};
+exports.AnnotationReviewState = AnnotationReviewState;
+const AnnotationReplyType = {
+  GROUP: "Group",
+  REPLY: "R"
+};
+exports.AnnotationReplyType = AnnotationReplyType;
+const AnnotationFlag = {
+  INVISIBLE: 0x01,
+  HIDDEN: 0x02,
+  PRINT: 0x04,
+  NOZOOM: 0x08,
+  NOROTATE: 0x10,
+  NOVIEW: 0x20,
+  READONLY: 0x40,
+  LOCKED: 0x80,
+  TOGGLENOVIEW: 0x100,
+  LOCKEDCONTENTS: 0x200
+};
+exports.AnnotationFlag = AnnotationFlag;
+const AnnotationFieldFlag = {
+  READONLY: 0x0000001,
+  REQUIRED: 0x0000002,
+  NOEXPORT: 0x0000004,
+  MULTILINE: 0x0001000,
+  PASSWORD: 0x0002000,
+  NOTOGGLETOOFF: 0x0004000,
+  RADIO: 0x0008000,
+  PUSHBUTTON: 0x0010000,
+  COMBO: 0x0020000,
+  EDIT: 0x0040000,
+  SORT: 0x0080000,
+  FILESELECT: 0x0100000,
+  MULTISELECT: 0x0200000,
+  DONOTSPELLCHECK: 0x0400000,
+  DONOTSCROLL: 0x0800000,
+  COMB: 0x1000000,
+  RICHTEXT: 0x2000000,
+  RADIOSINUNISON: 0x2000000,
+  COMMITONSELCHANGE: 0x4000000
+};
+exports.AnnotationFieldFlag = AnnotationFieldFlag;
+const AnnotationBorderStyleType = {
+  SOLID: 1,
+  DASHED: 2,
+  BEVELED: 3,
+  INSET: 4,
+  UNDERLINE: 5
+};
+exports.AnnotationBorderStyleType = AnnotationBorderStyleType;
+const AnnotationActionEventType = {
+  E: "Mouse Enter",
+  X: "Mouse Exit",
+  D: "Mouse Down",
+  U: "Mouse Up",
+  Fo: "Focus",
+  Bl: "Blur",
+  PO: "PageOpen",
+  PC: "PageClose",
+  PV: "PageVisible",
+  PI: "PageInvisible",
+  K: "Keystroke",
+  F: "Format",
+  V: "Validate",
+  C: "Calculate"
+};
+exports.AnnotationActionEventType = AnnotationActionEventType;
+const DocumentActionEventType = {
+  WC: "WillClose",
+  WS: "WillSave",
+  DS: "DidSave",
+  WP: "WillPrint",
+  DP: "DidPrint"
+};
+exports.DocumentActionEventType = DocumentActionEventType;
+const PageActionEventType = {
+  O: "PageOpen",
+  C: "PageClose"
+};
+exports.PageActionEventType = PageActionEventType;
+const StreamType = {
+  UNKNOWN: "UNKNOWN",
+  FLATE: "FLATE",
+  LZW: "LZW",
+  DCT: "DCT",
+  JPX: "JPX",
+  JBIG: "JBIG",
+  A85: "A85",
+  AHX: "AHX",
+  CCF: "CCF",
+  RLX: "RLX"
+};
+exports.StreamType = StreamType;
+const FontType = {
+  UNKNOWN: "UNKNOWN",
+  TYPE1: "TYPE1",
+  TYPE1STANDARD: "TYPE1STANDARD",
+  TYPE1C: "TYPE1C",
+  CIDFONTTYPE0: "CIDFONTTYPE0",
+  CIDFONTTYPE0C: "CIDFONTTYPE0C",
+  TRUETYPE: "TRUETYPE",
+  CIDFONTTYPE2: "CIDFONTTYPE2",
+  TYPE3: "TYPE3",
+  OPENTYPE: "OPENTYPE",
+  TYPE0: "TYPE0",
+  MMTYPE1: "MMTYPE1"
+};
+exports.FontType = FontType;
+const VerbosityLevel = {
+  ERRORS: 0,
+  WARNINGS: 1,
+  INFOS: 5
+};
+exports.VerbosityLevel = VerbosityLevel;
+const CMapCompressionType = {
+  NONE: 0,
+  BINARY: 1,
+  STREAM: 2
+};
+exports.CMapCompressionType = CMapCompressionType;
+const OPS = {
+  dependency: 1,
+  setLineWidth: 2,
+  setLineCap: 3,
+  setLineJoin: 4,
+  setMiterLimit: 5,
+  setDash: 6,
+  setRenderingIntent: 7,
+  setFlatness: 8,
+  setGState: 9,
+  save: 10,
+  restore: 11,
+  transform: 12,
+  moveTo: 13,
+  lineTo: 14,
+  curveTo: 15,
+  curveTo2: 16,
+  curveTo3: 17,
+  closePath: 18,
+  rectangle: 19,
+  stroke: 20,
+  closeStroke: 21,
+  fill: 22,
+  eoFill: 23,
+  fillStroke: 24,
+  eoFillStroke: 25,
+  closeFillStroke: 26,
+  closeEOFillStroke: 27,
+  endPath: 28,
+  clip: 29,
+  eoClip: 30,
+  beginText: 31,
+  endText: 32,
+  setCharSpacing: 33,
+  setWordSpacing: 34,
+  setHScale: 35,
+  setLeading: 36,
+  setFont: 37,
+  setTextRenderingMode: 38,
+  setTextRise: 39,
+  moveText: 40,
+  setLeadingMoveText: 41,
+  setTextMatrix: 42,
+  nextLine: 43,
+  showText: 44,
+  showSpacedText: 45,
+  nextLineShowText: 46,
+  nextLineSetSpacingShowText: 47,
+  setCharWidth: 48,
+  setCharWidthAndBounds: 49,
+  setStrokeColorSpace: 50,
+  setFillColorSpace: 51,
+  setStrokeColor: 52,
+  setStrokeColorN: 53,
+  setFillColor: 54,
+  setFillColorN: 55,
+  setStrokeGray: 56,
+  setFillGray: 57,
+  setStrokeRGBColor: 58,
+  setFillRGBColor: 59,
+  setStrokeCMYKColor: 60,
+  setFillCMYKColor: 61,
+  shadingFill: 62,
+  beginInlineImage: 63,
+  beginImageData: 64,
+  endInlineImage: 65,
+  paintXObject: 66,
+  markPoint: 67,
+  markPointProps: 68,
+  beginMarkedContent: 69,
+  beginMarkedContentProps: 70,
+  endMarkedContent: 71,
+  beginCompat: 72,
+  endCompat: 73,
+  paintFormXObjectBegin: 74,
+  paintFormXObjectEnd: 75,
+  beginGroup: 76,
+  endGroup: 77,
+  beginAnnotations: 78,
+  endAnnotations: 79,
+  beginAnnotation: 80,
+  endAnnotation: 81,
+  paintJpegXObject: 82,
+  paintImageMaskXObject: 83,
+  paintImageMaskXObjectGroup: 84,
+  paintImageXObject: 85,
+  paintInlineImageXObject: 86,
+  paintInlineImageXObjectGroup: 87,
+  paintImageXObjectRepeat: 88,
+  paintImageMaskXObjectRepeat: 89,
+  paintSolidColorImageMask: 90,
+  constructPath: 91
+};
+exports.OPS = OPS;
+const UNSUPPORTED_FEATURES = {
+  unknown: "unknown",
+  forms: "forms",
+  javaScript: "javaScript",
+  signatures: "signatures",
+  smask: "smask",
+  shadingPattern: "shadingPattern",
+  font: "font",
+  errorTilingPattern: "errorTilingPattern",
+  errorExtGState: "errorExtGState",
+  errorXObject: "errorXObject",
+  errorFontLoadType3: "errorFontLoadType3",
+  errorFontState: "errorFontState",
+  errorFontMissing: "errorFontMissing",
+  errorFontTranslate: "errorFontTranslate",
+  errorColorSpace: "errorColorSpace",
+  errorOperatorList: "errorOperatorList",
+  errorFontToUnicode: "errorFontToUnicode",
+  errorFontLoadNative: "errorFontLoadNative",
+  errorFontBuildPath: "errorFontBuildPath",
+  errorFontGetPath: "errorFontGetPath",
+  errorMarkedContent: "errorMarkedContent",
+  errorContentSubStream: "errorContentSubStream"
+};
+exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
+const PasswordResponses = {
+  NEED_PASSWORD: 1,
+  INCORRECT_PASSWORD: 2
+};
+exports.PasswordResponses = PasswordResponses;
+let verbosity = VerbosityLevel.WARNINGS;
+
+function setVerbosityLevel(level) {
+  if (Number.isInteger(level)) {
+    verbosity = level;
+  }
+}
+
+function getVerbosityLevel() {
+  return verbosity;
+}
+
+function info(msg) {
+  if (verbosity >= VerbosityLevel.INFOS) {
+    console.log(`Info: ${msg}`);
+  }
+}
+
+function warn(msg) {
+  if (verbosity >= VerbosityLevel.WARNINGS) {
+    console.log(`Warning: ${msg}`);
+  }
+}
+
+function unreachable(msg) {
+  throw new Error(msg);
+}
+
+function assert(cond, msg) {
+  if (!cond) {
+    unreachable(msg);
+  }
+}
+
+function isSameOrigin(baseUrl, otherUrl) {
+  let base;
+
+  try {
+    base = new URL(baseUrl);
+
+    if (!base.origin || base.origin === "null") {
+      return false;
+    }
+  } catch (e) {
+    return false;
+  }
+
+  const other = new URL(otherUrl, base);
+  return base.origin === other.origin;
+}
+
+function _isValidProtocol(url) {
+  if (!url) {
+    return false;
+  }
+
+  switch (url.protocol) {
+    case "http:":
+    case "https:":
+    case "ftp:":
+    case "mailto:":
+    case "tel:":
+      return true;
+
+    default:
+      return false;
+  }
+}
+
+function createValidAbsoluteUrl(url, baseUrl = null, options = null) {
+  if (!url) {
+    return null;
+  }
+
+  try {
+    if (options && typeof url === "string") {
+      if (options.addDefaultProtocol && url.startsWith("www.")) {
+        const dots = url.match(/\./g);
+
+        if (dots && dots.length >= 2) {
+          url = `http://${url}`;
+        }
+      }
+
+      if (options.tryConvertEncoding) {
+        try {
+          url = stringToUTF8String(url);
+        } catch (ex) {}
+      }
+    }
+
+    const absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url);
+
+    if (_isValidProtocol(absoluteUrl)) {
+      return absoluteUrl;
+    }
+  } catch (ex) {}
+
+  return null;
+}
+
+function shadow(obj, prop, value) {
+  Object.defineProperty(obj, prop, {
+    value,
+    enumerable: true,
+    configurable: true,
+    writable: false
+  });
+  return value;
+}
+
+const BaseException = function BaseExceptionClosure() {
+  function BaseException(message, name) {
+    if (this.constructor === BaseException) {
+      unreachable("Cannot initialize BaseException.");
+    }
+
+    this.message = message;
+    this.name = name;
+  }
+
+  BaseException.prototype = new Error();
+  BaseException.constructor = BaseException;
+  return BaseException;
+}();
+
+exports.BaseException = BaseException;
+
+class PasswordException extends BaseException {
+  constructor(msg, code) {
+    super(msg, "PasswordException");
+    this.code = code;
+  }
+
+}
+
+exports.PasswordException = PasswordException;
+
+class UnknownErrorException extends BaseException {
+  constructor(msg, details) {
+    super(msg, "UnknownErrorException");
+    this.details = details;
+  }
+
+}
+
+exports.UnknownErrorException = UnknownErrorException;
+
+class InvalidPDFException extends BaseException {
+  constructor(msg) {
+    super(msg, "InvalidPDFException");
+  }
+
+}
+
+exports.InvalidPDFException = InvalidPDFException;
+
+class MissingPDFException extends BaseException {
+  constructor(msg) {
+    super(msg, "MissingPDFException");
+  }
+
+}
+
+exports.MissingPDFException = MissingPDFException;
+
+class UnexpectedResponseException extends BaseException {
+  constructor(msg, status) {
+    super(msg, "UnexpectedResponseException");
+    this.status = status;
+  }
+
+}
+
+exports.UnexpectedResponseException = UnexpectedResponseException;
+
+class FormatError extends BaseException {
+  constructor(msg) {
+    super(msg, "FormatError");
+  }
+
+}
+
+exports.FormatError = FormatError;
+
+class AbortException extends BaseException {
+  constructor(msg) {
+    super(msg, "AbortException");
+  }
+
+}
+
+exports.AbortException = AbortException;
+const NullCharactersRegExp = /\x00+/g;
+const InvisibleCharactersRegExp = /[\x01-\x1F]/g;
+
+function removeNullCharacters(str, replaceInvisible = false) {
+  if (typeof str !== "string") {
+    warn("The argument for removeNullCharacters must be a string.");
+    return str;
+  }
+
+  if (replaceInvisible) {
+    str = str.replace(InvisibleCharactersRegExp, " ");
+  }
+
+  return str.replace(NullCharactersRegExp, "");
+}
+
+function bytesToString(bytes) {
+  assert(bytes !== null && typeof bytes === "object" && bytes.length !== undefined, "Invalid argument for bytesToString");
+  const length = bytes.length;
+  const MAX_ARGUMENT_COUNT = 8192;
+
+  if (length < MAX_ARGUMENT_COUNT) {
+    return String.fromCharCode.apply(null, bytes);
+  }
+
+  const strBuf = [];
+
+  for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
+    const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
+    const chunk = bytes.subarray(i, chunkEnd);
+    strBuf.push(String.fromCharCode.apply(null, chunk));
+  }
+
+  return strBuf.join("");
+}
+
+function stringToBytes(str) {
+  assert(typeof str === "string", "Invalid argument for stringToBytes");
+  const length = str.length;
+  const bytes = new Uint8Array(length);
+
+  for (let i = 0; i < length; ++i) {
+    bytes[i] = str.charCodeAt(i) & 0xff;
+  }
+
+  return bytes;
+}
+
+function arrayByteLength(arr) {
+  if (arr.length !== undefined) {
+    return arr.length;
+  }
+
+  assert(arr.byteLength !== undefined, "arrayByteLength - invalid argument.");
+  return arr.byteLength;
+}
+
+function arraysToBytes(arr) {
+  const length = arr.length;
+
+  if (length === 1 && arr[0] instanceof Uint8Array) {
+    return arr[0];
+  }
+
+  let resultLength = 0;
+
+  for (let i = 0; i < length; i++) {
+    resultLength += arrayByteLength(arr[i]);
+  }
+
+  let pos = 0;
+  const data = new Uint8Array(resultLength);
+
+  for (let i = 0; i < length; i++) {
+    let item = arr[i];
+
+    if (!(item instanceof Uint8Array)) {
+      if (typeof item === "string") {
+        item = stringToBytes(item);
+      } else {
+        item = new Uint8Array(item);
+      }
+    }
+
+    const itemLength = item.byteLength;
+    data.set(item, pos);
+    pos += itemLength;
+  }
+
+  return data;
+}
+
+function string32(value) {
+  return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
+}
+
+function objectSize(obj) {
+  return Object.keys(obj).length;
+}
+
+function objectFromMap(map) {
+  const obj = Object.create(null);
+
+  for (const [key, value] of map) {
+    obj[key] = value;
+  }
+
+  return obj;
+}
+
+function isLittleEndian() {
+  const buffer8 = new Uint8Array(4);
+  buffer8[0] = 1;
+  const view32 = new Uint32Array(buffer8.buffer, 0, 1);
+  return view32[0] === 1;
+}
+
+const IsLittleEndianCached = {
+  get value() {
+    return shadow(this, "value", isLittleEndian());
+  }
+
+};
+exports.IsLittleEndianCached = IsLittleEndianCached;
+
+function isEvalSupported() {
+  try {
+    new Function("");
+    return true;
+  } catch (e) {
+    return false;
+  }
+}
+
+const IsEvalSupportedCached = {
+  get value() {
+    return shadow(this, "value", isEvalSupported());
+  }
+
+};
+exports.IsEvalSupportedCached = IsEvalSupportedCached;
+const hexNumbers = [...Array(256).keys()].map(n => n.toString(16).padStart(2, "0"));
+
+class Util {
+  static makeHexColor(r, g, b) {
+    return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`;
+  }
+
+  static transform(m1, m2) {
+    return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];
+  }
+
+  static applyTransform(p, m) {
+    const xt = p[0] * m[0] + p[1] * m[2] + m[4];
+    const yt = p[0] * m[1] + p[1] * m[3] + m[5];
+    return [xt, yt];
+  }
+
+  static applyInverseTransform(p, m) {
+    const d = m[0] * m[3] - m[1] * m[2];
+    const xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
+    const yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
+    return [xt, yt];
+  }
+
+  static getAxialAlignedBoundingBox(r, m) {
+    const p1 = Util.applyTransform(r, m);
+    const p2 = Util.applyTransform(r.slice(2, 4), m);
+    const p3 = Util.applyTransform([r[0], r[3]], m);
+    const p4 = Util.applyTransform([r[2], r[1]], m);
+    return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])];
+  }
+
+  static inverseTransform(m) {
+    const d = m[0] * m[3] - m[1] * m[2];
+    return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
+  }
+
+  static apply3dTransform(m, v) {
+    return [m[0] * v[0] + m[1] * v[1] + m[2] * v[2], m[3] * v[0] + m[4] * v[1] + m[5] * v[2], m[6] * v[0] + m[7] * v[1] + m[8] * v[2]];
+  }
+
+  static singularValueDecompose2dScale(m) {
+    const transpose = [m[0], m[2], m[1], m[3]];
+    const a = m[0] * transpose[0] + m[1] * transpose[2];
+    const b = m[0] * transpose[1] + m[1] * transpose[3];
+    const c = m[2] * transpose[0] + m[3] * transpose[2];
+    const d = m[2] * transpose[1] + m[3] * transpose[3];
+    const first = (a + d) / 2;
+    const second = Math.sqrt((a + d) ** 2 - 4 * (a * d - c * b)) / 2;
+    const sx = first + second || 1;
+    const sy = first - second || 1;
+    return [Math.sqrt(sx), Math.sqrt(sy)];
+  }
+
+  static normalizeRect(rect) {
+    const r = rect.slice(0);
+
+    if (rect[0] > rect[2]) {
+      r[0] = rect[2];
+      r[2] = rect[0];
+    }
+
+    if (rect[1] > rect[3]) {
+      r[1] = rect[3];
+      r[3] = rect[1];
+    }
+
+    return r;
+  }
+
+  static intersect(rect1, rect2) {
+    function compare(a, b) {
+      return a - b;
+    }
+
+    const orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare);
+    const orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare);
+    const result = [];
+    rect1 = Util.normalizeRect(rect1);
+    rect2 = Util.normalizeRect(rect2);
+
+    if (orderedX[0] === rect1[0] && orderedX[1] === rect2[0] || orderedX[0] === rect2[0] && orderedX[1] === rect1[0]) {
+      result[0] = orderedX[1];
+      result[2] = orderedX[2];
+    } else {
+      return null;
+    }
+
+    if (orderedY[0] === rect1[1] && orderedY[1] === rect2[1] || orderedY[0] === rect2[1] && orderedY[1] === rect1[1]) {
+      result[1] = orderedY[1];
+      result[3] = orderedY[2];
+    } else {
+      return null;
+    }
+
+    return result;
+  }
+
+  static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3) {
+    const tvalues = [],
+          bounds = [[], []];
+    let a, b, c, t, t1, t2, b2ac, sqrtb2ac;
+
+    for (let i = 0; i < 2; ++i) {
+      if (i === 0) {
+        b = 6 * x0 - 12 * x1 + 6 * x2;
+        a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
+        c = 3 * x1 - 3 * x0;
+      } else {
+        b = 6 * y0 - 12 * y1 + 6 * y2;
+        a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
+        c = 3 * y1 - 3 * y0;
+      }
+
+      if (Math.abs(a) < 1e-12) {
+        if (Math.abs(b) < 1e-12) {
+          continue;
+        }
+
+        t = -c / b;
+
+        if (0 < t && t < 1) {
+          tvalues.push(t);
+        }
+
+        continue;
+      }
+
+      b2ac = b * b - 4 * c * a;
+      sqrtb2ac = Math.sqrt(b2ac);
+
+      if (b2ac < 0) {
+        continue;
+      }
+
+      t1 = (-b + sqrtb2ac) / (2 * a);
+
+      if (0 < t1 && t1 < 1) {
+        tvalues.push(t1);
+      }
+
+      t2 = (-b - sqrtb2ac) / (2 * a);
+
+      if (0 < t2 && t2 < 1) {
+        tvalues.push(t2);
+      }
+    }
+
+    let j = tvalues.length,
+        mt;
+    const jlen = j;
+
+    while (j--) {
+      t = tvalues[j];
+      mt = 1 - t;
+      bounds[0][j] = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3;
+      bounds[1][j] = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3;
+    }
+
+    bounds[0][jlen] = x0;
+    bounds[1][jlen] = y0;
+    bounds[0][jlen + 1] = x3;
+    bounds[1][jlen + 1] = y3;
+    bounds[0].length = bounds[1].length = jlen + 2;
+    return [Math.min(...bounds[0]), Math.min(...bounds[1]), Math.max(...bounds[0]), Math.max(...bounds[1])];
+  }
+
+}
+
+exports.Util = Util;
+const PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac];
+
+function stringToPDFString(str) {
+  const length = str.length,
+        strBuf = [];
+
+  if (str[0] === "\xFE" && str[1] === "\xFF") {
+    for (let i = 2; i < length; i += 2) {
+      strBuf.push(String.fromCharCode(str.charCodeAt(i) << 8 | str.charCodeAt(i + 1)));
+    }
+  } else if (str[0] === "\xFF" && str[1] === "\xFE") {
+    for (let i = 2; i < length; i += 2) {
+      strBuf.push(String.fromCharCode(str.charCodeAt(i + 1) << 8 | str.charCodeAt(i)));
+    }
+  } else {
+    for (let i = 0; i < length; ++i) {
+      const code = PDFStringTranslateTable[str.charCodeAt(i)];
+      strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
+    }
+  }
+
+  return strBuf.join("");
+}
+
+function escapeString(str) {
+  return str.replace(/([()\\\n\r])/g, match => {
+    if (match === "\n") {
+      return "\\n";
+    } else if (match === "\r") {
+      return "\\r";
+    }
+
+    return `\\${match}`;
+  });
+}
+
+function isAscii(str) {
+  return /^[\x00-\x7F]*$/.test(str);
+}
+
+function stringToUTF16BEString(str) {
+  const buf = ["\xFE\xFF"];
+
+  for (let i = 0, ii = str.length; i < ii; i++) {
+    const char = str.charCodeAt(i);
+    buf.push(String.fromCharCode(char >> 8 & 0xff), String.fromCharCode(char & 0xff));
+  }
+
+  return buf.join("");
+}
+
+function stringToUTF8String(str) {
+  return decodeURIComponent(escape(str));
+}
+
+function utf8StringToString(str) {
+  return unescape(encodeURIComponent(str));
+}
+
+function isBool(v) {
+  return typeof v === "boolean";
+}
+
+function isNum(v) {
+  return typeof v === "number";
+}
+
+function isString(v) {
+  return typeof v === "string";
+}
+
+function isArrayBuffer(v) {
+  return typeof v === "object" && v !== null && v.byteLength !== undefined;
+}
+
+function isArrayEqual(arr1, arr2) {
+  if (arr1.length !== arr2.length) {
+    return false;
+  }
+
+  for (let i = 0, ii = arr1.length; i < ii; i++) {
+    if (arr1[i] !== arr2[i]) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+function getModificationDate(date = new Date()) {
+  const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, "0"), date.getUTCDate().toString().padStart(2, "0"), date.getUTCHours().toString().padStart(2, "0"), date.getUTCMinutes().toString().padStart(2, "0"), date.getUTCSeconds().toString().padStart(2, "0")];
+  return buffer.join("");
+}
+
+function createPromiseCapability() {
+  const capability = Object.create(null);
+  let isSettled = false;
+  Object.defineProperty(capability, "settled", {
+    get() {
+      return isSettled;
+    }
+
+  });
+  capability.promise = new Promise(function (resolve, reject) {
+    capability.resolve = function (data) {
+      isSettled = true;
+      resolve(data);
+    };
+
+    capability.reject = function (reason) {
+      isSettled = true;
+      reject(reason);
+    };
+  });
+  return capability;
+}
+
+function createObjectURL(data, contentType = "", forceDataSchema = false) {
+  if (URL.createObjectURL && typeof Blob !== "undefined" && !forceDataSchema) {
+    return URL.createObjectURL(new Blob([data], {
+      type: contentType
+    }));
+  }
+
+  const digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+  let buffer = `data:${contentType};base64,`;
+
+  for (let i = 0, ii = data.length; i < ii; i += 3) {
+    const b1 = data[i] & 0xff;
+    const b2 = data[i + 1] & 0xff;
+    const b3 = data[i + 2] & 0xff;
+    const d1 = b1 >> 2,
+          d2 = (b1 & 3) << 4 | b2 >> 4;
+    const d3 = i + 1 < ii ? (b2 & 0xf) << 2 | b3 >> 6 : 64;
+    const d4 = i + 2 < ii ? b3 & 0x3f : 64;
+    buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
+  }
+
+  return buffer;
+}
+
+/***/ }),
+/* 3 */
+/***/ ((__unused_webpack_module, __unused_webpack_exports, __w_pdfjs_require__) => {
+
+
+
+var _is_node = __w_pdfjs_require__(4);
+
+;
+
+/***/ }),
+/* 4 */
+/***/ ((__unused_webpack_module, exports) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.isNodeJS = void 0;
+const isNodeJS = typeof process === "object" && process + "" === "[object process]" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== "browser");
+exports.isNodeJS = isNodeJS;
+
+/***/ }),
+/* 5 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.BaseStandardFontDataFactory = exports.BaseSVGFactory = exports.BaseCanvasFactory = exports.BaseCMapReaderFactory = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+class BaseCanvasFactory {
+  constructor() {
+    if (this.constructor === BaseCanvasFactory) {
+      (0, _util.unreachable)("Cannot initialize BaseCanvasFactory.");
+    }
+  }
+
+  create(width, height) {
+    if (width <= 0 || height <= 0) {
+      throw new Error("Invalid canvas size");
+    }
+
+    const canvas = this._createCanvas(width, height);
+
+    return {
+      canvas,
+      context: canvas.getContext("2d")
+    };
+  }
+
+  reset(canvasAndContext, width, height) {
+    if (!canvasAndContext.canvas) {
+      throw new Error("Canvas is not specified");
+    }
+
+    if (width <= 0 || height <= 0) {
+      throw new Error("Invalid canvas size");
+    }
+
+    canvasAndContext.canvas.width = width;
+    canvasAndContext.canvas.height = height;
+  }
+
+  destroy(canvasAndContext) {
+    if (!canvasAndContext.canvas) {
+      throw new Error("Canvas is not specified");
+    }
+
+    canvasAndContext.canvas.width = 0;
+    canvasAndContext.canvas.height = 0;
+    canvasAndContext.canvas = null;
+    canvasAndContext.context = null;
+  }
+
+  _createCanvas(width, height) {
+    (0, _util.unreachable)("Abstract method `_createCanvas` called.");
+  }
+
+}
+
+exports.BaseCanvasFactory = BaseCanvasFactory;
+
+class BaseCMapReaderFactory {
+  constructor({
+    baseUrl = null,
+    isCompressed = false
+  }) {
+    if (this.constructor === BaseCMapReaderFactory) {
+      (0, _util.unreachable)("Cannot initialize BaseCMapReaderFactory.");
+    }
+
+    this.baseUrl = baseUrl;
+    this.isCompressed = isCompressed;
+  }
+
+  async fetch({
+    name
+  }) {
+    if (!this.baseUrl) {
+      throw new Error('The CMap "baseUrl" parameter must be specified, ensure that ' + 'the "cMapUrl" and "cMapPacked" API parameters are provided.');
+    }
+
+    if (!name) {
+      throw new Error("CMap name must be specified.");
+    }
+
+    const url = this.baseUrl + name + (this.isCompressed ? ".bcmap" : "");
+    const compressionType = this.isCompressed ? _util.CMapCompressionType.BINARY : _util.CMapCompressionType.NONE;
+    return this._fetchData(url, compressionType).catch(reason => {
+      throw new Error(`Unable to load ${this.isCompressed ? "binary " : ""}CMap at: ${url}`);
+    });
+  }
+
+  _fetchData(url, compressionType) {
+    (0, _util.unreachable)("Abstract method `_fetchData` called.");
+  }
+
+}
+
+exports.BaseCMapReaderFactory = BaseCMapReaderFactory;
+
+class BaseStandardFontDataFactory {
+  constructor({
+    baseUrl = null
+  }) {
+    if (this.constructor === BaseStandardFontDataFactory) {
+      (0, _util.unreachable)("Cannot initialize BaseStandardFontDataFactory.");
+    }
+
+    this.baseUrl = baseUrl;
+  }
+
+  async fetch({
+    filename
+  }) {
+    if (!this.baseUrl) {
+      throw new Error('The standard font "baseUrl" parameter must be specified, ensure that ' + 'the "standardFontDataUrl" API parameter is provided.');
+    }
+
+    if (!filename) {
+      throw new Error("Font filename must be specified.");
+    }
+
+    const url = `${this.baseUrl}${filename}`;
+    return this._fetchData(url).catch(reason => {
+      throw new Error(`Unable to load font data at: ${url}`);
+    });
+  }
+
+  _fetchData(url) {
+    (0, _util.unreachable)("Abstract method `_fetchData` called.");
+  }
+
+}
+
+exports.BaseStandardFontDataFactory = BaseStandardFontDataFactory;
+
+class BaseSVGFactory {
+  constructor() {
+    if (this.constructor === BaseSVGFactory) {
+      (0, _util.unreachable)("Cannot initialize BaseSVGFactory.");
+    }
+  }
+
+  create(width, height) {
+    if (width <= 0 || height <= 0) {
+      throw new Error("Invalid SVG dimensions");
+    }
+
+    const svg = this._createSVG("svg:svg");
+
+    svg.setAttribute("version", "1.1");
+    svg.setAttribute("width", `${width}px`);
+    svg.setAttribute("height", `${height}px`);
+    svg.setAttribute("preserveAspectRatio", "none");
+    svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
+    return svg;
+  }
+
+  createElement(type) {
+    if (typeof type !== "string") {
+      throw new Error("Invalid SVG element type");
+    }
+
+    return this._createSVG(type);
+  }
+
+  _createSVG(type) {
+    (0, _util.unreachable)("Abstract method `_createSVG` called.");
+  }
+
+}
+
+exports.BaseSVGFactory = BaseSVGFactory;
+
+/***/ }),
+/* 6 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.build = exports.RenderTask = exports.PDFWorker = exports.PDFPageProxy = exports.PDFDocumentProxy = exports.PDFDocumentLoadingTask = exports.PDFDataRangeTransport = exports.LoopbackPort = exports.DefaultStandardFontDataFactory = exports.DefaultCanvasFactory = exports.DefaultCMapReaderFactory = void 0;
+exports.getDocument = getDocument;
+exports.setPDFNetworkStreamFactory = setPDFNetworkStreamFactory;
+exports.version = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+var _display_utils = __w_pdfjs_require__(1);
+
+var _font_loader = __w_pdfjs_require__(7);
+
+var _node_utils = __w_pdfjs_require__(8);
+
+var _annotation_storage = __w_pdfjs_require__(9);
+
+var _canvas = __w_pdfjs_require__(10);
+
+var _worker_options = __w_pdfjs_require__(12);
+
+var _is_node = __w_pdfjs_require__(4);
+
+var _message_handler = __w_pdfjs_require__(13);
+
+var _metadata = __w_pdfjs_require__(14);
+
+var _optional_content_config = __w_pdfjs_require__(15);
+
+var _transport_stream = __w_pdfjs_require__(16);
+
+var _xfa_text = __w_pdfjs_require__(17);
+
+const DEFAULT_RANGE_CHUNK_SIZE = 65536;
+const RENDERING_CANCELLED_TIMEOUT = 100;
+const DefaultCanvasFactory = _is_node.isNodeJS ? _node_utils.NodeCanvasFactory : _display_utils.DOMCanvasFactory;
+exports.DefaultCanvasFactory = DefaultCanvasFactory;
+const DefaultCMapReaderFactory = _is_node.isNodeJS ? _node_utils.NodeCMapReaderFactory : _display_utils.DOMCMapReaderFactory;
+exports.DefaultCMapReaderFactory = DefaultCMapReaderFactory;
+const DefaultStandardFontDataFactory = _is_node.isNodeJS ? _node_utils.NodeStandardFontDataFactory : _display_utils.DOMStandardFontDataFactory;
+exports.DefaultStandardFontDataFactory = DefaultStandardFontDataFactory;
+let createPDFNetworkStream;
+
+function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) {
+  createPDFNetworkStream = pdfNetworkStreamFactory;
+}
+
+function getDocument(src) {
+  const task = new PDFDocumentLoadingTask();
+  let source;
+
+  if (typeof src === "string" || src instanceof URL) {
+    source = {
+      url: src
+    };
+  } else if ((0, _util.isArrayBuffer)(src)) {
+    source = {
+      data: src
+    };
+  } else if (src instanceof PDFDataRangeTransport) {
+    source = {
+      range: src
+    };
+  } else {
+    if (typeof src !== "object") {
+      throw new Error("Invalid parameter in getDocument, " + "need either string, URL, Uint8Array, or parameter object.");
+    }
+
+    if (!src.url && !src.data && !src.range) {
+      throw new Error("Invalid parameter object: need either .data, .range or .url");
+    }
+
+    source = src;
+  }
+
+  const params = Object.create(null);
+  let rangeTransport = null,
+      worker = null;
+
+  for (const key in source) {
+    const value = source[key];
+
+    switch (key) {
+      case "url":
+        if (typeof window !== "undefined") {
+          try {
+            params[key] = new URL(value, window.location).href;
+            continue;
+          } catch (ex) {
+            (0, _util.warn)(`Cannot create valid URL: "${ex}".`);
+          }
+        } else if (typeof value === "string" || value instanceof URL) {
+          params[key] = value.toString();
+          continue;
+        }
+
+        throw new Error("Invalid PDF url data: " + "either string or URL-object is expected in the url property.");
+
+      case "range":
+        rangeTransport = value;
+        continue;
+
+      case "worker":
+        worker = value;
+        continue;
+
+      case "data":
+        if (_is_node.isNodeJS && typeof Buffer !== "undefined" && value instanceof Buffer) {
+          params[key] = new Uint8Array(value);
+        } else if (value instanceof Uint8Array) {
+          break;
+        } else if (typeof value === "string") {
+          params[key] = (0, _util.stringToBytes)(value);
+        } else if (typeof value === "object" && value !== null && !isNaN(value.length)) {
+          params[key] = new Uint8Array(value);
+        } else if ((0, _util.isArrayBuffer)(value)) {
+          params[key] = new Uint8Array(value);
+        } else {
+          throw new Error("Invalid PDF binary data: either typed array, " + "string, or array-like object is expected in the data property.");
+        }
+
+        continue;
+    }
+
+    params[key] = value;
+  }
+
+  params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
+  params.CMapReaderFactory = params.CMapReaderFactory || DefaultCMapReaderFactory;
+  params.StandardFontDataFactory = params.StandardFontDataFactory || DefaultStandardFontDataFactory;
+  params.ignoreErrors = params.stopAtErrors !== true;
+  params.fontExtraProperties = params.fontExtraProperties === true;
+  params.pdfBug = params.pdfBug === true;
+  params.enableXfa = params.enableXfa === true;
+
+  if (typeof params.docBaseUrl !== "string" || (0, _display_utils.isDataScheme)(params.docBaseUrl)) {
+    params.docBaseUrl = null;
+  }
+
+  if (!Number.isInteger(params.maxImageSize)) {
+    params.maxImageSize = -1;
+  }
+
+  if (typeof params.useWorkerFetch !== "boolean") {
+    params.useWorkerFetch = params.CMapReaderFactory === _display_utils.DOMCMapReaderFactory && params.StandardFontDataFactory === _display_utils.DOMStandardFontDataFactory;
+  }
+
+  if (typeof params.isEvalSupported !== "boolean") {
+    params.isEvalSupported = true;
+  }
+
+  if (typeof params.disableFontFace !== "boolean") {
+    params.disableFontFace = _is_node.isNodeJS;
+  }
+
+  if (typeof params.useSystemFonts !== "boolean") {
+    params.useSystemFonts = !_is_node.isNodeJS && !params.disableFontFace;
+  }
+
+  if (typeof params.ownerDocument === "undefined") {
+    params.ownerDocument = globalThis.document;
+  }
+
+  if (typeof params.disableRange !== "boolean") {
+    params.disableRange = false;
+  }
+
+  if (typeof params.disableStream !== "boolean") {
+    params.disableStream = false;
+  }
+
+  if (typeof params.disableAutoFetch !== "boolean") {
+    params.disableAutoFetch = false;
+  }
+
+  (0, _util.setVerbosityLevel)(params.verbosity);
+
+  if (!worker) {
+    const workerParams = {
+      verbosity: params.verbosity,
+      port: _worker_options.GlobalWorkerOptions.workerPort
+    };
+    worker = workerParams.port ? PDFWorker.fromPort(workerParams) : new PDFWorker(workerParams);
+    task._worker = worker;
+  }
+
+  const docId = task.docId;
+  worker.promise.then(function () {
+    if (task.destroyed) {
+      throw new Error("Loading aborted");
+    }
+
+    const workerIdPromise = _fetchDocument(worker, params, rangeTransport, docId);
+
+    const networkStreamPromise = new Promise(function (resolve) {
+      let networkStream;
+
+      if (rangeTransport) {
+        networkStream = new _transport_stream.PDFDataTransportStream({
+          length: params.length,
+          initialData: params.initialData,
+          progressiveDone: params.progressiveDone,
+          contentDispositionFilename: params.contentDispositionFilename,
+          disableRange: params.disableRange,
+          disableStream: params.disableStream
+        }, rangeTransport);
+      } else if (!params.data) {
+        networkStream = createPDFNetworkStream({
+          url: params.url,
+          length: params.length,
+          httpHeaders: params.httpHeaders,
+          withCredentials: params.withCredentials,
+          rangeChunkSize: params.rangeChunkSize,
+          disableRange: params.disableRange,
+          disableStream: params.disableStream
+        });
+      }
+
+      resolve(networkStream);
+    });
+    return Promise.all([workerIdPromise, networkStreamPromise]).then(function ([workerId, networkStream]) {
+      if (task.destroyed) {
+        throw new Error("Loading aborted");
+      }
+
+      const messageHandler = new _message_handler.MessageHandler(docId, workerId, worker.port);
+      const transport = new WorkerTransport(messageHandler, task, networkStream, params);
+      task._transport = transport;
+      messageHandler.send("Ready", null);
+    });
+  }).catch(task._capability.reject);
+  return task;
+}
+
+async function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
+  if (worker.destroyed) {
+    throw new Error("Worker was destroyed");
+  }
+
+  if (pdfDataRangeTransport) {
+    source.length = pdfDataRangeTransport.length;
+    source.initialData = pdfDataRangeTransport.initialData;
+    source.progressiveDone = pdfDataRangeTransport.progressiveDone;
+    source.contentDispositionFilename = pdfDataRangeTransport.contentDispositionFilename;
+  }
+
+  const workerId = await worker.messageHandler.sendWithPromise("GetDocRequest", {
+    docId,
+    apiVersion: '2.12.313',
+    source: {
+      data: source.data,
+      url: source.url,
+      password: source.password,
+      disableAutoFetch: source.disableAutoFetch,
+      rangeChunkSize: source.rangeChunkSize,
+      length: source.length
+    },
+    maxImageSize: source.maxImageSize,
+    disableFontFace: source.disableFontFace,
+    docBaseUrl: source.docBaseUrl,
+    ignoreErrors: source.ignoreErrors,
+    isEvalSupported: source.isEvalSupported,
+    fontExtraProperties: source.fontExtraProperties,
+    enableXfa: source.enableXfa,
+    useSystemFonts: source.useSystemFonts,
+    cMapUrl: source.useWorkerFetch ? source.cMapUrl : null,
+    standardFontDataUrl: source.useWorkerFetch ? source.standardFontDataUrl : null
+  });
+
+  if (worker.destroyed) {
+    throw new Error("Worker was destroyed");
+  }
+
+  return workerId;
+}
+
+class PDFDocumentLoadingTask {
+  static get idCounters() {
+    return (0, _util.shadow)(this, "idCounters", {
+      doc: 0
+    });
+  }
+
+  constructor() {
+    this._capability = (0, _util.createPromiseCapability)();
+    this._transport = null;
+    this._worker = null;
+    this.docId = `d${PDFDocumentLoadingTask.idCounters.doc++}`;
+    this.destroyed = false;
+    this.onPassword = null;
+    this.onProgress = null;
+    this.onUnsupportedFeature = null;
+  }
+
+  get promise() {
+    return this._capability.promise;
+  }
+
+  async destroy() {
+    this.destroyed = true;
+    await this._transport?.destroy();
+    this._transport = null;
+
+    if (this._worker) {
+      this._worker.destroy();
+
+      this._worker = null;
+    }
+  }
+
+}
+
+exports.PDFDocumentLoadingTask = PDFDocumentLoadingTask;
+
+class PDFDataRangeTransport {
+  constructor(length, initialData, progressiveDone = false, contentDispositionFilename = null) {
+    this.length = length;
+    this.initialData = initialData;
+    this.progressiveDone = progressiveDone;
+    this.contentDispositionFilename = contentDispositionFilename;
+    this._rangeListeners = [];
+    this._progressListeners = [];
+    this._progressiveReadListeners = [];
+    this._progressiveDoneListeners = [];
+    this._readyCapability = (0, _util.createPromiseCapability)();
+  }
+
+  addRangeListener(listener) {
+    this._rangeListeners.push(listener);
+  }
+
+  addProgressListener(listener) {
+    this._progressListeners.push(listener);
+  }
+
+  addProgressiveReadListener(listener) {
+    this._progressiveReadListeners.push(listener);
+  }
+
+  addProgressiveDoneListener(listener) {
+    this._progressiveDoneListeners.push(listener);
+  }
+
+  onDataRange(begin, chunk) {
+    for (const listener of this._rangeListeners) {
+      listener(begin, chunk);
+    }
+  }
+
+  onDataProgress(loaded, total) {
+    this._readyCapability.promise.then(() => {
+      for (const listener of this._progressListeners) {
+        listener(loaded, total);
+      }
+    });
+  }
+
+  onDataProgressiveRead(chunk) {
+    this._readyCapability.promise.then(() => {
+      for (const listener of this._progressiveReadListeners) {
+        listener(chunk);
+      }
+    });
+  }
+
+  onDataProgressiveDone() {
+    this._readyCapability.promise.then(() => {
+      for (const listener of this._progressiveDoneListeners) {
+        listener();
+      }
+    });
+  }
+
+  transportReady() {
+    this._readyCapability.resolve();
+  }
+
+  requestDataRange(begin, end) {
+    (0, _util.unreachable)("Abstract method PDFDataRangeTransport.requestDataRange");
+  }
+
+  abort() {}
+
+}
+
+exports.PDFDataRangeTransport = PDFDataRangeTransport;
+
+class PDFDocumentProxy {
+  constructor(pdfInfo, transport) {
+    this._pdfInfo = pdfInfo;
+    this._transport = transport;
+    Object.defineProperty(this, "fingerprint", {
+      get() {
+        (0, _display_utils.deprecated)("`PDFDocumentProxy.fingerprint`, " + "please use `PDFDocumentProxy.fingerprints` instead.");
+        return this.fingerprints[0];
+      }
+
+    });
+    Object.defineProperty(this, "getStats", {
+      value: async () => {
+        (0, _display_utils.deprecated)("`PDFDocumentProxy.getStats`, " + "please use the `PDFDocumentProxy.stats`-getter instead.");
+        return this.stats || {
+          streamTypes: {},
+          fontTypes: {}
+        };
+      }
+    });
+  }
+
+  get annotationStorage() {
+    return this._transport.annotationStorage;
+  }
+
+  get numPages() {
+    return this._pdfInfo.numPages;
+  }
+
+  get fingerprints() {
+    return this._pdfInfo.fingerprints;
+  }
+
+  get stats() {
+    return this._transport.stats;
+  }
+
+  get isPureXfa() {
+    return !!this._transport._htmlForXfa;
+  }
+
+  get allXfaHtml() {
+    return this._transport._htmlForXfa;
+  }
+
+  getPage(pageNumber) {
+    return this._transport.getPage(pageNumber);
+  }
+
+  getPageIndex(ref) {
+    return this._transport.getPageIndex(ref);
+  }
+
+  getDestinations() {
+    return this._transport.getDestinations();
+  }
+
+  getDestination(id) {
+    return this._transport.getDestination(id);
+  }
+
+  getPageLabels() {
+    return this._transport.getPageLabels();
+  }
+
+  getPageLayout() {
+    return this._transport.getPageLayout();
+  }
+
+  getPageMode() {
+    return this._transport.getPageMode();
+  }
+
+  getViewerPreferences() {
+    return this._transport.getViewerPreferences();
+  }
+
+  getOpenAction() {
+    return this._transport.getOpenAction();
+  }
+
+  getAttachments() {
+    return this._transport.getAttachments();
+  }
+
+  getJavaScript() {
+    return this._transport.getJavaScript();
+  }
+
+  getJSActions() {
+    return this._transport.getDocJSActions();
+  }
+
+  getOutline() {
+    return this._transport.getOutline();
+  }
+
+  getOptionalContentConfig() {
+    return this._transport.getOptionalContentConfig();
+  }
+
+  getPermissions() {
+    return this._transport.getPermissions();
+  }
+
+  getMetadata() {
+    return this._transport.getMetadata();
+  }
+
+  getMarkInfo() {
+    return this._transport.getMarkInfo();
+  }
+
+  getData() {
+    return this._transport.getData();
+  }
+
+  getDownloadInfo() {
+    return this._transport.downloadInfoCapability.promise;
+  }
+
+  cleanup(keepLoadedFonts = false) {
+    return this._transport.startCleanup(keepLoadedFonts || this.isPureXfa);
+  }
+
+  destroy() {
+    return this.loadingTask.destroy();
+  }
+
+  get loadingParams() {
+    return this._transport.loadingParams;
+  }
+
+  get loadingTask() {
+    return this._transport.loadingTask;
+  }
+
+  saveDocument() {
+    if (this._transport.annotationStorage.size <= 0) {
+      (0, _display_utils.deprecated)("saveDocument called while `annotationStorage` is empty, " + "please use the getData-method instead.");
+    }
+
+    return this._transport.saveDocument();
+  }
+
+  getFieldObjects() {
+    return this._transport.getFieldObjects();
+  }
+
+  hasJSActions() {
+    return this._transport.hasJSActions();
+  }
+
+  getCalculationOrderIds() {
+    return this._transport.getCalculationOrderIds();
+  }
+
+}
+
+exports.PDFDocumentProxy = PDFDocumentProxy;
+
+class PDFPageProxy {
+  constructor(pageIndex, pageInfo, transport, ownerDocument, pdfBug = false) {
+    this._pageIndex = pageIndex;
+    this._pageInfo = pageInfo;
+    this._ownerDocument = ownerDocument;
+    this._transport = transport;
+    this._stats = pdfBug ? new _display_utils.StatTimer() : null;
+    this._pdfBug = pdfBug;
+    this.commonObjs = transport.commonObjs;
+    this.objs = new PDFObjects();
+    this.cleanupAfterRender = false;
+    this.pendingCleanup = false;
+    this._intentStates = new Map();
+    this._annotationPromises = new Map();
+    this.destroyed = false;
+  }
+
+  get pageNumber() {
+    return this._pageIndex + 1;
+  }
+
+  get rotate() {
+    return this._pageInfo.rotate;
+  }
+
+  get ref() {
+    return this._pageInfo.ref;
+  }
+
+  get userUnit() {
+    return this._pageInfo.userUnit;
+  }
+
+  get view() {
+    return this._pageInfo.view;
+  }
+
+  getViewport({
+    scale,
+    rotation = this.rotate,
+    offsetX = 0,
+    offsetY = 0,
+    dontFlip = false
+  } = {}) {
+    return new _display_utils.PageViewport({
+      viewBox: this.view,
+      scale,
+      rotation,
+      offsetX,
+      offsetY,
+      dontFlip
+    });
+  }
+
+  getAnnotations({
+    intent = "display"
+  } = {}) {
+    const intentArgs = this._transport.getRenderingIntent(intent);
+
+    let promise = this._annotationPromises.get(intentArgs.cacheKey);
+
+    if (!promise) {
+      promise = this._transport.getAnnotations(this._pageIndex, intentArgs.renderingIntent);
+
+      this._annotationPromises.set(intentArgs.cacheKey, promise);
+
+      promise = promise.then(annotations => {
+        for (const annotation of annotations) {
+          if (annotation.titleObj !== undefined) {
+            Object.defineProperty(annotation, "title", {
+              get() {
+                (0, _display_utils.deprecated)("`title`-property on annotation, please use `titleObj` instead.");
+                return annotation.titleObj.str;
+              }
+
+            });
+          }
+
+          if (annotation.contentsObj !== undefined) {
+            Object.defineProperty(annotation, "contents", {
+              get() {
+                (0, _display_utils.deprecated)("`contents`-property on annotation, please use `contentsObj` instead.");
+                return annotation.contentsObj.str;
+              }
+
+            });
+          }
+        }
+
+        return annotations;
+      });
+    }
+
+    return promise;
+  }
+
+  getJSActions() {
+    return this._jsActionsPromise ||= this._transport.getPageJSActions(this._pageIndex);
+  }
+
+  async getXfa() {
+    return this._transport._htmlForXfa?.children[this._pageIndex] || null;
+  }
+
+  render({
+    canvasContext,
+    viewport,
+    intent = "display",
+    annotationMode = _util.AnnotationMode.ENABLE,
+    transform = null,
+    imageLayer = null,
+    canvasFactory = null,
+    background = null,
+    optionalContentConfigPromise = null,
+    annotationCanvasMap = null
+  }) {
+    if (arguments[0]?.renderInteractiveForms !== undefined) {
+      (0, _display_utils.deprecated)("render no longer accepts the `renderInteractiveForms`-option, " + "please use the `annotationMode`-option instead.");
+
+      if (arguments[0].renderInteractiveForms === true && annotationMode === _util.AnnotationMode.ENABLE) {
+        annotationMode = _util.AnnotationMode.ENABLE_FORMS;
+      }
+    }
+
+    if (arguments[0]?.includeAnnotationStorage !== undefined) {
+      (0, _display_utils.deprecated)("render no longer accepts the `includeAnnotationStorage`-option, " + "please use the `annotationMode`-option instead.");
+
+      if (arguments[0].includeAnnotationStorage === true && annotationMode === _util.AnnotationMode.ENABLE) {
+        annotationMode = _util.AnnotationMode.ENABLE_STORAGE;
+      }
+    }
+
+    if (this._stats) {
+      this._stats.time("Overall");
+    }
+
+    const intentArgs = this._transport.getRenderingIntent(intent, annotationMode);
+
+    this.pendingCleanup = false;
+
+    if (!optionalContentConfigPromise) {
+      optionalContentConfigPromise = this._transport.getOptionalContentConfig();
+    }
+
+    let intentState = this._intentStates.get(intentArgs.cacheKey);
+
+    if (!intentState) {
+      intentState = Object.create(null);
+
+      this._intentStates.set(intentArgs.cacheKey, intentState);
+    }
+
+    if (intentState.streamReaderCancelTimeout) {
+      clearTimeout(intentState.streamReaderCancelTimeout);
+      intentState.streamReaderCancelTimeout = null;
+    }
+
+    const canvasFactoryInstance = canvasFactory || new DefaultCanvasFactory({
+      ownerDocument: this._ownerDocument
+    });
+    const intentPrint = !!(intentArgs.renderingIntent & _util.RenderingIntentFlag.PRINT);
+
+    if (!intentState.displayReadyCapability) {
+      intentState.displayReadyCapability = (0, _util.createPromiseCapability)();
+      intentState.operatorList = {
+        fnArray: [],
+        argsArray: [],
+        lastChunk: false
+      };
+
+      if (this._stats) {
+        this._stats.time("Page Request");
+      }
+
+      this._pumpOperatorList(intentArgs);
+    }
+
+    const complete = error => {
+      intentState.renderTasks.delete(internalRenderTask);
+
+      if (this.cleanupAfterRender || intentPrint) {
+        this.pendingCleanup = true;
+      }
+
+      this._tryCleanup();
+
+      if (error) {
+        internalRenderTask.capability.reject(error);
+
+        this._abortOperatorList({
+          intentState,
+          reason: error instanceof Error ? error : new Error(error)
+        });
+      } else {
+        internalRenderTask.capability.resolve();
+      }
+
+      if (this._stats) {
+        this._stats.timeEnd("Rendering");
+
+        this._stats.timeEnd("Overall");
+      }
+    };
+
+    const internalRenderTask = new InternalRenderTask({
+      callback: complete,
+      params: {
+        canvasContext,
+        viewport,
+        transform,
+        imageLayer,
+        background
+      },
+      objs: this.objs,
+      commonObjs: this.commonObjs,
+      annotationCanvasMap,
+      operatorList: intentState.operatorList,
+      pageIndex: this._pageIndex,
+      canvasFactory: canvasFactoryInstance,
+      useRequestAnimationFrame: !intentPrint,
+      pdfBug: this._pdfBug
+    });
+    (intentState.renderTasks ||= new Set()).add(internalRenderTask);
+    const renderTask = internalRenderTask.task;
+    Promise.all([intentState.displayReadyCapability.promise, optionalContentConfigPromise]).then(([transparency, optionalContentConfig]) => {
+      if (this.pendingCleanup) {
+        complete();
+        return;
+      }
+
+      if (this._stats) {
+        this._stats.time("Rendering");
+      }
+
+      internalRenderTask.initializeGraphics({
+        transparency,
+        optionalContentConfig
+      });
+      internalRenderTask.operatorListChanged();
+    }).catch(complete);
+    return renderTask;
+  }
+
+  getOperatorList({
+    intent = "display",
+    annotationMode = _util.AnnotationMode.ENABLE
+  } = {}) {
+    function operatorListChanged() {
+      if (intentState.operatorList.lastChunk) {
+        intentState.opListReadCapability.resolve(intentState.operatorList);
+        intentState.renderTasks.delete(opListTask);
+      }
+    }
+
+    const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, true);
+
+    let intentState = this._intentStates.get(intentArgs.cacheKey);
+
+    if (!intentState) {
+      intentState = Object.create(null);
+
+      this._intentStates.set(intentArgs.cacheKey, intentState);
+    }
+
+    let opListTask;
+
+    if (!intentState.opListReadCapability) {
+      opListTask = Object.create(null);
+      opListTask.operatorListChanged = operatorListChanged;
+      intentState.opListReadCapability = (0, _util.createPromiseCapability)();
+      (intentState.renderTasks ||= new Set()).add(opListTask);
+      intentState.operatorList = {
+        fnArray: [],
+        argsArray: [],
+        lastChunk: false
+      };
+
+      if (this._stats) {
+        this._stats.time("Page Request");
+      }
+
+      this._pumpOperatorList(intentArgs);
+    }
+
+    return intentState.opListReadCapability.promise;
+  }
+
+  streamTextContent({
+    normalizeWhitespace = false,
+    disableCombineTextItems = false,
+    includeMarkedContent = false
+  } = {}) {
+    const TEXT_CONTENT_CHUNK_SIZE = 100;
+    return this._transport.messageHandler.sendWithStream("GetTextContent", {
+      pageIndex: this._pageIndex,
+      normalizeWhitespace: normalizeWhitespace === true,
+      combineTextItems: disableCombineTextItems !== true,
+      includeMarkedContent: includeMarkedContent === true
+    }, {
+      highWaterMark: TEXT_CONTENT_CHUNK_SIZE,
+
+      size(textContent) {
+        return textContent.items.length;
+      }
+
+    });
+  }
+
+  getTextContent(params = {}) {
+    if (this._transport._htmlForXfa) {
+      return this.getXfa().then(xfa => {
+        return _xfa_text.XfaText.textContent(xfa);
+      });
+    }
+
+    const readableStream = this.streamTextContent(params);
+    return new Promise(function (resolve, reject) {
+      function pump() {
+        reader.read().then(function ({
+          value,
+          done
+        }) {
+          if (done) {
+            resolve(textContent);
+            return;
+          }
+
+          Object.assign(textContent.styles, value.styles);
+          textContent.items.push(...value.items);
+          pump();
+        }, reject);
+      }
+
+      const reader = readableStream.getReader();
+      const textContent = {
+        items: [],
+        styles: Object.create(null)
+      };
+      pump();
+    });
+  }
+
+  getStructTree() {
+    return this._structTreePromise ||= this._transport.getStructTree(this._pageIndex);
+  }
+
+  _destroy() {
+    this.destroyed = true;
+    const waitOn = [];
+
+    for (const intentState of this._intentStates.values()) {
+      this._abortOperatorList({
+        intentState,
+        reason: new Error("Page was destroyed."),
+        force: true
+      });
+
+      if (intentState.opListReadCapability) {
+        continue;
+      }
+
+      for (const internalRenderTask of intentState.renderTasks) {
+        waitOn.push(internalRenderTask.completed);
+        internalRenderTask.cancel();
+      }
+    }
+
+    this.objs.clear();
+
+    this._annotationPromises.clear();
+
+    this._jsActionsPromise = null;
+    this._structTreePromise = null;
+    this.pendingCleanup = false;
+    return Promise.all(waitOn);
+  }
+
+  cleanup(resetStats = false) {
+    this.pendingCleanup = true;
+    return this._tryCleanup(resetStats);
+  }
+
+  _tryCleanup(resetStats = false) {
+    if (!this.pendingCleanup) {
+      return false;
+    }
+
+    for (const {
+      renderTasks,
+      operatorList
+    } of this._intentStates.values()) {
+      if (renderTasks.size > 0 || !operatorList.lastChunk) {
+        return false;
+      }
+    }
+
+    this._intentStates.clear();
+
+    this.objs.clear();
+
+    this._annotationPromises.clear();
+
+    this._jsActionsPromise = null;
+    this._structTreePromise = null;
+
+    if (resetStats && this._stats) {
+      this._stats = new _display_utils.StatTimer();
+    }
+
+    this.pendingCleanup = false;
+    return true;
+  }
+
+  _startRenderPage(transparency, cacheKey) {
+    const intentState = this._intentStates.get(cacheKey);
+
+    if (!intentState) {
+      return;
+    }
+
+    if (this._stats) {
+      this._stats.timeEnd("Page Request");
+    }
+
+    if (intentState.displayReadyCapability) {
+      intentState.displayReadyCapability.resolve(transparency);
+    }
+  }
+
+  _renderPageChunk(operatorListChunk, intentState) {
+    for (let i = 0, ii = operatorListChunk.length; i < ii; i++) {
+      intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
+      intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
+    }
+
+    intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
+
+    for (const internalRenderTask of intentState.renderTasks) {
+      internalRenderTask.operatorListChanged();
+    }
+
+    if (operatorListChunk.lastChunk) {
+      this._tryCleanup();
+    }
+  }
+
+  _pumpOperatorList({
+    renderingIntent,
+    cacheKey
+  }) {
+    const readableStream = this._transport.messageHandler.sendWithStream("GetOperatorList", {
+      pageIndex: this._pageIndex,
+      intent: renderingIntent,
+      cacheKey,
+      annotationStorage: renderingIntent & _util.RenderingIntentFlag.ANNOTATIONS_STORAGE ? this._transport.annotationStorage.serializable : null
+    });
+
+    const reader = readableStream.getReader();
+
+    const intentState = this._intentStates.get(cacheKey);
+
+    intentState.streamReader = reader;
+
+    const pump = () => {
+      reader.read().then(({
+        value,
+        done
+      }) => {
+        if (done) {
+          intentState.streamReader = null;
+          return;
+        }
+
+        if (this._transport.destroyed) {
+          return;
+        }
+
+        this._renderPageChunk(value, intentState);
+
+        pump();
+      }, reason => {
+        intentState.streamReader = null;
+
+        if (this._transport.destroyed) {
+          return;
+        }
+
+        if (intentState.operatorList) {
+          intentState.operatorList.lastChunk = true;
+
+          for (const internalRenderTask of intentState.renderTasks) {
+            internalRenderTask.operatorListChanged();
+          }
+
+          this._tryCleanup();
+        }
+
+        if (intentState.displayReadyCapability) {
+          intentState.displayReadyCapability.reject(reason);
+        } else if (intentState.opListReadCapability) {
+          intentState.opListReadCapability.reject(reason);
+        } else {
+          throw reason;
+        }
+      });
+    };
+
+    pump();
+  }
+
+  _abortOperatorList({
+    intentState,
+    reason,
+    force = false
+  }) {
+    if (!intentState.streamReader) {
+      return;
+    }
+
+    if (!force) {
+      if (intentState.renderTasks.size > 0) {
+        return;
+      }
+
+      if (reason instanceof _display_utils.RenderingCancelledException) {
+        intentState.streamReaderCancelTimeout = setTimeout(() => {
+          this._abortOperatorList({
+            intentState,
+            reason,
+            force: true
+          });
+
+          intentState.streamReaderCancelTimeout = null;
+        }, RENDERING_CANCELLED_TIMEOUT);
+        return;
+      }
+    }
+
+    intentState.streamReader.cancel(new _util.AbortException(reason.message)).catch(() => {});
+    intentState.streamReader = null;
+
+    if (this._transport.destroyed) {
+      return;
+    }
+
+    for (const [curCacheKey, curIntentState] of this._intentStates) {
+      if (curIntentState === intentState) {
+        this._intentStates.delete(curCacheKey);
+
+        break;
+      }
+    }
+
+    this.cleanup();
+  }
+
+  get stats() {
+    return this._stats;
+  }
+
+}
+
+exports.PDFPageProxy = PDFPageProxy;
+
+class LoopbackPort {
+  constructor() {
+    this._listeners = [];
+    this._deferred = Promise.resolve();
+  }
+
+  postMessage(obj, transfers) {
+    function cloneValue(object) {
+      if (globalThis.structuredClone) {
+        return globalThis.structuredClone(object, transfers);
+      }
+
+      function fallbackCloneValue(value) {
+        if (typeof value === "function" || typeof value === "symbol" || value instanceof URL) {
+          throw new Error(`LoopbackPort.postMessage - cannot clone: ${value?.toString()}`);
+        }
+
+        if (typeof value !== "object" || value === null) {
+          return value;
+        }
+
+        if (cloned.has(value)) {
+          return cloned.get(value);
+        }
+
+        let buffer, result;
+
+        if ((buffer = value.buffer) && (0, _util.isArrayBuffer)(buffer)) {
+          if (transfers?.includes(buffer)) {
+            result = new value.constructor(buffer, value.byteOffset, value.byteLength);
+          } else {
+            result = new value.constructor(value);
+          }
+
+          cloned.set(value, result);
+          return result;
+        }
+
+        if (value instanceof Map) {
+          result = new Map();
+          cloned.set(value, result);
+
+          for (const [key, val] of value) {
+            result.set(key, fallbackCloneValue(val));
+          }
+
+          return result;
+        }
+
+        if (value instanceof Set) {
+          result = new Set();
+          cloned.set(value, result);
+
+          for (const val of value) {
+            result.add(fallbackCloneValue(val));
+          }
+
+          return result;
+        }
+
+        result = Array.isArray(value) ? [] : Object.create(null);
+        cloned.set(value, result);
+
+        for (const i in value) {
+          let desc,
+              p = value;
+
+          while (!(desc = Object.getOwnPropertyDescriptor(p, i))) {
+            p = Object.getPrototypeOf(p);
+          }
+
+          if (typeof desc.value === "undefined") {
+            continue;
+          }
+
+          if (typeof desc.value === "function" && !value.hasOwnProperty?.(i)) {
+            continue;
+          }
+
+          result[i] = fallbackCloneValue(desc.value);
+        }
+
+        return result;
+      }
+
+      const cloned = new WeakMap();
+      return fallbackCloneValue(object);
+    }
+
+    const event = {
+      data: cloneValue(obj)
+    };
+
+    this._deferred.then(() => {
+      for (const listener of this._listeners) {
+        listener.call(this, event);
+      }
+    });
+  }
+
+  addEventListener(name, listener) {
+    this._listeners.push(listener);
+  }
+
+  removeEventListener(name, listener) {
+    const i = this._listeners.indexOf(listener);
+
+    this._listeners.splice(i, 1);
+  }
+
+  terminate() {
+    this._listeners.length = 0;
+  }
+
+}
+
+exports.LoopbackPort = LoopbackPort;
+const PDFWorkerUtil = {
+  isWorkerDisabled: false,
+  fallbackWorkerSrc: null,
+  fakeWorkerId: 0
+};
+{
+  if (_is_node.isNodeJS && typeof require === "function") {
+    PDFWorkerUtil.isWorkerDisabled = true;
+    PDFWorkerUtil.fallbackWorkerSrc = "./pdf.worker.js";
+  } else if (typeof document === "object") {
+    const pdfjsFilePath = document?.currentScript?.src;
+
+    if (pdfjsFilePath) {
+      PDFWorkerUtil.fallbackWorkerSrc = pdfjsFilePath.replace(/(\.(?:min\.)?js)(\?.*)?$/i, ".worker$1$2");
+    }
+  }
+
+  PDFWorkerUtil.createCDNWrapper = function (url) {
+    const wrapper = `importScripts("${url}");`;
+    return URL.createObjectURL(new Blob([wrapper]));
+  };
+}
+
+class PDFWorker {
+  static get _workerPorts() {
+    return (0, _util.shadow)(this, "_workerPorts", new WeakMap());
+  }
+
+  constructor({
+    name = null,
+    port = null,
+    verbosity = (0, _util.getVerbosityLevel)()
+  } = {}) {
+    if (port && PDFWorker._workerPorts.has(port)) {
+      throw new Error("Cannot use more than one PDFWorker per port.");
+    }
+
+    this.name = name;
+    this.destroyed = false;
+    this.verbosity = verbosity;
+    this._readyCapability = (0, _util.createPromiseCapability)();
+    this._port = null;
+    this._webWorker = null;
+    this._messageHandler = null;
+
+    if (port) {
+      PDFWorker._workerPorts.set(port, this);
+
+      this._initializeFromPort(port);
+
+      return;
+    }
+
+    this._initialize();
+  }
+
+  get promise() {
+    return this._readyCapability.promise;
+  }
+
+  get port() {
+    return this._port;
+  }
+
+  get messageHandler() {
+    return this._messageHandler;
+  }
+
+  _initializeFromPort(port) {
+    this._port = port;
+    this._messageHandler = new _message_handler.MessageHandler("main", "worker", port);
+
+    this._messageHandler.on("ready", function () {});
+
+    this._readyCapability.resolve();
+  }
+
+  _initialize() {
+    if (typeof Worker !== "undefined" && !PDFWorkerUtil.isWorkerDisabled && !PDFWorker._mainThreadWorkerMessageHandler) {
+      let workerSrc = PDFWorker.workerSrc;
+
+      try {
+        if (!(0, _util.isSameOrigin)(window.location.href, workerSrc)) {
+          workerSrc = PDFWorkerUtil.createCDNWrapper(new URL(workerSrc, window.location).href);
+        }
+
+        const worker = new Worker(workerSrc);
+        const messageHandler = new _message_handler.MessageHandler("main", "worker", worker);
+
+        const terminateEarly = () => {
+          worker.removeEventListener("error", onWorkerError);
+          messageHandler.destroy();
+          worker.terminate();
+
+          if (this.destroyed) {
+            this._readyCapability.reject(new Error("Worker was destroyed"));
+          } else {
+            this._setupFakeWorker();
+          }
+        };
+
+        const onWorkerError = () => {
+          if (!this._webWorker) {
+            terminateEarly();
+          }
+        };
+
+        worker.addEventListener("error", onWorkerError);
+        messageHandler.on("test", data => {
+          worker.removeEventListener("error", onWorkerError);
+
+          if (this.destroyed) {
+            terminateEarly();
+            return;
+          }
+
+          if (data) {
+            this._messageHandler = messageHandler;
+            this._port = worker;
+            this._webWorker = worker;
+
+            this._readyCapability.resolve();
+
+            messageHandler.send("configure", {
+              verbosity: this.verbosity
+            });
+          } else {
+            this._setupFakeWorker();
+
+            messageHandler.destroy();
+            worker.terminate();
+          }
+        });
+        messageHandler.on("ready", data => {
+          worker.removeEventListener("error", onWorkerError);
+
+          if (this.destroyed) {
+            terminateEarly();
+            return;
+          }
+
+          try {
+            sendTest();
+          } catch (e) {
+            this._setupFakeWorker();
+          }
+        });
+
+        const sendTest = () => {
+          const testObj = new Uint8Array([255]);
+
+          try {
+            messageHandler.send("test", testObj, [testObj.buffer]);
+          } catch (ex) {
+            (0, _util.warn)("Cannot use postMessage transfers.");
+            testObj[0] = 0;
+            messageHandler.send("test", testObj);
+          }
+        };
+
+        sendTest();
+        return;
+      } catch (e) {
+        (0, _util.info)("The worker has been disabled.");
+      }
+    }
+
+    this._setupFakeWorker();
+  }
+
+  _setupFakeWorker() {
+    if (!PDFWorkerUtil.isWorkerDisabled) {
+      (0, _util.warn)("Setting up fake worker.");
+      PDFWorkerUtil.isWorkerDisabled = true;
+    }
+
+    PDFWorker._setupFakeWorkerGlobal.then(WorkerMessageHandler => {
+      if (this.destroyed) {
+        this._readyCapability.reject(new Error("Worker was destroyed"));
+
+        return;
+      }
+
+      const port = new LoopbackPort();
+      this._port = port;
+      const id = `fake${PDFWorkerUtil.fakeWorkerId++}`;
+      const workerHandler = new _message_handler.MessageHandler(id + "_worker", id, port);
+      WorkerMessageHandler.setup(workerHandler, port);
+      const messageHandler = new _message_handler.MessageHandler(id, id + "_worker", port);
+      this._messageHandler = messageHandler;
+
+      this._readyCapability.resolve();
+
+      messageHandler.send("configure", {
+        verbosity: this.verbosity
+      });
+    }).catch(reason => {
+      this._readyCapability.reject(new Error(`Setting up fake worker failed: "${reason.message}".`));
+    });
+  }
+
+  destroy() {
+    this.destroyed = true;
+
+    if (this._webWorker) {
+      this._webWorker.terminate();
+
+      this._webWorker = null;
+    }
+
+    PDFWorker._workerPorts.delete(this._port);
+
+    this._port = null;
+
+    if (this._messageHandler) {
+      this._messageHandler.destroy();
+
+      this._messageHandler = null;
+    }
+  }
+
+  static fromPort(params) {
+    if (!params?.port) {
+      throw new Error("PDFWorker.fromPort - invalid method signature.");
+    }
+
+    if (this._workerPorts.has(params.port)) {
+      return this._workerPorts.get(params.port);
+    }
+
+    return new PDFWorker(params);
+  }
+
+  static get workerSrc() {
+    if (_worker_options.GlobalWorkerOptions.workerSrc) {
+      return _worker_options.GlobalWorkerOptions.workerSrc;
+    }
+
+    if (PDFWorkerUtil.fallbackWorkerSrc !== null) {
+      if (!_is_node.isNodeJS) {
+        (0, _display_utils.deprecated)('No "GlobalWorkerOptions.workerSrc" specified.');
+      }
+
+      return PDFWorkerUtil.fallbackWorkerSrc;
+    }
+
+    throw new Error('No "GlobalWorkerOptions.workerSrc" specified.');
+  }
+
+  static get _mainThreadWorkerMessageHandler() {
+    try {
+      return globalThis.pdfjsWorker?.WorkerMessageHandler || null;
+    } catch (ex) {
+      return null;
+    }
+  }
+
+  static get _setupFakeWorkerGlobal() {
+    const loader = async () => {
+      const mainWorkerMessageHandler = this._mainThreadWorkerMessageHandler;
+
+      if (mainWorkerMessageHandler) {
+        return mainWorkerMessageHandler;
+      }
+
+      if (_is_node.isNodeJS && typeof require === "function") {
+        const worker = eval("require")(this.workerSrc);
+        return worker.WorkerMessageHandler;
+      }
+
+      await (0, _display_utils.loadScript)(this.workerSrc);
+      return window.pdfjsWorker.WorkerMessageHandler;
+    };
+
+    return (0, _util.shadow)(this, "_setupFakeWorkerGlobal", loader());
+  }
+
+}
+
+exports.PDFWorker = PDFWorker;
+{
+  PDFWorker.getWorkerSrc = function () {
+    (0, _display_utils.deprecated)("`PDFWorker.getWorkerSrc()`, please use `PDFWorker.workerSrc` instead.");
+    return this.workerSrc;
+  };
+}
+
+class WorkerTransport {
+  #docStats = null;
+  #pageCache = new Map();
+  #pagePromises = new Map();
+  #metadataPromise = null;
+
+  constructor(messageHandler, loadingTask, networkStream, params) {
+    this.messageHandler = messageHandler;
+    this.loadingTask = loadingTask;
+    this.commonObjs = new PDFObjects();
+    this.fontLoader = new _font_loader.FontLoader({
+      docId: loadingTask.docId,
+      onUnsupportedFeature: this._onUnsupportedFeature.bind(this),
+      ownerDocument: params.ownerDocument,
+      styleElement: params.styleElement
+    });
+    this._params = params;
+
+    if (!params.useWorkerFetch) {
+      this.CMapReaderFactory = new params.CMapReaderFactory({
+        baseUrl: params.cMapUrl,
+        isCompressed: params.cMapPacked
+      });
+      this.StandardFontDataFactory = new params.StandardFontDataFactory({
+        baseUrl: params.standardFontDataUrl
+      });
+    }
+
+    this.destroyed = false;
+    this.destroyCapability = null;
+    this._passwordCapability = null;
+    this._networkStream = networkStream;
+    this._fullReader = null;
+    this._lastProgress = null;
+    this.downloadInfoCapability = (0, _util.createPromiseCapability)();
+    this.setupMessageHandler();
+  }
+
+  get annotationStorage() {
+    return (0, _util.shadow)(this, "annotationStorage", new _annotation_storage.AnnotationStorage());
+  }
+
+  get stats() {
+    return this.#docStats;
+  }
+
+  getRenderingIntent(intent, annotationMode = _util.AnnotationMode.ENABLE, isOpList = false) {
+    let renderingIntent = _util.RenderingIntentFlag.DISPLAY;
+    let lastModified = "";
+
+    switch (intent) {
+      case "any":
+        renderingIntent = _util.RenderingIntentFlag.ANY;
+        break;
+
+      case "display":
+        break;
+
+      case "print":
+        renderingIntent = _util.RenderingIntentFlag.PRINT;
+        break;
+
+      default:
+        (0, _util.warn)(`getRenderingIntent - invalid intent: ${intent}`);
+    }
+
+    switch (annotationMode) {
+      case _util.AnnotationMode.DISABLE:
+        renderingIntent += _util.RenderingIntentFlag.ANNOTATIONS_DISABLE;
+        break;
+
+      case _util.AnnotationMode.ENABLE:
+        break;
+
+      case _util.AnnotationMode.ENABLE_FORMS:
+        renderingIntent += _util.RenderingIntentFlag.ANNOTATIONS_FORMS;
+        break;
+
+      case _util.AnnotationMode.ENABLE_STORAGE:
+        renderingIntent += _util.RenderingIntentFlag.ANNOTATIONS_STORAGE;
+        lastModified = this.annotationStorage.lastModified;
+        break;
+
+      default:
+        (0, _util.warn)(`getRenderingIntent - invalid annotationMode: ${annotationMode}`);
+    }
+
+    if (isOpList) {
+      renderingIntent += _util.RenderingIntentFlag.OPLIST;
+    }
+
+    return {
+      renderingIntent,
+      cacheKey: `${renderingIntent}_${lastModified}`
+    };
+  }
+
+  destroy() {
+    if (this.destroyCapability) {
+      return this.destroyCapability.promise;
+    }
+
+    this.destroyed = true;
+    this.destroyCapability = (0, _util.createPromiseCapability)();
+
+    if (this._passwordCapability) {
+      this._passwordCapability.reject(new Error("Worker was destroyed during onPassword callback"));
+    }
+
+    const waitOn = [];
+
+    for (const page of this.#pageCache.values()) {
+      waitOn.push(page._destroy());
+    }
+
+    this.#pageCache.clear();
+    this.#pagePromises.clear();
+
+    if (this.hasOwnProperty("annotationStorage")) {
+      this.annotationStorage.resetModified();
+    }
+
+    const terminated = this.messageHandler.sendWithPromise("Terminate", null);
+    waitOn.push(terminated);
+    Promise.all(waitOn).then(() => {
+      this.commonObjs.clear();
+      this.fontLoader.clear();
+      this.#metadataPromise = null;
+      this._getFieldObjectsPromise = null;
+      this._hasJSActionsPromise = null;
+
+      if (this._networkStream) {
+        this._networkStream.cancelAllRequests(new _util.AbortException("Worker was terminated."));
+      }
+
+      if (this.messageHandler) {
+        this.messageHandler.destroy();
+        this.messageHandler = null;
+      }
+
+      this.destroyCapability.resolve();
+    }, this.destroyCapability.reject);
+    return this.destroyCapability.promise;
+  }
+
+  setupMessageHandler() {
+    const {
+      messageHandler,
+      loadingTask
+    } = this;
+    messageHandler.on("GetReader", (data, sink) => {
+      (0, _util.assert)(this._networkStream, "GetReader - no `IPDFStream` instance available.");
+      this._fullReader = this._networkStream.getFullReader();
+
+      this._fullReader.onProgress = evt => {
+        this._lastProgress = {
+          loaded: evt.loaded,
+          total: evt.total
+        };
+      };
+
+      sink.onPull = () => {
+        this._fullReader.read().then(function ({
+          value,
+          done
+        }) {
+          if (done) {
+            sink.close();
+            return;
+          }
+
+          (0, _util.assert)((0, _util.isArrayBuffer)(value), "GetReader - expected an ArrayBuffer.");
+          sink.enqueue(new Uint8Array(value), 1, [value]);
+        }).catch(reason => {
+          sink.error(reason);
+        });
+      };
+
+      sink.onCancel = reason => {
+        this._fullReader.cancel(reason);
+
+        sink.ready.catch(readyReason => {
+          if (this.destroyed) {
+            return;
+          }
+
+          throw readyReason;
+        });
+      };
+    });
+    messageHandler.on("ReaderHeadersReady", data => {
+      const headersCapability = (0, _util.createPromiseCapability)();
+      const fullReader = this._fullReader;
+      fullReader.headersReady.then(() => {
+        if (!fullReader.isStreamingSupported || !fullReader.isRangeSupported) {
+          if (this._lastProgress) {
+            loadingTask.onProgress?.(this._lastProgress);
+          }
+
+          fullReader.onProgress = evt => {
+            loadingTask.onProgress?.({
+              loaded: evt.loaded,
+              total: evt.total
+            });
+          };
+        }
+
+        headersCapability.resolve({
+          isStreamingSupported: fullReader.isStreamingSupported,
+          isRangeSupported: fullReader.isRangeSupported,
+          contentLength: fullReader.contentLength
+        });
+      }, headersCapability.reject);
+      return headersCapability.promise;
+    });
+    messageHandler.on("GetRangeReader", (data, sink) => {
+      (0, _util.assert)(this._networkStream, "GetRangeReader - no `IPDFStream` instance available.");
+
+      const rangeReader = this._networkStream.getRangeReader(data.begin, data.end);
+
+      if (!rangeReader) {
+        sink.close();
+        return;
+      }
+
+      sink.onPull = () => {
+        rangeReader.read().then(function ({
+          value,
+          done
+        }) {
+          if (done) {
+            sink.close();
+            return;
+          }
+
+          (0, _util.assert)((0, _util.isArrayBuffer)(value), "GetRangeReader - expected an ArrayBuffer.");
+          sink.enqueue(new Uint8Array(value), 1, [value]);
+        }).catch(reason => {
+          sink.error(reason);
+        });
+      };
+
+      sink.onCancel = reason => {
+        rangeReader.cancel(reason);
+        sink.ready.catch(readyReason => {
+          if (this.destroyed) {
+            return;
+          }
+
+          throw readyReason;
+        });
+      };
+    });
+    messageHandler.on("GetDoc", ({
+      pdfInfo
+    }) => {
+      this._numPages = pdfInfo.numPages;
+      this._htmlForXfa = pdfInfo.htmlForXfa;
+      delete pdfInfo.htmlForXfa;
+
+      loadingTask._capability.resolve(new PDFDocumentProxy(pdfInfo, this));
+    });
+    messageHandler.on("DocException", function (ex) {
+      let reason;
+
+      switch (ex.name) {
+        case "PasswordException":
+          reason = new _util.PasswordException(ex.message, ex.code);
+          break;
+
+        case "InvalidPDFException":
+          reason = new _util.InvalidPDFException(ex.message);
+          break;
+
+        case "MissingPDFException":
+          reason = new _util.MissingPDFException(ex.message);
+          break;
+
+        case "UnexpectedResponseException":
+          reason = new _util.UnexpectedResponseException(ex.message, ex.status);
+          break;
+
+        case "UnknownErrorException":
+          reason = new _util.UnknownErrorException(ex.message, ex.details);
+          break;
+
+        default:
+          (0, _util.unreachable)("DocException - expected a valid Error.");
+      }
+
+      loadingTask._capability.reject(reason);
+    });
+    messageHandler.on("PasswordRequest", exception => {
+      this._passwordCapability = (0, _util.createPromiseCapability)();
+
+      if (loadingTask.onPassword) {
+        const updatePassword = password => {
+          this._passwordCapability.resolve({
+            password
+          });
+        };
+
+        try {
+          loadingTask.onPassword(updatePassword, exception.code);
+        } catch (ex) {
+          this._passwordCapability.reject(ex);
+        }
+      } else {
+        this._passwordCapability.reject(new _util.PasswordException(exception.message, exception.code));
+      }
+
+      return this._passwordCapability.promise;
+    });
+    messageHandler.on("DataLoaded", data => {
+      loadingTask.onProgress?.({
+        loaded: data.length,
+        total: data.length
+      });
+      this.downloadInfoCapability.resolve(data);
+    });
+    messageHandler.on("StartRenderPage", data => {
+      if (this.destroyed) {
+        return;
+      }
+
+      const page = this.#pageCache.get(data.pageIndex);
+
+      page._startRenderPage(data.transparency, data.cacheKey);
+    });
+    messageHandler.on("commonobj", ([id, type, exportedData]) => {
+      if (this.destroyed) {
+        return;
+      }
+
+      if (this.commonObjs.has(id)) {
+        return;
+      }
+
+      switch (type) {
+        case "Font":
+          const params = this._params;
+
+          if ("error" in exportedData) {
+            const exportedError = exportedData.error;
+            (0, _util.warn)(`Error during font loading: ${exportedError}`);
+            this.commonObjs.resolve(id, exportedError);
+            break;
+          }
+
+          let fontRegistry = null;
+
+          if (params.pdfBug && globalThis.FontInspector?.enabled) {
+            fontRegistry = {
+              registerFont(font, url) {
+                globalThis.FontInspector.fontAdded(font, url);
+              }
+
+            };
+          }
+
+          const font = new _font_loader.FontFaceObject(exportedData, {
+            isEvalSupported: params.isEvalSupported,
+            disableFontFace: params.disableFontFace,
+            ignoreErrors: params.ignoreErrors,
+            onUnsupportedFeature: this._onUnsupportedFeature.bind(this),
+            fontRegistry
+          });
+          this.fontLoader.bind(font).catch(reason => {
+            return messageHandler.sendWithPromise("FontFallback", {
+              id
+            });
+          }).finally(() => {
+            if (!params.fontExtraProperties && font.data) {
+              font.data = null;
+            }
+
+            this.commonObjs.resolve(id, font);
+          });
+          break;
+
+        case "FontPath":
+        case "Image":
+          this.commonObjs.resolve(id, exportedData);
+          break;
+
+        default:
+          throw new Error(`Got unknown common object type ${type}`);
+      }
+    });
+    messageHandler.on("obj", ([id, pageIndex, type, imageData]) => {
+      if (this.destroyed) {
+        return;
+      }
+
+      const pageProxy = this.#pageCache.get(pageIndex);
+
+      if (pageProxy.objs.has(id)) {
+        return;
+      }
+
+      switch (type) {
+        case "Image":
+          pageProxy.objs.resolve(id, imageData);
+          const MAX_IMAGE_SIZE_TO_STORE = 8000000;
+
+          if (imageData?.data?.length > MAX_IMAGE_SIZE_TO_STORE) {
+            pageProxy.cleanupAfterRender = true;
+          }
+
+          break;
+
+        case "Pattern":
+          pageProxy.objs.resolve(id, imageData);
+          break;
+
+        default:
+          throw new Error(`Got unknown object type ${type}`);
+      }
+    });
+    messageHandler.on("DocProgress", data => {
+      if (this.destroyed) {
+        return;
+      }
+
+      loadingTask.onProgress?.({
+        loaded: data.loaded,
+        total: data.total
+      });
+    });
+    messageHandler.on("DocStats", data => {
+      if (this.destroyed) {
+        return;
+      }
+
+      this.#docStats = Object.freeze({
+        streamTypes: Object.freeze(data.streamTypes),
+        fontTypes: Object.freeze(data.fontTypes)
+      });
+    });
+    messageHandler.on("UnsupportedFeature", this._onUnsupportedFeature.bind(this));
+    messageHandler.on("FetchBuiltInCMap", data => {
+      if (this.destroyed) {
+        return Promise.reject(new Error("Worker was destroyed."));
+      }
+
+      if (!this.CMapReaderFactory) {
+        return Promise.reject(new Error("CMapReaderFactory not initialized, see the `useWorkerFetch` parameter."));
+      }
+
+      return this.CMapReaderFactory.fetch(data);
+    });
+    messageHandler.on("FetchStandardFontData", data => {
+      if (this.destroyed) {
+        return Promise.reject(new Error("Worker was destroyed."));
+      }
+
+      if (!this.StandardFontDataFactory) {
+        return Promise.reject(new Error("StandardFontDataFactory not initialized, see the `useWorkerFetch` parameter."));
+      }
+
+      return this.StandardFontDataFactory.fetch(data);
+    });
+  }
+
+  _onUnsupportedFeature({
+    featureId
+  }) {
+    if (this.destroyed) {
+      return;
+    }
+
+    this.loadingTask.onUnsupportedFeature?.(featureId);
+  }
+
+  getData() {
+    return this.messageHandler.sendWithPromise("GetData", null);
+  }
+
+  getPage(pageNumber) {
+    if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this._numPages) {
+      return Promise.reject(new Error("Invalid page request"));
+    }
+
+    const pageIndex = pageNumber - 1,
+          cachedPromise = this.#pagePromises.get(pageIndex);
+
+    if (cachedPromise) {
+      return cachedPromise;
+    }
+
+    const promise = this.messageHandler.sendWithPromise("GetPage", {
+      pageIndex
+    }).then(pageInfo => {
+      if (this.destroyed) {
+        throw new Error("Transport destroyed");
+      }
+
+      const page = new PDFPageProxy(pageIndex, pageInfo, this, this._params.ownerDocument, this._params.pdfBug);
+      this.#pageCache.set(pageIndex, page);
+      return page;
+    });
+    this.#pagePromises.set(pageIndex, promise);
+    return promise;
+  }
+
+  getPageIndex(ref) {
+    return this.messageHandler.sendWithPromise("GetPageIndex", {
+      ref
+    });
+  }
+
+  getAnnotations(pageIndex, intent) {
+    return this.messageHandler.sendWithPromise("GetAnnotations", {
+      pageIndex,
+      intent
+    });
+  }
+
+  saveDocument() {
+    return this.messageHandler.sendWithPromise("SaveDocument", {
+      isPureXfa: !!this._htmlForXfa,
+      numPages: this._numPages,
+      annotationStorage: this.annotationStorage.serializable,
+      filename: this._fullReader?.filename ?? null
+    }).finally(() => {
+      this.annotationStorage.resetModified();
+    });
+  }
+
+  getFieldObjects() {
+    return this._getFieldObjectsPromise ||= this.messageHandler.sendWithPromise("GetFieldObjects", null);
+  }
+
+  hasJSActions() {
+    return this._hasJSActionsPromise ||= this.messageHandler.sendWithPromise("HasJSActions", null);
+  }
+
+  getCalculationOrderIds() {
+    return this.messageHandler.sendWithPromise("GetCalculationOrderIds", null);
+  }
+
+  getDestinations() {
+    return this.messageHandler.sendWithPromise("GetDestinations", null);
+  }
+
+  getDestination(id) {
+    if (typeof id !== "string") {
+      return Promise.reject(new Error("Invalid destination request."));
+    }
+
+    return this.messageHandler.sendWithPromise("GetDestination", {
+      id
+    });
+  }
+
+  getPageLabels() {
+    return this.messageHandler.sendWithPromise("GetPageLabels", null);
+  }
+
+  getPageLayout() {
+    return this.messageHandler.sendWithPromise("GetPageLayout", null);
+  }
+
+  getPageMode() {
+    return this.messageHandler.sendWithPromise("GetPageMode", null);
+  }
+
+  getViewerPreferences() {
+    return this.messageHandler.sendWithPromise("GetViewerPreferences", null);
+  }
+
+  getOpenAction() {
+    return this.messageHandler.sendWithPromise("GetOpenAction", null);
+  }
+
+  getAttachments() {
+    return this.messageHandler.sendWithPromise("GetAttachments", null);
+  }
+
+  getJavaScript() {
+    return this.messageHandler.sendWithPromise("GetJavaScript", null);
+  }
+
+  getDocJSActions() {
+    return this.messageHandler.sendWithPromise("GetDocJSActions", null);
+  }
+
+  getPageJSActions(pageIndex) {
+    return this.messageHandler.sendWithPromise("GetPageJSActions", {
+      pageIndex
+    });
+  }
+
+  getStructTree(pageIndex) {
+    return this.messageHandler.sendWithPromise("GetStructTree", {
+      pageIndex
+    });
+  }
+
+  getOutline() {
+    return this.messageHandler.sendWithPromise("GetOutline", null);
+  }
+
+  getOptionalContentConfig() {
+    return this.messageHandler.sendWithPromise("GetOptionalContentConfig", null).then(results => {
+      return new _optional_content_config.OptionalContentConfig(results);
+    });
+  }
+
+  getPermissions() {
+    return this.messageHandler.sendWithPromise("GetPermissions", null);
+  }
+
+  getMetadata() {
+    return this.#metadataPromise ||= this.messageHandler.sendWithPromise("GetMetadata", null).then(results => {
+      return {
+        info: results[0],
+        metadata: results[1] ? new _metadata.Metadata(results[1]) : null,
+        contentDispositionFilename: this._fullReader?.filename ?? null,
+        contentLength: this._fullReader?.contentLength ?? null
+      };
+    });
+  }
+
+  getMarkInfo() {
+    return this.messageHandler.sendWithPromise("GetMarkInfo", null);
+  }
+
+  async startCleanup(keepLoadedFonts = false) {
+    await this.messageHandler.sendWithPromise("Cleanup", null);
+
+    if (this.destroyed) {
+      return;
+    }
+
+    for (const page of this.#pageCache.values()) {
+      const cleanupSuccessful = page.cleanup();
+
+      if (!cleanupSuccessful) {
+        throw new Error(`startCleanup: Page ${page.pageNumber} is currently rendering.`);
+      }
+    }
+
+    this.commonObjs.clear();
+
+    if (!keepLoadedFonts) {
+      this.fontLoader.clear();
+    }
+
+    this.#metadataPromise = null;
+    this._getFieldObjectsPromise = null;
+    this._hasJSActionsPromise = null;
+  }
+
+  get loadingParams() {
+    const params = this._params;
+    return (0, _util.shadow)(this, "loadingParams", {
+      disableAutoFetch: params.disableAutoFetch,
+      enableXfa: params.enableXfa
+    });
+  }
+
+}
+
+class PDFObjects {
+  constructor() {
+    this._objs = Object.create(null);
+  }
+
+  _ensureObj(objId) {
+    if (this._objs[objId]) {
+      return this._objs[objId];
+    }
+
+    return this._objs[objId] = {
+      capability: (0, _util.createPromiseCapability)(),
+      data: null,
+      resolved: false
+    };
+  }
+
+  get(objId, callback = null) {
+    if (callback) {
+      this._ensureObj(objId).capability.promise.then(callback);
+
+      return null;
+    }
+
+    const obj = this._objs[objId];
+
+    if (!obj || !obj.resolved) {
+      throw new Error(`Requesting object that isn't resolved yet ${objId}.`);
+    }
+
+    return obj.data;
+  }
+
+  has(objId) {
+    const obj = this._objs[objId];
+    return obj?.resolved || false;
+  }
+
+  resolve(objId, data) {
+    const obj = this._ensureObj(objId);
+
+    obj.resolved = true;
+    obj.data = data;
+    obj.capability.resolve(data);
+  }
+
+  clear() {
+    this._objs = Object.create(null);
+  }
+
+}
+
+class RenderTask {
+  constructor(internalRenderTask) {
+    this._internalRenderTask = internalRenderTask;
+    this.onContinue = null;
+  }
+
+  get promise() {
+    return this._internalRenderTask.capability.promise;
+  }
+
+  cancel() {
+    this._internalRenderTask.cancel();
+  }
+
+}
+
+exports.RenderTask = RenderTask;
+
+class InternalRenderTask {
+  static get canvasInUse() {
+    return (0, _util.shadow)(this, "canvasInUse", new WeakSet());
+  }
+
+  constructor({
+    callback,
+    params,
+    objs,
+    commonObjs,
+    annotationCanvasMap,
+    operatorList,
+    pageIndex,
+    canvasFactory,
+    useRequestAnimationFrame = false,
+    pdfBug = false
+  }) {
+    this.callback = callback;
+    this.params = params;
+    this.objs = objs;
+    this.commonObjs = commonObjs;
+    this.annotationCanvasMap = annotationCanvasMap;
+    this.operatorListIdx = null;
+    this.operatorList = operatorList;
+    this._pageIndex = pageIndex;
+    this.canvasFactory = canvasFactory;
+    this._pdfBug = pdfBug;
+    this.running = false;
+    this.graphicsReadyCallback = null;
+    this.graphicsReady = false;
+    this._useRequestAnimationFrame = useRequestAnimationFrame === true && typeof window !== "undefined";
+    this.cancelled = false;
+    this.capability = (0, _util.createPromiseCapability)();
+    this.task = new RenderTask(this);
+    this._cancelBound = this.cancel.bind(this);
+    this._continueBound = this._continue.bind(this);
+    this._scheduleNextBound = this._scheduleNext.bind(this);
+    this._nextBound = this._next.bind(this);
+    this._canvas = params.canvasContext.canvas;
+  }
+
+  get completed() {
+    return this.capability.promise.catch(function () {});
+  }
+
+  initializeGraphics({
+    transparency = false,
+    optionalContentConfig
+  }) {
+    if (this.cancelled) {
+      return;
+    }
+
+    if (this._canvas) {
+      if (InternalRenderTask.canvasInUse.has(this._canvas)) {
+        throw new Error("Cannot use the same canvas during multiple render() operations. " + "Use different canvas or ensure previous operations were " + "cancelled or completed.");
+      }
+
+      InternalRenderTask.canvasInUse.add(this._canvas);
+    }
+
+    if (this._pdfBug && globalThis.StepperManager?.enabled) {
+      this.stepper = globalThis.StepperManager.create(this._pageIndex);
+      this.stepper.init(this.operatorList);
+      this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
+    }
+
+    const {
+      canvasContext,
+      viewport,
+      transform,
+      imageLayer,
+      background
+    } = this.params;
+    this.gfx = new _canvas.CanvasGraphics(canvasContext, this.commonObjs, this.objs, this.canvasFactory, imageLayer, optionalContentConfig, this.annotationCanvasMap);
+    this.gfx.beginDrawing({
+      transform,
+      viewport,
+      transparency,
+      background
+    });
+    this.operatorListIdx = 0;
+    this.graphicsReady = true;
+
+    if (this.graphicsReadyCallback) {
+      this.graphicsReadyCallback();
+    }
+  }
+
+  cancel(error = null) {
+    this.running = false;
+    this.cancelled = true;
+
+    if (this.gfx) {
+      this.gfx.endDrawing();
+    }
+
+    if (this._canvas) {
+      InternalRenderTask.canvasInUse.delete(this._canvas);
+    }
+
+    this.callback(error || new _display_utils.RenderingCancelledException(`Rendering cancelled, page ${this._pageIndex + 1}`, "canvas"));
+  }
+
+  operatorListChanged() {
+    if (!this.graphicsReady) {
+      if (!this.graphicsReadyCallback) {
+        this.graphicsReadyCallback = this._continueBound;
+      }
+
+      return;
+    }
+
+    if (this.stepper) {
+      this.stepper.updateOperatorList(this.operatorList);
+    }
+
+    if (this.running) {
+      return;
+    }
+
+    this._continue();
+  }
+
+  _continue() {
+    this.running = true;
+
+    if (this.cancelled) {
+      return;
+    }
+
+    if (this.task.onContinue) {
+      this.task.onContinue(this._scheduleNextBound);
+    } else {
+      this._scheduleNext();
+    }
+  }
+
+  _scheduleNext() {
+    if (this._useRequestAnimationFrame) {
+      window.requestAnimationFrame(() => {
+        this._nextBound().catch(this._cancelBound);
+      });
+    } else {
+      Promise.resolve().then(this._nextBound).catch(this._cancelBound);
+    }
+  }
+
+  async _next() {
+    if (this.cancelled) {
+      return;
+    }
+
+    this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, this.operatorListIdx, this._continueBound, this.stepper);
+
+    if (this.operatorListIdx === this.operatorList.argsArray.length) {
+      this.running = false;
+
+      if (this.operatorList.lastChunk) {
+        this.gfx.endDrawing();
+
+        if (this._canvas) {
+          InternalRenderTask.canvasInUse.delete(this._canvas);
+        }
+
+        this.callback();
+      }
+    }
+  }
+
+}
+
+const version = '2.12.313';
+exports.version = version;
+const build = 'a2ae56f39';
+exports.build = build;
+
+/***/ }),
+/* 7 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.FontLoader = exports.FontFaceObject = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+class BaseFontLoader {
+  constructor({
+    docId,
+    onUnsupportedFeature,
+    ownerDocument = globalThis.document,
+    styleElement = null
+  }) {
+    if (this.constructor === BaseFontLoader) {
+      (0, _util.unreachable)("Cannot initialize BaseFontLoader.");
+    }
+
+    this.docId = docId;
+    this._onUnsupportedFeature = onUnsupportedFeature;
+    this._document = ownerDocument;
+    this.nativeFontFaces = [];
+    this.styleElement = null;
+  }
+
+  addNativeFontFace(nativeFontFace) {
+    this.nativeFontFaces.push(nativeFontFace);
+
+    this._document.fonts.add(nativeFontFace);
+  }
+
+  insertRule(rule) {
+    let styleElement = this.styleElement;
+
+    if (!styleElement) {
+      styleElement = this.styleElement = this._document.createElement("style");
+      styleElement.id = `PDFJS_FONT_STYLE_TAG_${this.docId}`;
+
+      this._document.documentElement.getElementsByTagName("head")[0].appendChild(styleElement);
+    }
+
+    const styleSheet = styleElement.sheet;
+    styleSheet.insertRule(rule, styleSheet.cssRules.length);
+  }
+
+  clear() {
+    for (const nativeFontFace of this.nativeFontFaces) {
+      this._document.fonts.delete(nativeFontFace);
+    }
+
+    this.nativeFontFaces.length = 0;
+
+    if (this.styleElement) {
+      this.styleElement.remove();
+      this.styleElement = null;
+    }
+  }
+
+  async bind(font) {
+    if (font.attached || font.missingFile) {
+      return;
+    }
+
+    font.attached = true;
+
+    if (this.isFontLoadingAPISupported) {
+      const nativeFontFace = font.createNativeFontFace();
+
+      if (nativeFontFace) {
+        this.addNativeFontFace(nativeFontFace);
+
+        try {
+          await nativeFontFace.loaded;
+        } catch (ex) {
+          this._onUnsupportedFeature({
+            featureId: _util.UNSUPPORTED_FEATURES.errorFontLoadNative
+          });
+
+          (0, _util.warn)(`Failed to load font '${nativeFontFace.family}': '${ex}'.`);
+          font.disableFontFace = true;
+          throw ex;
+        }
+      }
+
+      return;
+    }
+
+    const rule = font.createFontFaceRule();
+
+    if (rule) {
+      this.insertRule(rule);
+
+      if (this.isSyncFontLoadingSupported) {
+        return;
+      }
+
+      await new Promise(resolve => {
+        const request = this._queueLoadingCallback(resolve);
+
+        this._prepareFontLoadEvent([rule], [font], request);
+      });
+    }
+  }
+
+  _queueLoadingCallback(callback) {
+    (0, _util.unreachable)("Abstract method `_queueLoadingCallback`.");
+  }
+
+  get isFontLoadingAPISupported() {
+    const hasFonts = !!this._document?.fonts;
+    return (0, _util.shadow)(this, "isFontLoadingAPISupported", hasFonts);
+  }
+
+  get isSyncFontLoadingSupported() {
+    (0, _util.unreachable)("Abstract method `isSyncFontLoadingSupported`.");
+  }
+
+  get _loadTestFont() {
+    (0, _util.unreachable)("Abstract method `_loadTestFont`.");
+  }
+
+  _prepareFontLoadEvent(rules, fontsToLoad, request) {
+    (0, _util.unreachable)("Abstract method `_prepareFontLoadEvent`.");
+  }
+
+}
+
+let FontLoader;
+exports.FontLoader = FontLoader;
+{
+  exports.FontLoader = FontLoader = class GenericFontLoader extends BaseFontLoader {
+    constructor(params) {
+      super(params);
+      this.loadingContext = {
+        requests: [],
+        nextRequestId: 0
+      };
+      this.loadTestFontId = 0;
+    }
+
+    get isSyncFontLoadingSupported() {
+      let supported = false;
+
+      if (typeof navigator === "undefined") {
+        supported = true;
+      } else {
+        const m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
+
+        if (m?.[1] >= 14) {
+          supported = true;
+        }
+      }
+
+      return (0, _util.shadow)(this, "isSyncFontLoadingSupported", supported);
+    }
+
+    _queueLoadingCallback(callback) {
+      function completeRequest() {
+        (0, _util.assert)(!request.done, "completeRequest() cannot be called twice.");
+        request.done = true;
+
+        while (context.requests.length > 0 && context.requests[0].done) {
+          const otherRequest = context.requests.shift();
+          setTimeout(otherRequest.callback, 0);
+        }
+      }
+
+      const context = this.loadingContext;
+      const request = {
+        id: `pdfjs-font-loading-${context.nextRequestId++}`,
+        done: false,
+        complete: completeRequest,
+        callback
+      };
+      context.requests.push(request);
+      return request;
+    }
+
+    get _loadTestFont() {
+      const getLoadTestFont = function () {
+        return atob("T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA" + "FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA" + "ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA" + "AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1" + "AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD" + "6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM" + "AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D" + "IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA" + "AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA" + "AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB" + "AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY" + "AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA" + "AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA" + "AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC" + "AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3" + "Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj" + "FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA==");
+      };
+
+      return (0, _util.shadow)(this, "_loadTestFont", getLoadTestFont());
+    }
+
+    _prepareFontLoadEvent(rules, fonts, request) {
+      function int32(data, offset) {
+        return data.charCodeAt(offset) << 24 | data.charCodeAt(offset + 1) << 16 | data.charCodeAt(offset + 2) << 8 | data.charCodeAt(offset + 3) & 0xff;
+      }
+
+      function spliceString(s, offset, remove, insert) {
+        const chunk1 = s.substring(0, offset);
+        const chunk2 = s.substring(offset + remove);
+        return chunk1 + insert + chunk2;
+      }
+
+      let i, ii;
+
+      const canvas = this._document.createElement("canvas");
+
+      canvas.width = 1;
+      canvas.height = 1;
+      const ctx = canvas.getContext("2d");
+      let called = 0;
+
+      function isFontReady(name, callback) {
+        called++;
+
+        if (called > 30) {
+          (0, _util.warn)("Load test font never loaded.");
+          callback();
+          return;
+        }
+
+        ctx.font = "30px " + name;
+        ctx.fillText(".", 0, 20);
+        const imageData = ctx.getImageData(0, 0, 1, 1);
+
+        if (imageData.data[3] > 0) {
+          callback();
+          return;
+        }
+
+        setTimeout(isFontReady.bind(null, name, callback));
+      }
+
+      const loadTestFontId = `lt${Date.now()}${this.loadTestFontId++}`;
+      let data = this._loadTestFont;
+      const COMMENT_OFFSET = 976;
+      data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, loadTestFontId);
+      const CFF_CHECKSUM_OFFSET = 16;
+      const XXXX_VALUE = 0x58585858;
+      let checksum = int32(data, CFF_CHECKSUM_OFFSET);
+
+      for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
+        checksum = checksum - XXXX_VALUE + int32(loadTestFontId, i) | 0;
+      }
+
+      if (i < loadTestFontId.length) {
+        checksum = checksum - XXXX_VALUE + int32(loadTestFontId + "XXX", i) | 0;
+      }
+
+      data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, (0, _util.string32)(checksum));
+      const url = `url(data:font/opentype;base64,${btoa(data)});`;
+      const rule = `@font-face {font-family:"${loadTestFontId}";src:${url}}`;
+      this.insertRule(rule);
+      const names = [];
+
+      for (const font of fonts) {
+        names.push(font.loadedName);
+      }
+
+      names.push(loadTestFontId);
+
+      const div = this._document.createElement("div");
+
+      div.style.visibility = "hidden";
+      div.style.width = div.style.height = "10px";
+      div.style.position = "absolute";
+      div.style.top = div.style.left = "0px";
+
+      for (const name of names) {
+        const span = this._document.createElement("span");
+
+        span.textContent = "Hi";
+        span.style.fontFamily = name;
+        div.appendChild(span);
+      }
+
+      this._document.body.appendChild(div);
+
+      isFontReady(loadTestFontId, () => {
+        div.remove();
+        request.complete();
+      });
+    }
+
+  };
+}
+
+class FontFaceObject {
+  constructor(translatedData, {
+    isEvalSupported = true,
+    disableFontFace = false,
+    ignoreErrors = false,
+    onUnsupportedFeature,
+    fontRegistry = null
+  }) {
+    this.compiledGlyphs = Object.create(null);
+
+    for (const i in translatedData) {
+      this[i] = translatedData[i];
+    }
+
+    this.isEvalSupported = isEvalSupported !== false;
+    this.disableFontFace = disableFontFace === true;
+    this.ignoreErrors = ignoreErrors === true;
+    this._onUnsupportedFeature = onUnsupportedFeature;
+    this.fontRegistry = fontRegistry;
+  }
+
+  createNativeFontFace() {
+    if (!this.data || this.disableFontFace) {
+      return null;
+    }
+
+    let nativeFontFace;
+
+    if (!this.cssFontInfo) {
+      nativeFontFace = new FontFace(this.loadedName, this.data, {});
+    } else {
+      const css = {
+        weight: this.cssFontInfo.fontWeight
+      };
+
+      if (this.cssFontInfo.italicAngle) {
+        css.style = `oblique ${this.cssFontInfo.italicAngle}deg`;
+      }
+
+      nativeFontFace = new FontFace(this.cssFontInfo.fontFamily, this.data, css);
+    }
+
+    if (this.fontRegistry) {
+      this.fontRegistry.registerFont(this);
+    }
+
+    return nativeFontFace;
+  }
+
+  createFontFaceRule() {
+    if (!this.data || this.disableFontFace) {
+      return null;
+    }
+
+    const data = (0, _util.bytesToString)(this.data);
+    const url = `url(data:${this.mimetype};base64,${btoa(data)});`;
+    let rule;
+
+    if (!this.cssFontInfo) {
+      rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`;
+    } else {
+      let css = `font-weight: ${this.cssFontInfo.fontWeight};`;
+
+      if (this.cssFontInfo.italicAngle) {
+        css += `font-style: oblique ${this.cssFontInfo.italicAngle}deg;`;
+      }
+
+      rule = `@font-face {font-family:"${this.cssFontInfo.fontFamily}";${css}src:${url}}`;
+    }
+
+    if (this.fontRegistry) {
+      this.fontRegistry.registerFont(this, url);
+    }
+
+    return rule;
+  }
+
+  getPathGenerator(objs, character) {
+    if (this.compiledGlyphs[character] !== undefined) {
+      return this.compiledGlyphs[character];
+    }
+
+    let cmds;
+
+    try {
+      cmds = objs.get(this.loadedName + "_path_" + character);
+    } catch (ex) {
+      if (!this.ignoreErrors) {
+        throw ex;
+      }
+
+      this._onUnsupportedFeature({
+        featureId: _util.UNSUPPORTED_FEATURES.errorFontGetPath
+      });
+
+      (0, _util.warn)(`getPathGenerator - ignoring character: "${ex}".`);
+      return this.compiledGlyphs[character] = function (c, size) {};
+    }
+
+    if (this.isEvalSupported && _util.IsEvalSupportedCached.value) {
+      const jsBuf = [];
+
+      for (const current of cmds) {
+        const args = current.args !== undefined ? current.args.join(",") : "";
+        jsBuf.push("c.", current.cmd, "(", args, ");\n");
+      }
+
+      return this.compiledGlyphs[character] = new Function("c", "size", jsBuf.join(""));
+    }
+
+    return this.compiledGlyphs[character] = function (c, size) {
+      for (const current of cmds) {
+        if (current.cmd === "scale") {
+          current.args = [size, -size];
+        }
+
+        c[current.cmd].apply(c, current.args);
+      }
+    };
+  }
+
+}
+
+exports.FontFaceObject = FontFaceObject;
+
+/***/ }),
+/* 8 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.NodeStandardFontDataFactory = exports.NodeCanvasFactory = exports.NodeCMapReaderFactory = void 0;
+
+var _base_factory = __w_pdfjs_require__(5);
+
+var _is_node = __w_pdfjs_require__(4);
+
+var _util = __w_pdfjs_require__(2);
+
+let NodeCanvasFactory = class {
+  constructor() {
+    (0, _util.unreachable)("Not implemented: NodeCanvasFactory");
+  }
+
+};
+exports.NodeCanvasFactory = NodeCanvasFactory;
+let NodeCMapReaderFactory = class {
+  constructor() {
+    (0, _util.unreachable)("Not implemented: NodeCMapReaderFactory");
+  }
+
+};
+exports.NodeCMapReaderFactory = NodeCMapReaderFactory;
+let NodeStandardFontDataFactory = class {
+  constructor() {
+    (0, _util.unreachable)("Not implemented: NodeStandardFontDataFactory");
+  }
+
+};
+exports.NodeStandardFontDataFactory = NodeStandardFontDataFactory;
+
+if (_is_node.isNodeJS) {
+  const fetchData = function (url) {
+    return new Promise((resolve, reject) => {
+      const fs = require("fs");
+
+      fs.readFile(url, (error, data) => {
+        if (error || !data) {
+          reject(new Error(error));
+          return;
+        }
+
+        resolve(new Uint8Array(data));
+      });
+    });
+  };
+
+  exports.NodeCanvasFactory = NodeCanvasFactory = class extends _base_factory.BaseCanvasFactory {
+    _createCanvas(width, height) {
+      const Canvas = require("canvas");
+
+      return Canvas.createCanvas(width, height);
+    }
+
+  };
+  exports.NodeCMapReaderFactory = NodeCMapReaderFactory = class extends _base_factory.BaseCMapReaderFactory {
+    _fetchData(url, compressionType) {
+      return fetchData(url).then(data => {
+        return {
+          cMapData: data,
+          compressionType
+        };
+      });
+    }
+
+  };
+  exports.NodeStandardFontDataFactory = NodeStandardFontDataFactory = class extends _base_factory.BaseStandardFontDataFactory {
+    _fetchData(url) {
+      return fetchData(url);
+    }
+
+  };
+}
+
+/***/ }),
+/* 9 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.AnnotationStorage = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+class AnnotationStorage {
+  constructor() {
+    this._storage = new Map();
+    this._timeStamp = Date.now();
+    this._modified = false;
+    this.onSetModified = null;
+    this.onResetModified = null;
+  }
+
+  getValue(key, defaultValue) {
+    const value = this._storage.get(key);
+
+    if (value === undefined) {
+      return defaultValue;
+    }
+
+    return Object.assign(defaultValue, value);
+  }
+
+  setValue(key, value) {
+    const obj = this._storage.get(key);
+
+    let modified = false;
+
+    if (obj !== undefined) {
+      for (const [entry, val] of Object.entries(value)) {
+        if (obj[entry] !== val) {
+          modified = true;
+          obj[entry] = val;
+        }
+      }
+    } else {
+      modified = true;
+
+      this._storage.set(key, value);
+    }
+
+    if (modified) {
+      this._timeStamp = Date.now();
+
+      this._setModified();
+    }
+  }
+
+  getAll() {
+    return this._storage.size > 0 ? (0, _util.objectFromMap)(this._storage) : null;
+  }
+
+  get size() {
+    return this._storage.size;
+  }
+
+  _setModified() {
+    if (!this._modified) {
+      this._modified = true;
+
+      if (typeof this.onSetModified === "function") {
+        this.onSetModified();
+      }
+    }
+  }
+
+  resetModified() {
+    if (this._modified) {
+      this._modified = false;
+
+      if (typeof this.onResetModified === "function") {
+        this.onResetModified();
+      }
+    }
+  }
+
+  get serializable() {
+    return this._storage.size > 0 ? this._storage : null;
+  }
+
+  get lastModified() {
+    return this._timeStamp.toString();
+  }
+
+}
+
+exports.AnnotationStorage = AnnotationStorage;
+
+/***/ }),
+/* 10 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.CanvasGraphics = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+var _pattern_helper = __w_pdfjs_require__(11);
+
+var _display_utils = __w_pdfjs_require__(1);
+
+const MIN_FONT_SIZE = 16;
+const MAX_FONT_SIZE = 100;
+const MAX_GROUP_SIZE = 4096;
+const EXECUTION_TIME = 15;
+const EXECUTION_STEPS = 10;
+const COMPILE_TYPE3_GLYPHS = true;
+const MAX_SIZE_TO_COMPILE = 1000;
+const FULL_CHUNK_HEIGHT = 16;
+const LINEWIDTH_SCALE_FACTOR = 1.000001;
+
+function mirrorContextOperations(ctx, destCtx) {
+  if (ctx._removeMirroring) {
+    throw new Error("Context is already forwarding operations.");
+  }
+
+  ctx.__originalSave = ctx.save;
+  ctx.__originalRestore = ctx.restore;
+  ctx.__originalRotate = ctx.rotate;
+  ctx.__originalScale = ctx.scale;
+  ctx.__originalTranslate = ctx.translate;
+  ctx.__originalTransform = ctx.transform;
+  ctx.__originalSetTransform = ctx.setTransform;
+  ctx.__originalResetTransform = ctx.resetTransform;
+  ctx.__originalClip = ctx.clip;
+  ctx.__originalMoveTo = ctx.moveTo;
+  ctx.__originalLineTo = ctx.lineTo;
+  ctx.__originalBezierCurveTo = ctx.bezierCurveTo;
+  ctx.__originalRect = ctx.rect;
+  ctx.__originalClosePath = ctx.closePath;
+  ctx.__originalBeginPath = ctx.beginPath;
+
+  ctx._removeMirroring = () => {
+    ctx.save = ctx.__originalSave;
+    ctx.restore = ctx.__originalRestore;
+    ctx.rotate = ctx.__originalRotate;
+    ctx.scale = ctx.__originalScale;
+    ctx.translate = ctx.__originalTranslate;
+    ctx.transform = ctx.__originalTransform;
+    ctx.setTransform = ctx.__originalSetTransform;
+    ctx.resetTransform = ctx.__originalResetTransform;
+    ctx.clip = ctx.__originalClip;
+    ctx.moveTo = ctx.__originalMoveTo;
+    ctx.lineTo = ctx.__originalLineTo;
+    ctx.bezierCurveTo = ctx.__originalBezierCurveTo;
+    ctx.rect = ctx.__originalRect;
+    ctx.closePath = ctx.__originalClosePath;
+    ctx.beginPath = ctx.__originalBeginPath;
+    delete ctx._removeMirroring;
+  };
+
+  ctx.save = function ctxSave() {
+    destCtx.save();
+
+    this.__originalSave();
+  };
+
+  ctx.restore = function ctxRestore() {
+    destCtx.restore();
+
+    this.__originalRestore();
+  };
+
+  ctx.translate = function ctxTranslate(x, y) {
+    destCtx.translate(x, y);
+
+    this.__originalTranslate(x, y);
+  };
+
+  ctx.scale = function ctxScale(x, y) {
+    destCtx.scale(x, y);
+
+    this.__originalScale(x, y);
+  };
+
+  ctx.transform = function ctxTransform(a, b, c, d, e, f) {
+    destCtx.transform(a, b, c, d, e, f);
+
+    this.__originalTransform(a, b, c, d, e, f);
+  };
+
+  ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) {
+    destCtx.setTransform(a, b, c, d, e, f);
+
+    this.__originalSetTransform(a, b, c, d, e, f);
+  };
+
+  ctx.resetTransform = function ctxResetTransform() {
+    destCtx.resetTransform();
+
+    this.__originalResetTransform();
+  };
+
+  ctx.rotate = function ctxRotate(angle) {
+    destCtx.rotate(angle);
+
+    this.__originalRotate(angle);
+  };
+
+  ctx.clip = function ctxRotate(rule) {
+    destCtx.clip(rule);
+
+    this.__originalClip(rule);
+  };
+
+  ctx.moveTo = function (x, y) {
+    destCtx.moveTo(x, y);
+
+    this.__originalMoveTo(x, y);
+  };
+
+  ctx.lineTo = function (x, y) {
+    destCtx.lineTo(x, y);
+
+    this.__originalLineTo(x, y);
+  };
+
+  ctx.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
+    destCtx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
+
+    this.__originalBezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
+  };
+
+  ctx.rect = function (x, y, width, height) {
+    destCtx.rect(x, y, width, height);
+
+    this.__originalRect(x, y, width, height);
+  };
+
+  ctx.closePath = function () {
+    destCtx.closePath();
+
+    this.__originalClosePath();
+  };
+
+  ctx.beginPath = function () {
+    destCtx.beginPath();
+
+    this.__originalBeginPath();
+  };
+}
+
+function addContextCurrentTransform(ctx) {
+  if (ctx.mozCurrentTransform) {
+    return;
+  }
+
+  ctx._originalSave = ctx.save;
+  ctx._originalRestore = ctx.restore;
+  ctx._originalRotate = ctx.rotate;
+  ctx._originalScale = ctx.scale;
+  ctx._originalTranslate = ctx.translate;
+  ctx._originalTransform = ctx.transform;
+  ctx._originalSetTransform = ctx.setTransform;
+  ctx._originalResetTransform = ctx.resetTransform;
+  ctx._transformMatrix = ctx._transformMatrix || [1, 0, 0, 1, 0, 0];
+  ctx._transformStack = [];
+
+  try {
+    const desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(ctx), "lineWidth");
+    ctx._setLineWidth = desc.set;
+    ctx._getLineWidth = desc.get;
+    Object.defineProperty(ctx, "lineWidth", {
+      set: function setLineWidth(width) {
+        this._setLineWidth(width * LINEWIDTH_SCALE_FACTOR);
+      },
+      get: function getLineWidth() {
+        return this._getLineWidth();
+      }
+    });
+  } catch (_) {}
+
+  Object.defineProperty(ctx, "mozCurrentTransform", {
+    get: function getCurrentTransform() {
+      return this._transformMatrix;
+    }
+  });
+  Object.defineProperty(ctx, "mozCurrentTransformInverse", {
+    get: function getCurrentTransformInverse() {
+      const [a, b, c, d, e, f] = this._transformMatrix;
+      const ad_bc = a * d - b * c;
+      const bc_ad = b * c - a * d;
+      return [d / ad_bc, b / bc_ad, c / bc_ad, a / ad_bc, (d * e - c * f) / bc_ad, (b * e - a * f) / ad_bc];
+    }
+  });
+
+  ctx.save = function ctxSave() {
+    const old = this._transformMatrix;
+
+    this._transformStack.push(old);
+
+    this._transformMatrix = old.slice(0, 6);
+
+    this._originalSave();
+  };
+
+  ctx.restore = function ctxRestore() {
+    const prev = this._transformStack.pop();
+
+    if (prev) {
+      this._transformMatrix = prev;
+
+      this._originalRestore();
+    }
+  };
+
+  ctx.translate = function ctxTranslate(x, y) {
+    const m = this._transformMatrix;
+    m[4] = m[0] * x + m[2] * y + m[4];
+    m[5] = m[1] * x + m[3] * y + m[5];
+
+    this._originalTranslate(x, y);
+  };
+
+  ctx.scale = function ctxScale(x, y) {
+    const m = this._transformMatrix;
+    m[0] *= x;
+    m[1] *= x;
+    m[2] *= y;
+    m[3] *= y;
+
+    this._originalScale(x, y);
+  };
+
+  ctx.transform = function ctxTransform(a, b, c, d, e, f) {
+    const m = this._transformMatrix;
+    this._transformMatrix = [m[0] * a + m[2] * b, m[1] * a + m[3] * b, m[0] * c + m[2] * d, m[1] * c + m[3] * d, m[0] * e + m[2] * f + m[4], m[1] * e + m[3] * f + m[5]];
+
+    ctx._originalTransform(a, b, c, d, e, f);
+  };
+
+  ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) {
+    this._transformMatrix = [a, b, c, d, e, f];
+
+    ctx._originalSetTransform(a, b, c, d, e, f);
+  };
+
+  ctx.resetTransform = function ctxResetTransform() {
+    this._transformMatrix = [1, 0, 0, 1, 0, 0];
+
+    ctx._originalResetTransform();
+  };
+
+  ctx.rotate = function ctxRotate(angle) {
+    const cosValue = Math.cos(angle);
+    const sinValue = Math.sin(angle);
+    const m = this._transformMatrix;
+    this._transformMatrix = [m[0] * cosValue + m[2] * sinValue, m[1] * cosValue + m[3] * sinValue, m[0] * -sinValue + m[2] * cosValue, m[1] * -sinValue + m[3] * cosValue, m[4], m[5]];
+
+    this._originalRotate(angle);
+  };
+}
+
+class CachedCanvases {
+  constructor(canvasFactory) {
+    this.canvasFactory = canvasFactory;
+    this.cache = Object.create(null);
+  }
+
+  getCanvas(id, width, height, trackTransform) {
+    let canvasEntry;
+
+    if (this.cache[id] !== undefined) {
+      canvasEntry = this.cache[id];
+      this.canvasFactory.reset(canvasEntry, width, height);
+      canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0);
+    } else {
+      canvasEntry = this.canvasFactory.create(width, height);
+      this.cache[id] = canvasEntry;
+    }
+
+    if (trackTransform) {
+      addContextCurrentTransform(canvasEntry.context);
+    }
+
+    return canvasEntry;
+  }
+
+  clear() {
+    for (const id in this.cache) {
+      const canvasEntry = this.cache[id];
+      this.canvasFactory.destroy(canvasEntry);
+      delete this.cache[id];
+    }
+  }
+
+}
+
+function compileType3Glyph(imgData) {
+  const POINT_TO_PROCESS_LIMIT = 1000;
+  const POINT_TYPES = new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]);
+  const width = imgData.width,
+        height = imgData.height,
+        width1 = width + 1;
+  let i, ii, j, j0;
+  const points = new Uint8Array(width1 * (height + 1));
+  const lineSize = width + 7 & ~7,
+        data0 = imgData.data;
+  const data = new Uint8Array(lineSize * height);
+  let pos = 0;
+
+  for (i = 0, ii = data0.length; i < ii; i++) {
+    const elem = data0[i];
+    let mask = 128;
+
+    while (mask > 0) {
+      data[pos++] = elem & mask ? 0 : 255;
+      mask >>= 1;
+    }
+  }
+
+  let count = 0;
+  pos = 0;
+
+  if (data[pos] !== 0) {
+    points[0] = 1;
+    ++count;
+  }
+
+  for (j = 1; j < width; j++) {
+    if (data[pos] !== data[pos + 1]) {
+      points[j] = data[pos] ? 2 : 1;
+      ++count;
+    }
+
+    pos++;
+  }
+
+  if (data[pos] !== 0) {
+    points[j] = 2;
+    ++count;
+  }
+
+  for (i = 1; i < height; i++) {
+    pos = i * lineSize;
+    j0 = i * width1;
+
+    if (data[pos - lineSize] !== data[pos]) {
+      points[j0] = data[pos] ? 1 : 8;
+      ++count;
+    }
+
+    let sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);
+
+    for (j = 1; j < width; j++) {
+      sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0);
+
+      if (POINT_TYPES[sum]) {
+        points[j0 + j] = POINT_TYPES[sum];
+        ++count;
+      }
+
+      pos++;
+    }
+
+    if (data[pos - lineSize] !== data[pos]) {
+      points[j0 + j] = data[pos] ? 2 : 4;
+      ++count;
+    }
+
+    if (count > POINT_TO_PROCESS_LIMIT) {
+      return null;
+    }
+  }
+
+  pos = lineSize * (height - 1);
+  j0 = i * width1;
+
+  if (data[pos] !== 0) {
+    points[j0] = 8;
+    ++count;
+  }
+
+  for (j = 1; j < width; j++) {
+    if (data[pos] !== data[pos + 1]) {
+      points[j0 + j] = data[pos] ? 4 : 8;
+      ++count;
+    }
+
+    pos++;
+  }
+
+  if (data[pos] !== 0) {
+    points[j0 + j] = 4;
+    ++count;
+  }
+
+  if (count > POINT_TO_PROCESS_LIMIT) {
+    return null;
+  }
+
+  const steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]);
+  const outlines = [];
+
+  for (i = 0; count && i <= height; i++) {
+    let p = i * width1;
+    const end = p + width;
+
+    while (p < end && !points[p]) {
+      p++;
+    }
+
+    if (p === end) {
+      continue;
+    }
+
+    const coords = [p % width1, i];
+    const p0 = p;
+    let type = points[p];
+
+    do {
+      const step = steps[type];
+
+      do {
+        p += step;
+      } while (!points[p]);
+
+      const pp = points[p];
+
+      if (pp !== 5 && pp !== 10) {
+        type = pp;
+        points[p] = 0;
+      } else {
+        type = pp & 0x33 * type >> 4;
+        points[p] &= type >> 2 | type << 2;
+      }
+
+      coords.push(p % width1, p / width1 | 0);
+
+      if (!points[p]) {
+        --count;
+      }
+    } while (p0 !== p);
+
+    outlines.push(coords);
+    --i;
+  }
+
+  const drawOutline = function (c) {
+    c.save();
+    c.scale(1 / width, -1 / height);
+    c.translate(0, -height);
+    c.beginPath();
+
+    for (let k = 0, kk = outlines.length; k < kk; k++) {
+      const o = outlines[k];
+      c.moveTo(o[0], o[1]);
+
+      for (let l = 2, ll = o.length; l < ll; l += 2) {
+        c.lineTo(o[l], o[l + 1]);
+      }
+    }
+
+    c.fill();
+    c.beginPath();
+    c.restore();
+  };
+
+  return drawOutline;
+}
+
+class CanvasExtraState {
+  constructor(width, height) {
+    this.alphaIsShape = false;
+    this.fontSize = 0;
+    this.fontSizeScale = 1;
+    this.textMatrix = _util.IDENTITY_MATRIX;
+    this.textMatrixScale = 1;
+    this.fontMatrix = _util.FONT_IDENTITY_MATRIX;
+    this.leading = 0;
+    this.x = 0;
+    this.y = 0;
+    this.lineX = 0;
+    this.lineY = 0;
+    this.charSpacing = 0;
+    this.wordSpacing = 0;
+    this.textHScale = 1;
+    this.textRenderingMode = _util.TextRenderingMode.FILL;
+    this.textRise = 0;
+    this.fillColor = "#000000";
+    this.strokeColor = "#000000";
+    this.patternFill = false;
+    this.fillAlpha = 1;
+    this.strokeAlpha = 1;
+    this.lineWidth = 1;
+    this.activeSMask = null;
+    this.transferMaps = null;
+    this.startNewPathAndClipBox([0, 0, width, height]);
+  }
+
+  clone() {
+    const clone = Object.create(this);
+    clone.clipBox = this.clipBox.slice();
+    return clone;
+  }
+
+  setCurrentPoint(x, y) {
+    this.x = x;
+    this.y = y;
+  }
+
+  updatePathMinMax(transform, x, y) {
+    [x, y] = _util.Util.applyTransform([x, y], transform);
+    this.minX = Math.min(this.minX, x);
+    this.minY = Math.min(this.minY, y);
+    this.maxX = Math.max(this.maxX, x);
+    this.maxY = Math.max(this.maxY, y);
+  }
+
+  updateCurvePathMinMax(transform, x0, y0, x1, y1, x2, y2, x3, y3) {
+    const box = _util.Util.bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3);
+
+    this.updatePathMinMax(transform, box[0], box[1]);
+    this.updatePathMinMax(transform, box[2], box[3]);
+  }
+
+  getPathBoundingBox(pathType = _pattern_helper.PathType.FILL, transform = null) {
+    const box = [this.minX, this.minY, this.maxX, this.maxY];
+
+    if (pathType === _pattern_helper.PathType.STROKE) {
+      if (!transform) {
+        (0, _util.unreachable)("Stroke bounding box must include transform.");
+      }
+
+      const scale = _util.Util.singularValueDecompose2dScale(transform);
+
+      const xStrokePad = scale[0] * this.lineWidth / 2;
+      const yStrokePad = scale[1] * this.lineWidth / 2;
+      box[0] -= xStrokePad;
+      box[1] -= yStrokePad;
+      box[2] += xStrokePad;
+      box[3] += yStrokePad;
+    }
+
+    return box;
+  }
+
+  updateClipFromPath() {
+    const intersect = _util.Util.intersect(this.clipBox, this.getPathBoundingBox());
+
+    this.startNewPathAndClipBox(intersect || [0, 0, 0, 0]);
+  }
+
+  startNewPathAndClipBox(box) {
+    this.clipBox = box;
+    this.minX = Infinity;
+    this.minY = Infinity;
+    this.maxX = 0;
+    this.maxY = 0;
+  }
+
+  getClippedPathBoundingBox(pathType = _pattern_helper.PathType.FILL, transform = null) {
+    return _util.Util.intersect(this.clipBox, this.getPathBoundingBox(pathType, transform));
+  }
+
+}
+
+function putBinaryImageData(ctx, imgData, transferMaps = null) {
+  if (typeof ImageData !== "undefined" && imgData instanceof ImageData) {
+    ctx.putImageData(imgData, 0, 0);
+    return;
+  }
+
+  const height = imgData.height,
+        width = imgData.width;
+  const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
+  const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
+  const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
+  const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
+  let srcPos = 0,
+      destPos;
+  const src = imgData.data;
+  const dest = chunkImgData.data;
+  let i, j, thisChunkHeight, elemsInThisChunk;
+  let transferMapRed, transferMapGreen, transferMapBlue, transferMapGray;
+
+  if (transferMaps) {
+    switch (transferMaps.length) {
+      case 1:
+        transferMapRed = transferMaps[0];
+        transferMapGreen = transferMaps[0];
+        transferMapBlue = transferMaps[0];
+        transferMapGray = transferMaps[0];
+        break;
+
+      case 4:
+        transferMapRed = transferMaps[0];
+        transferMapGreen = transferMaps[1];
+        transferMapBlue = transferMaps[2];
+        transferMapGray = transferMaps[3];
+        break;
+    }
+  }
+
+  if (imgData.kind === _util.ImageKind.GRAYSCALE_1BPP) {
+    const srcLength = src.byteLength;
+    const dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2);
+    const dest32DataLength = dest32.length;
+    const fullSrcDiff = width + 7 >> 3;
+    let white = 0xffffffff;
+    let black = _util.IsLittleEndianCached.value ? 0xff000000 : 0x000000ff;
+
+    if (transferMapGray) {
+      if (transferMapGray[0] === 0xff && transferMapGray[0xff] === 0) {
+        [white, black] = [black, white];
+      }
+    }
+
+    for (i = 0; i < totalChunks; i++) {
+      thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
+      destPos = 0;
+
+      for (j = 0; j < thisChunkHeight; j++) {
+        const srcDiff = srcLength - srcPos;
+        let k = 0;
+        const kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7;
+        const kEndUnrolled = kEnd & ~7;
+        let mask = 0;
+        let srcByte = 0;
+
+        for (; k < kEndUnrolled; k += 8) {
+          srcByte = src[srcPos++];
+          dest32[destPos++] = srcByte & 128 ? white : black;
+          dest32[destPos++] = srcByte & 64 ? white : black;
+          dest32[destPos++] = srcByte & 32 ? white : black;
+          dest32[destPos++] = srcByte & 16 ? white : black;
+          dest32[destPos++] = srcByte & 8 ? white : black;
+          dest32[destPos++] = srcByte & 4 ? white : black;
+          dest32[destPos++] = srcByte & 2 ? white : black;
+          dest32[destPos++] = srcByte & 1 ? white : black;
+        }
+
+        for (; k < kEnd; k++) {
+          if (mask === 0) {
+            srcByte = src[srcPos++];
+            mask = 128;
+          }
+
+          dest32[destPos++] = srcByte & mask ? white : black;
+          mask >>= 1;
+        }
+      }
+
+      while (destPos < dest32DataLength) {
+        dest32[destPos++] = 0;
+      }
+
+      ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
+    }
+  } else if (imgData.kind === _util.ImageKind.RGBA_32BPP) {
+    const hasTransferMaps = !!(transferMapRed || transferMapGreen || transferMapBlue);
+    j = 0;
+    elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4;
+
+    for (i = 0; i < fullChunks; i++) {
+      dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
+      srcPos += elemsInThisChunk;
+
+      if (hasTransferMaps) {
+        for (let k = 0; k < elemsInThisChunk; k += 4) {
+          if (transferMapRed) {
+            dest[k + 0] = transferMapRed[dest[k + 0]];
+          }
+
+          if (transferMapGreen) {
+            dest[k + 1] = transferMapGreen[dest[k + 1]];
+          }
+
+          if (transferMapBlue) {
+            dest[k + 2] = transferMapBlue[dest[k + 2]];
+          }
+        }
+      }
+
+      ctx.putImageData(chunkImgData, 0, j);
+      j += FULL_CHUNK_HEIGHT;
+    }
+
+    if (i < totalChunks) {
+      elemsInThisChunk = width * partialChunkHeight * 4;
+      dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
+
+      if (hasTransferMaps) {
+        for (let k = 0; k < elemsInThisChunk; k += 4) {
+          if (transferMapRed) {
+            dest[k + 0] = transferMapRed[dest[k + 0]];
+          }
+
+          if (transferMapGreen) {
+            dest[k + 1] = transferMapGreen[dest[k + 1]];
+          }
+
+          if (transferMapBlue) {
+            dest[k + 2] = transferMapBlue[dest[k + 2]];
+          }
+        }
+      }
+
+      ctx.putImageData(chunkImgData, 0, j);
+    }
+  } else if (imgData.kind === _util.ImageKind.RGB_24BPP) {
+    const hasTransferMaps = !!(transferMapRed || transferMapGreen || transferMapBlue);
+    thisChunkHeight = FULL_CHUNK_HEIGHT;
+    elemsInThisChunk = width * thisChunkHeight;
+
+    for (i = 0; i < totalChunks; i++) {
+      if (i >= fullChunks) {
+        thisChunkHeight = partialChunkHeight;
+        elemsInThisChunk = width * thisChunkHeight;
+      }
+
+      destPos = 0;
+
+      for (j = elemsInThisChunk; j--;) {
+        dest[destPos++] = src[srcPos++];
+        dest[destPos++] = src[srcPos++];
+        dest[destPos++] = src[srcPos++];
+        dest[destPos++] = 255;
+      }
+
+      if (hasTransferMaps) {
+        for (let k = 0; k < destPos; k += 4) {
+          if (transferMapRed) {
+            dest[k + 0] = transferMapRed[dest[k + 0]];
+          }
+
+          if (transferMapGreen) {
+            dest[k + 1] = transferMapGreen[dest[k + 1]];
+          }
+
+          if (transferMapBlue) {
+            dest[k + 2] = transferMapBlue[dest[k + 2]];
+          }
+        }
+      }
+
+      ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
+    }
+  } else {
+    throw new Error(`bad image kind: ${imgData.kind}`);
+  }
+}
+
+function putBinaryImageMask(ctx, imgData) {
+  const height = imgData.height,
+        width = imgData.width;
+  const partialChunkHeight = height % FULL_CHUNK_HEIGHT;
+  const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
+  const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
+  const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
+  let srcPos = 0;
+  const src = imgData.data;
+  const dest = chunkImgData.data;
+
+  for (let i = 0; i < totalChunks; i++) {
+    const thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
+    let destPos = 3;
+
+    for (let j = 0; j < thisChunkHeight; j++) {
+      let elem,
+          mask = 0;
+
+      for (let k = 0; k < width; k++) {
+        if (!mask) {
+          elem = src[srcPos++];
+          mask = 128;
+        }
+
+        dest[destPos] = elem & mask ? 0 : 255;
+        destPos += 4;
+        mask >>= 1;
+      }
+    }
+
+    ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
+  }
+}
+
+function copyCtxState(sourceCtx, destCtx) {
+  const properties = ["strokeStyle", "fillStyle", "fillRule", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "globalCompositeOperation", "font"];
+
+  for (let i = 0, ii = properties.length; i < ii; i++) {
+    const property = properties[i];
+
+    if (sourceCtx[property] !== undefined) {
+      destCtx[property] = sourceCtx[property];
+    }
+  }
+
+  if (sourceCtx.setLineDash !== undefined) {
+    destCtx.setLineDash(sourceCtx.getLineDash());
+    destCtx.lineDashOffset = sourceCtx.lineDashOffset;
+  }
+}
+
+function resetCtxToDefault(ctx) {
+  ctx.strokeStyle = "#000000";
+  ctx.fillStyle = "#000000";
+  ctx.fillRule = "nonzero";
+  ctx.globalAlpha = 1;
+  ctx.lineWidth = 1;
+  ctx.lineCap = "butt";
+  ctx.lineJoin = "miter";
+  ctx.miterLimit = 10;
+  ctx.globalCompositeOperation = "source-over";
+  ctx.font = "10px sans-serif";
+
+  if (ctx.setLineDash !== undefined) {
+    ctx.setLineDash([]);
+    ctx.lineDashOffset = 0;
+  }
+}
+
+function composeSMaskBackdrop(bytes, r0, g0, b0) {
+  const length = bytes.length;
+
+  for (let i = 3; i < length; i += 4) {
+    const alpha = bytes[i];
+
+    if (alpha === 0) {
+      bytes[i - 3] = r0;
+      bytes[i - 2] = g0;
+      bytes[i - 1] = b0;
+    } else if (alpha < 255) {
+      const alpha_ = 255 - alpha;
+      bytes[i - 3] = bytes[i - 3] * alpha + r0 * alpha_ >> 8;
+      bytes[i - 2] = bytes[i - 2] * alpha + g0 * alpha_ >> 8;
+      bytes[i - 1] = bytes[i - 1] * alpha + b0 * alpha_ >> 8;
+    }
+  }
+}
+
+function composeSMaskAlpha(maskData, layerData, transferMap) {
+  const length = maskData.length;
+  const scale = 1 / 255;
+
+  for (let i = 3; i < length; i += 4) {
+    const alpha = transferMap ? transferMap[maskData[i]] : maskData[i];
+    layerData[i] = layerData[i] * alpha * scale | 0;
+  }
+}
+
+function composeSMaskLuminosity(maskData, layerData, transferMap) {
+  const length = maskData.length;
+
+  for (let i = 3; i < length; i += 4) {
+    const y = maskData[i - 3] * 77 + maskData[i - 2] * 152 + maskData[i - 1] * 28;
+    layerData[i] = transferMap ? layerData[i] * transferMap[y >> 8] >> 8 : layerData[i] * y >> 16;
+  }
+}
+
+function genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap, layerOffsetX, layerOffsetY, maskOffsetX, maskOffsetY) {
+  const hasBackdrop = !!backdrop;
+  const r0 = hasBackdrop ? backdrop[0] : 0;
+  const g0 = hasBackdrop ? backdrop[1] : 0;
+  const b0 = hasBackdrop ? backdrop[2] : 0;
+  let composeFn;
+
+  if (subtype === "Luminosity") {
+    composeFn = composeSMaskLuminosity;
+  } else {
+    composeFn = composeSMaskAlpha;
+  }
+
+  const PIXELS_TO_PROCESS = 1048576;
+  const chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width));
+
+  for (let row = 0; row < height; row += chunkSize) {
+    const chunkHeight = Math.min(chunkSize, height - row);
+    const maskData = maskCtx.getImageData(layerOffsetX - maskOffsetX, row + (layerOffsetY - maskOffsetY), width, chunkHeight);
+    const layerData = layerCtx.getImageData(layerOffsetX, row + layerOffsetY, width, chunkHeight);
+
+    if (hasBackdrop) {
+      composeSMaskBackdrop(maskData.data, r0, g0, b0);
+    }
+
+    composeFn(maskData.data, layerData.data, transferMap);
+    layerCtx.putImageData(layerData, layerOffsetX, row + layerOffsetY);
+  }
+}
+
+function composeSMask(ctx, smask, layerCtx, layerBox) {
+  const layerOffsetX = layerBox[0];
+  const layerOffsetY = layerBox[1];
+  const layerWidth = layerBox[2] - layerOffsetX;
+  const layerHeight = layerBox[3] - layerOffsetY;
+
+  if (layerWidth === 0 || layerHeight === 0) {
+    return;
+  }
+
+  genericComposeSMask(smask.context, layerCtx, layerWidth, layerHeight, smask.subtype, smask.backdrop, smask.transferMap, layerOffsetX, layerOffsetY, smask.offsetX, smask.offsetY);
+  ctx.save();
+  ctx.globalAlpha = 1;
+  ctx.globalCompositeOperation = "source-over";
+  ctx.setTransform(1, 0, 0, 1, 0, 0);
+  ctx.drawImage(layerCtx.canvas, 0, 0);
+  ctx.restore();
+}
+
+function getImageSmoothingEnabled(transform, interpolate) {
+  const scale = _util.Util.singularValueDecompose2dScale(transform);
+
+  scale[0] = Math.fround(scale[0]);
+  scale[1] = Math.fround(scale[1]);
+  const actualScale = Math.fround((globalThis.devicePixelRatio || 1) * _display_utils.PixelsPerInch.PDF_TO_CSS_UNITS);
+
+  if (interpolate !== undefined) {
+    return interpolate;
+  } else if (scale[0] <= actualScale || scale[1] <= actualScale) {
+    return true;
+  }
+
+  return false;
+}
+
+const LINE_CAP_STYLES = ["butt", "round", "square"];
+const LINE_JOIN_STYLES = ["miter", "round", "bevel"];
+const NORMAL_CLIP = {};
+const EO_CLIP = {};
+
+class CanvasGraphics {
+  constructor(canvasCtx, commonObjs, objs, canvasFactory, imageLayer, optionalContentConfig, annotationCanvasMap) {
+    this.ctx = canvasCtx;
+    this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height);
+    this.stateStack = [];
+    this.pendingClip = null;
+    this.pendingEOFill = false;
+    this.res = null;
+    this.xobjs = null;
+    this.commonObjs = commonObjs;
+    this.objs = objs;
+    this.canvasFactory = canvasFactory;
+    this.imageLayer = imageLayer;
+    this.groupStack = [];
+    this.processingType3 = null;
+    this.baseTransform = null;
+    this.baseTransformStack = [];
+    this.groupLevel = 0;
+    this.smaskStack = [];
+    this.smaskCounter = 0;
+    this.tempSMask = null;
+    this.suspendedCtx = null;
+    this.contentVisible = true;
+    this.markedContentStack = [];
+    this.optionalContentConfig = optionalContentConfig;
+    this.cachedCanvases = new CachedCanvases(this.canvasFactory);
+    this.cachedPatterns = new Map();
+    this.annotationCanvasMap = annotationCanvasMap;
+    this.viewportScale = 1;
+    this.outputScaleX = 1;
+    this.outputScaleY = 1;
+
+    if (canvasCtx) {
+      addContextCurrentTransform(canvasCtx);
+    }
+
+    this._cachedGetSinglePixelWidth = null;
+  }
+
+  beginDrawing({
+    transform,
+    viewport,
+    transparency = false,
+    background = null
+  }) {
+    const width = this.ctx.canvas.width;
+    const height = this.ctx.canvas.height;
+    this.ctx.save();
+    this.ctx.fillStyle = background || "rgb(255, 255, 255)";
+    this.ctx.fillRect(0, 0, width, height);
+    this.ctx.restore();
+
+    if (transparency) {
+      const transparentCanvas = this.cachedCanvases.getCanvas("transparent", width, height, true);
+      this.compositeCtx = this.ctx;
+      this.transparentCanvas = transparentCanvas.canvas;
+      this.ctx = transparentCanvas.context;
+      this.ctx.save();
+      this.ctx.transform.apply(this.ctx, this.compositeCtx.mozCurrentTransform);
+    }
+
+    this.ctx.save();
+    resetCtxToDefault(this.ctx);
+
+    if (transform) {
+      this.ctx.transform.apply(this.ctx, transform);
+      this.outputScaleX = transform[0];
+      this.outputScaleY = transform[0];
+    }
+
+    this.ctx.transform.apply(this.ctx, viewport.transform);
+    this.viewportScale = viewport.scale;
+    this.baseTransform = this.ctx.mozCurrentTransform.slice();
+    this._combinedScaleFactor = Math.hypot(this.baseTransform[0], this.baseTransform[2]);
+
+    if (this.imageLayer) {
+      this.imageLayer.beginLayout();
+    }
+  }
+
+  executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper) {
+    const argsArray = operatorList.argsArray;
+    const fnArray = operatorList.fnArray;
+    let i = executionStartIdx || 0;
+    const argsArrayLen = argsArray.length;
+
+    if (argsArrayLen === i) {
+      return i;
+    }
+
+    const chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === "function";
+    const endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0;
+    let steps = 0;
+    const commonObjs = this.commonObjs;
+    const objs = this.objs;
+    let fnId;
+
+    while (true) {
+      if (stepper !== undefined && i === stepper.nextBreakPoint) {
+        stepper.breakIt(i, continueCallback);
+        return i;
+      }
+
+      fnId = fnArray[i];
+
+      if (fnId !== _util.OPS.dependency) {
+        this[fnId].apply(this, argsArray[i]);
+      } else {
+        for (const depObjId of argsArray[i]) {
+          const objsPool = depObjId.startsWith("g_") ? commonObjs : objs;
+
+          if (!objsPool.has(depObjId)) {
+            objsPool.get(depObjId, continueCallback);
+            return i;
+          }
+        }
+      }
+
+      i++;
+
+      if (i === argsArrayLen) {
+        return i;
+      }
+
+      if (chunkOperations && ++steps > EXECUTION_STEPS) {
+        if (Date.now() > endTime) {
+          continueCallback();
+          return i;
+        }
+
+        steps = 0;
+      }
+    }
+  }
+
+  endDrawing() {
+    while (this.stateStack.length || this.current.activeSMask !== null) {
+      this.restore();
+    }
+
+    this.ctx.restore();
+
+    if (this.transparentCanvas) {
+      this.ctx = this.compositeCtx;
+      this.ctx.save();
+      this.ctx.setTransform(1, 0, 0, 1, 0, 0);
+      this.ctx.drawImage(this.transparentCanvas, 0, 0);
+      this.ctx.restore();
+      this.transparentCanvas = null;
+    }
+
+    this.cachedCanvases.clear();
+    this.cachedPatterns.clear();
+
+    if (this.imageLayer) {
+      this.imageLayer.endLayout();
+    }
+  }
+
+  _scaleImage(img, inverseTransform) {
+    const width = img.width;
+    const height = img.height;
+    let widthScale = Math.max(Math.hypot(inverseTransform[0], inverseTransform[1]), 1);
+    let heightScale = Math.max(Math.hypot(inverseTransform[2], inverseTransform[3]), 1);
+    let paintWidth = width,
+        paintHeight = height;
+    let tmpCanvasId = "prescale1";
+    let tmpCanvas, tmpCtx;
+
+    while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) {
+      let newWidth = paintWidth,
+          newHeight = paintHeight;
+
+      if (widthScale > 2 && paintWidth > 1) {
+        newWidth = Math.ceil(paintWidth / 2);
+        widthScale /= paintWidth / newWidth;
+      }
+
+      if (heightScale > 2 && paintHeight > 1) {
+        newHeight = Math.ceil(paintHeight / 2);
+        heightScale /= paintHeight / newHeight;
+      }
+
+      tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight);
+      tmpCtx = tmpCanvas.context;
+      tmpCtx.clearRect(0, 0, newWidth, newHeight);
+      tmpCtx.drawImage(img, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight);
+      img = tmpCanvas.canvas;
+      paintWidth = newWidth;
+      paintHeight = newHeight;
+      tmpCanvasId = tmpCanvasId === "prescale1" ? "prescale2" : "prescale1";
+    }
+
+    return {
+      img,
+      paintWidth,
+      paintHeight
+    };
+  }
+
+  _createMaskCanvas(img) {
+    const ctx = this.ctx;
+    const width = img.width,
+          height = img.height;
+    const fillColor = this.current.fillColor;
+    const isPatternFill = this.current.patternFill;
+    const maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height);
+    const maskCtx = maskCanvas.context;
+    putBinaryImageMask(maskCtx, img);
+    const objToCanvas = ctx.mozCurrentTransform;
+
+    let maskToCanvas = _util.Util.transform(objToCanvas, [1 / width, 0, 0, -1 / height, 0, 0]);
+
+    maskToCanvas = _util.Util.transform(maskToCanvas, [1, 0, 0, 1, 0, -height]);
+
+    const cord1 = _util.Util.applyTransform([0, 0], maskToCanvas);
+
+    const cord2 = _util.Util.applyTransform([width, height], maskToCanvas);
+
+    const rect = _util.Util.normalizeRect([cord1[0], cord1[1], cord2[0], cord2[1]]);
+
+    const drawnWidth = Math.ceil(rect[2] - rect[0]);
+    const drawnHeight = Math.ceil(rect[3] - rect[1]);
+    const fillCanvas = this.cachedCanvases.getCanvas("fillCanvas", drawnWidth, drawnHeight, true);
+    const fillCtx = fillCanvas.context;
+    const offsetX = Math.min(cord1[0], cord2[0]);
+    const offsetY = Math.min(cord1[1], cord2[1]);
+    fillCtx.translate(-offsetX, -offsetY);
+    fillCtx.transform.apply(fillCtx, maskToCanvas);
+
+    const scaled = this._scaleImage(maskCanvas.canvas, fillCtx.mozCurrentTransformInverse);
+
+    fillCtx.imageSmoothingEnabled = getImageSmoothingEnabled(fillCtx.mozCurrentTransform, img.interpolate);
+    fillCtx.drawImage(scaled.img, 0, 0, scaled.img.width, scaled.img.height, 0, 0, width, height);
+    fillCtx.globalCompositeOperation = "source-in";
+
+    const inverse = _util.Util.transform(fillCtx.mozCurrentTransformInverse, [1, 0, 0, 1, -offsetX, -offsetY]);
+
+    fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(ctx, this, inverse, _pattern_helper.PathType.FILL) : fillColor;
+    fillCtx.fillRect(0, 0, width, height);
+    return {
+      canvas: fillCanvas.canvas,
+      offsetX: Math.round(offsetX),
+      offsetY: Math.round(offsetY)
+    };
+  }
+
+  setLineWidth(width) {
+    this.current.lineWidth = width;
+    this.ctx.lineWidth = width;
+  }
+
+  setLineCap(style) {
+    this.ctx.lineCap = LINE_CAP_STYLES[style];
+  }
+
+  setLineJoin(style) {
+    this.ctx.lineJoin = LINE_JOIN_STYLES[style];
+  }
+
+  setMiterLimit(limit) {
+    this.ctx.miterLimit = limit;
+  }
+
+  setDash(dashArray, dashPhase) {
+    const ctx = this.ctx;
+
+    if (ctx.setLineDash !== undefined) {
+      ctx.setLineDash(dashArray);
+      ctx.lineDashOffset = dashPhase;
+    }
+  }
+
+  setRenderingIntent(intent) {}
+
+  setFlatness(flatness) {}
+
+  setGState(states) {
+    for (let i = 0, ii = states.length; i < ii; i++) {
+      const state = states[i];
+      const key = state[0];
+      const value = state[1];
+
+      switch (key) {
+        case "LW":
+          this.setLineWidth(value);
+          break;
+
+        case "LC":
+          this.setLineCap(value);
+          break;
+
+        case "LJ":
+          this.setLineJoin(value);
+          break;
+
+        case "ML":
+          this.setMiterLimit(value);
+          break;
+
+        case "D":
+          this.setDash(value[0], value[1]);
+          break;
+
+        case "RI":
+          this.setRenderingIntent(value);
+          break;
+
+        case "FL":
+          this.setFlatness(value);
+          break;
+
+        case "Font":
+          this.setFont(value[0], value[1]);
+          break;
+
+        case "CA":
+          this.current.strokeAlpha = state[1];
+          break;
+
+        case "ca":
+          this.current.fillAlpha = state[1];
+          this.ctx.globalAlpha = state[1];
+          break;
+
+        case "BM":
+          this.ctx.globalCompositeOperation = value;
+          break;
+
+        case "SMask":
+          this.current.activeSMask = value ? this.tempSMask : null;
+          this.tempSMask = null;
+          this.checkSMaskState();
+          break;
+
+        case "TR":
+          this.current.transferMaps = value;
+      }
+    }
+  }
+
+  checkSMaskState() {
+    const inSMaskMode = !!this.suspendedCtx;
+
+    if (this.current.activeSMask && !inSMaskMode) {
+      this.beginSMaskMode();
+    } else if (!this.current.activeSMask && inSMaskMode) {
+      this.endSMaskMode();
+    }
+  }
+
+  beginSMaskMode() {
+    if (this.suspendedCtx) {
+      throw new Error("beginSMaskMode called while already in smask mode");
+    }
+
+    const drawnWidth = this.ctx.canvas.width;
+    const drawnHeight = this.ctx.canvas.height;
+    const cacheId = "smaskGroupAt" + this.groupLevel;
+    const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight, true);
+    this.suspendedCtx = this.ctx;
+    this.ctx = scratchCanvas.context;
+    const ctx = this.ctx;
+    ctx.setTransform.apply(ctx, this.suspendedCtx.mozCurrentTransform);
+    copyCtxState(this.suspendedCtx, ctx);
+    mirrorContextOperations(ctx, this.suspendedCtx);
+    this.setGState([["BM", "source-over"], ["ca", 1], ["CA", 1]]);
+  }
+
+  endSMaskMode() {
+    if (!this.suspendedCtx) {
+      throw new Error("endSMaskMode called while not in smask mode");
+    }
+
+    this.ctx._removeMirroring();
+
+    copyCtxState(this.ctx, this.suspendedCtx);
+    this.ctx = this.suspendedCtx;
+    this.current.activeSMask = null;
+    this.suspendedCtx = null;
+  }
+
+  compose(dirtyBox) {
+    if (!this.current.activeSMask) {
+      return;
+    }
+
+    if (!dirtyBox) {
+      dirtyBox = [0, 0, this.ctx.canvas.width, this.ctx.canvas.height];
+    } else {
+      dirtyBox[0] = Math.floor(dirtyBox[0]);
+      dirtyBox[1] = Math.floor(dirtyBox[1]);
+      dirtyBox[2] = Math.ceil(dirtyBox[2]);
+      dirtyBox[3] = Math.ceil(dirtyBox[3]);
+    }
+
+    const smask = this.current.activeSMask;
+    const suspendedCtx = this.suspendedCtx;
+    composeSMask(suspendedCtx, smask, this.ctx, dirtyBox);
+    this.ctx.save();
+    this.ctx.setTransform(1, 0, 0, 1, 0, 0);
+    this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
+    this.ctx.restore();
+  }
+
+  save() {
+    this.ctx.save();
+    const old = this.current;
+    this.stateStack.push(old);
+    this.current = old.clone();
+  }
+
+  restore() {
+    if (this.stateStack.length === 0 && this.current.activeSMask) {
+      this.endSMaskMode();
+    }
+
+    if (this.stateStack.length !== 0) {
+      this.current = this.stateStack.pop();
+      this.ctx.restore();
+      this.checkSMaskState();
+      this.pendingClip = null;
+      this._cachedGetSinglePixelWidth = null;
+    }
+  }
+
+  transform(a, b, c, d, e, f) {
+    this.ctx.transform(a, b, c, d, e, f);
+    this._cachedGetSinglePixelWidth = null;
+  }
+
+  constructPath(ops, args) {
+    const ctx = this.ctx;
+    const current = this.current;
+    let x = current.x,
+        y = current.y;
+    let startX, startY;
+
+    for (let i = 0, j = 0, ii = ops.length; i < ii; i++) {
+      switch (ops[i] | 0) {
+        case _util.OPS.rectangle:
+          x = args[j++];
+          y = args[j++];
+          const width = args[j++];
+          const height = args[j++];
+          const xw = x + width;
+          const yh = y + height;
+          ctx.moveTo(x, y);
+
+          if (width === 0 || height === 0) {
+            ctx.lineTo(xw, yh);
+          } else {
+            ctx.lineTo(xw, y);
+            ctx.lineTo(xw, yh);
+            ctx.lineTo(x, yh);
+          }
+
+          current.updatePathMinMax(ctx.mozCurrentTransform, x, y);
+          current.updatePathMinMax(ctx.mozCurrentTransform, xw, yh);
+          ctx.closePath();
+          break;
+
+        case _util.OPS.moveTo:
+          x = args[j++];
+          y = args[j++];
+          ctx.moveTo(x, y);
+          current.updatePathMinMax(ctx.mozCurrentTransform, x, y);
+          break;
+
+        case _util.OPS.lineTo:
+          x = args[j++];
+          y = args[j++];
+          ctx.lineTo(x, y);
+          current.updatePathMinMax(ctx.mozCurrentTransform, x, y);
+          break;
+
+        case _util.OPS.curveTo:
+          startX = x;
+          startY = y;
+          x = args[j + 4];
+          y = args[j + 5];
+          ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], x, y);
+          current.updateCurvePathMinMax(ctx.mozCurrentTransform, startX, startY, args[j], args[j + 1], args[j + 2], args[j + 3], x, y);
+          j += 6;
+          break;
+
+        case _util.OPS.curveTo2:
+          startX = x;
+          startY = y;
+          ctx.bezierCurveTo(x, y, args[j], args[j + 1], args[j + 2], args[j + 3]);
+          current.updateCurvePathMinMax(ctx.mozCurrentTransform, startX, startY, x, y, args[j], args[j + 1], args[j + 2], args[j + 3]);
+          x = args[j + 2];
+          y = args[j + 3];
+          j += 4;
+          break;
+
+        case _util.OPS.curveTo3:
+          startX = x;
+          startY = y;
+          x = args[j + 2];
+          y = args[j + 3];
+          ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y);
+          current.updateCurvePathMinMax(ctx.mozCurrentTransform, startX, startY, args[j], args[j + 1], x, y, x, y);
+          j += 4;
+          break;
+
+        case _util.OPS.closePath:
+          ctx.closePath();
+          break;
+      }
+    }
+
+    current.setCurrentPoint(x, y);
+  }
+
+  closePath() {
+    this.ctx.closePath();
+  }
+
+  stroke(consumePath) {
+    consumePath = typeof consumePath !== "undefined" ? consumePath : true;
+    const ctx = this.ctx;
+    const strokeColor = this.current.strokeColor;
+    ctx.globalAlpha = this.current.strokeAlpha;
+
+    if (this.contentVisible) {
+      if (typeof strokeColor === "object" && strokeColor?.getPattern) {
+        const lineWidth = this.getSinglePixelWidth();
+        ctx.save();
+        ctx.strokeStyle = strokeColor.getPattern(ctx, this, ctx.mozCurrentTransformInverse, _pattern_helper.PathType.STROKE);
+        ctx.lineWidth = Math.max(lineWidth, this.current.lineWidth);
+        ctx.stroke();
+        ctx.restore();
+      } else {
+        const lineWidth = this.getSinglePixelWidth();
+
+        if (lineWidth < 0 && -lineWidth >= this.current.lineWidth) {
+          ctx.save();
+          ctx.resetTransform();
+          ctx.lineWidth = Math.round(this._combinedScaleFactor);
+          ctx.stroke();
+          ctx.restore();
+        } else {
+          ctx.lineWidth = Math.max(lineWidth, this.current.lineWidth);
+          ctx.stroke();
+        }
+      }
+    }
+
+    if (consumePath) {
+      this.consumePath(this.current.getClippedPathBoundingBox());
+    }
+
+    ctx.globalAlpha = this.current.fillAlpha;
+  }
+
+  closeStroke() {
+    this.closePath();
+    this.stroke();
+  }
+
+  fill(consumePath) {
+    consumePath = typeof consumePath !== "undefined" ? consumePath : true;
+    const ctx = this.ctx;
+    const fillColor = this.current.fillColor;
+    const isPatternFill = this.current.patternFill;
+    let needRestore = false;
+
+    if (isPatternFill) {
+      ctx.save();
+      ctx.fillStyle = fillColor.getPattern(ctx, this, ctx.mozCurrentTransformInverse, _pattern_helper.PathType.FILL);
+      needRestore = true;
+    }
+
+    const intersect = this.current.getClippedPathBoundingBox();
+
+    if (this.contentVisible && intersect !== null) {
+      if (this.pendingEOFill) {
+        ctx.fill("evenodd");
+        this.pendingEOFill = false;
+      } else {
+        ctx.fill();
+      }
+    }
+
+    if (needRestore) {
+      ctx.restore();
+    }
+
+    if (consumePath) {
+      this.consumePath(intersect);
+    }
+  }
+
+  eoFill() {
+    this.pendingEOFill = true;
+    this.fill();
+  }
+
+  fillStroke() {
+    this.fill(false);
+    this.stroke(false);
+    this.consumePath();
+  }
+
+  eoFillStroke() {
+    this.pendingEOFill = true;
+    this.fillStroke();
+  }
+
+  closeFillStroke() {
+    this.closePath();
+    this.fillStroke();
+  }
+
+  closeEOFillStroke() {
+    this.pendingEOFill = true;
+    this.closePath();
+    this.fillStroke();
+  }
+
+  endPath() {
+    this.consumePath();
+  }
+
+  clip() {
+    this.pendingClip = NORMAL_CLIP;
+  }
+
+  eoClip() {
+    this.pendingClip = EO_CLIP;
+  }
+
+  beginText() {
+    this.current.textMatrix = _util.IDENTITY_MATRIX;
+    this.current.textMatrixScale = 1;
+    this.current.x = this.current.lineX = 0;
+    this.current.y = this.current.lineY = 0;
+  }
+
+  endText() {
+    const paths = this.pendingTextPaths;
+    const ctx = this.ctx;
+
+    if (paths === undefined) {
+      ctx.beginPath();
+      return;
+    }
+
+    ctx.save();
+    ctx.beginPath();
+
+    for (let i = 0; i < paths.length; i++) {
+      const path = paths[i];
+      ctx.setTransform.apply(ctx, path.transform);
+      ctx.translate(path.x, path.y);
+      path.addToPath(ctx, path.fontSize);
+    }
+
+    ctx.restore();
+    ctx.clip();
+    ctx.beginPath();
+    delete this.pendingTextPaths;
+  }
+
+  setCharSpacing(spacing) {
+    this.current.charSpacing = spacing;
+  }
+
+  setWordSpacing(spacing) {
+    this.current.wordSpacing = spacing;
+  }
+
+  setHScale(scale) {
+    this.current.textHScale = scale / 100;
+  }
+
+  setLeading(leading) {
+    this.current.leading = -leading;
+  }
+
+  setFont(fontRefName, size) {
+    const fontObj = this.commonObjs.get(fontRefName);
+    const current = this.current;
+
+    if (!fontObj) {
+      throw new Error(`Can't find font for ${fontRefName}`);
+    }
+
+    current.fontMatrix = fontObj.fontMatrix || _util.FONT_IDENTITY_MATRIX;
+
+    if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) {
+      (0, _util.warn)("Invalid font matrix for font " + fontRefName);
+    }
+
+    if (size < 0) {
+      size = -size;
+      current.fontDirection = -1;
+    } else {
+      current.fontDirection = 1;
+    }
+
+    this.current.font = fontObj;
+    this.current.fontSize = size;
+
+    if (fontObj.isType3Font) {
+      return;
+    }
+
+    const name = fontObj.loadedName || "sans-serif";
+    let bold = "normal";
+
+    if (fontObj.black) {
+      bold = "900";
+    } else if (fontObj.bold) {
+      bold = "bold";
+    }
+
+    const italic = fontObj.italic ? "italic" : "normal";
+    const typeface = `"${name}", ${fontObj.fallbackName}`;
+    let browserFontSize = size;
+
+    if (size < MIN_FONT_SIZE) {
+      browserFontSize = MIN_FONT_SIZE;
+    } else if (size > MAX_FONT_SIZE) {
+      browserFontSize = MAX_FONT_SIZE;
+    }
+
+    this.current.fontSizeScale = size / browserFontSize;
+    this.ctx.font = `${italic} ${bold} ${browserFontSize}px ${typeface}`;
+  }
+
+  setTextRenderingMode(mode) {
+    this.current.textRenderingMode = mode;
+  }
+
+  setTextRise(rise) {
+    this.current.textRise = rise;
+  }
+
+  moveText(x, y) {
+    this.current.x = this.current.lineX += x;
+    this.current.y = this.current.lineY += y;
+  }
+
+  setLeadingMoveText(x, y) {
+    this.setLeading(-y);
+    this.moveText(x, y);
+  }
+
+  setTextMatrix(a, b, c, d, e, f) {
+    this.current.textMatrix = [a, b, c, d, e, f];
+    this.current.textMatrixScale = Math.hypot(a, b);
+    this.current.x = this.current.lineX = 0;
+    this.current.y = this.current.lineY = 0;
+  }
+
+  nextLine() {
+    this.moveText(0, this.current.leading);
+  }
+
+  paintChar(character, x, y, patternTransform, resetLineWidthToOne) {
+    const ctx = this.ctx;
+    const current = this.current;
+    const font = current.font;
+    const textRenderingMode = current.textRenderingMode;
+    const fontSize = current.fontSize / current.fontSizeScale;
+    const fillStrokeMode = textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK;
+    const isAddToPathSet = !!(textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG);
+    const patternFill = current.patternFill && !font.missingFile;
+    let addToPath;
+
+    if (font.disableFontFace || isAddToPathSet || patternFill) {
+      addToPath = font.getPathGenerator(this.commonObjs, character);
+    }
+
+    if (font.disableFontFace || patternFill) {
+      ctx.save();
+      ctx.translate(x, y);
+      ctx.beginPath();
+      addToPath(ctx, fontSize);
+
+      if (patternTransform) {
+        ctx.setTransform.apply(ctx, patternTransform);
+      }
+
+      if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+        ctx.fill();
+      }
+
+      if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+        if (resetLineWidthToOne) {
+          ctx.resetTransform();
+          ctx.lineWidth = Math.round(this._combinedScaleFactor);
+        }
+
+        ctx.stroke();
+      }
+
+      ctx.restore();
+    } else {
+      if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+        ctx.fillText(character, x, y);
+      }
+
+      if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+        if (resetLineWidthToOne) {
+          ctx.save();
+          ctx.moveTo(x, y);
+          ctx.resetTransform();
+          ctx.lineWidth = Math.round(this._combinedScaleFactor);
+          ctx.strokeText(character, 0, 0);
+          ctx.restore();
+        } else {
+          ctx.strokeText(character, x, y);
+        }
+      }
+    }
+
+    if (isAddToPathSet) {
+      const paths = this.pendingTextPaths || (this.pendingTextPaths = []);
+      paths.push({
+        transform: ctx.mozCurrentTransform,
+        x,
+        y,
+        fontSize,
+        addToPath
+      });
+    }
+  }
+
+  get isFontSubpixelAAEnabled() {
+    const {
+      context: ctx
+    } = this.cachedCanvases.getCanvas("isFontSubpixelAAEnabled", 10, 10);
+    ctx.scale(1.5, 1);
+    ctx.fillText("I", 0, 10);
+    const data = ctx.getImageData(0, 0, 10, 10).data;
+    let enabled = false;
+
+    for (let i = 3; i < data.length; i += 4) {
+      if (data[i] > 0 && data[i] < 255) {
+        enabled = true;
+        break;
+      }
+    }
+
+    return (0, _util.shadow)(this, "isFontSubpixelAAEnabled", enabled);
+  }
+
+  showText(glyphs) {
+    const current = this.current;
+    const font = current.font;
+
+    if (font.isType3Font) {
+      return this.showType3Text(glyphs);
+    }
+
+    const fontSize = current.fontSize;
+
+    if (fontSize === 0) {
+      return undefined;
+    }
+
+    const ctx = this.ctx;
+    const fontSizeScale = current.fontSizeScale;
+    const charSpacing = current.charSpacing;
+    const wordSpacing = current.wordSpacing;
+    const fontDirection = current.fontDirection;
+    const textHScale = current.textHScale * fontDirection;
+    const glyphsLength = glyphs.length;
+    const vertical = font.vertical;
+    const spacingDir = vertical ? 1 : -1;
+    const defaultVMetrics = font.defaultVMetrics;
+    const widthAdvanceScale = fontSize * current.fontMatrix[0];
+    const simpleFillText = current.textRenderingMode === _util.TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill;
+    ctx.save();
+    ctx.transform.apply(ctx, current.textMatrix);
+    ctx.translate(current.x, current.y + current.textRise);
+
+    if (fontDirection > 0) {
+      ctx.scale(textHScale, -1);
+    } else {
+      ctx.scale(textHScale, 1);
+    }
+
+    let patternTransform;
+
+    if (current.patternFill) {
+      ctx.save();
+      const pattern = current.fillColor.getPattern(ctx, this, ctx.mozCurrentTransformInverse, _pattern_helper.PathType.FILL);
+      patternTransform = ctx.mozCurrentTransform;
+      ctx.restore();
+      ctx.fillStyle = pattern;
+    }
+
+    let lineWidth = current.lineWidth;
+    let resetLineWidthToOne = false;
+    const scale = current.textMatrixScale;
+
+    if (scale === 0 || lineWidth === 0) {
+      const fillStrokeMode = current.textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK;
+
+      if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+        this._cachedGetSinglePixelWidth = null;
+        lineWidth = this.getSinglePixelWidth();
+        resetLineWidthToOne = lineWidth < 0;
+      }
+    } else {
+      lineWidth /= scale;
+    }
+
+    if (fontSizeScale !== 1.0) {
+      ctx.scale(fontSizeScale, fontSizeScale);
+      lineWidth /= fontSizeScale;
+    }
+
+    ctx.lineWidth = lineWidth;
+    let x = 0,
+        i;
+
+    for (i = 0; i < glyphsLength; ++i) {
+      const glyph = glyphs[i];
+
+      if ((0, _util.isNum)(glyph)) {
+        x += spacingDir * glyph * fontSize / 1000;
+        continue;
+      }
+
+      let restoreNeeded = false;
+      const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
+      const character = glyph.fontChar;
+      const accent = glyph.accent;
+      let scaledX, scaledY;
+      let width = glyph.width;
+
+      if (vertical) {
+        const vmetric = glyph.vmetric || defaultVMetrics;
+        const vx = -(glyph.vmetric ? vmetric[1] : width * 0.5) * widthAdvanceScale;
+        const vy = vmetric[2] * widthAdvanceScale;
+        width = vmetric ? -vmetric[0] : width;
+        scaledX = vx / fontSizeScale;
+        scaledY = (x + vy) / fontSizeScale;
+      } else {
+        scaledX = x / fontSizeScale;
+        scaledY = 0;
+      }
+
+      if (font.remeasure && width > 0) {
+        const measuredWidth = ctx.measureText(character).width * 1000 / fontSize * fontSizeScale;
+
+        if (width < measuredWidth && this.isFontSubpixelAAEnabled) {
+          const characterScaleX = width / measuredWidth;
+          restoreNeeded = true;
+          ctx.save();
+          ctx.scale(characterScaleX, 1);
+          scaledX /= characterScaleX;
+        } else if (width !== measuredWidth) {
+          scaledX += (width - measuredWidth) / 2000 * fontSize / fontSizeScale;
+        }
+      }
+
+      if (this.contentVisible && (glyph.isInFont || font.missingFile)) {
+        if (simpleFillText && !accent) {
+          ctx.fillText(character, scaledX, scaledY);
+        } else {
+          this.paintChar(character, scaledX, scaledY, patternTransform, resetLineWidthToOne);
+
+          if (accent) {
+            const scaledAccentX = scaledX + fontSize * accent.offset.x / fontSizeScale;
+            const scaledAccentY = scaledY - fontSize * accent.offset.y / fontSizeScale;
+            this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY, patternTransform, resetLineWidthToOne);
+          }
+        }
+      }
+
+      let charWidth;
+
+      if (vertical) {
+        charWidth = width * widthAdvanceScale - spacing * fontDirection;
+      } else {
+        charWidth = width * widthAdvanceScale + spacing * fontDirection;
+      }
+
+      x += charWidth;
+
+      if (restoreNeeded) {
+        ctx.restore();
+      }
+    }
+
+    if (vertical) {
+      current.y -= x;
+    } else {
+      current.x += x * textHScale;
+    }
+
+    ctx.restore();
+    this.compose();
+    return undefined;
+  }
+
+  showType3Text(glyphs) {
+    const ctx = this.ctx;
+    const current = this.current;
+    const font = current.font;
+    const fontSize = current.fontSize;
+    const fontDirection = current.fontDirection;
+    const spacingDir = font.vertical ? 1 : -1;
+    const charSpacing = current.charSpacing;
+    const wordSpacing = current.wordSpacing;
+    const textHScale = current.textHScale * fontDirection;
+    const fontMatrix = current.fontMatrix || _util.FONT_IDENTITY_MATRIX;
+    const glyphsLength = glyphs.length;
+    const isTextInvisible = current.textRenderingMode === _util.TextRenderingMode.INVISIBLE;
+    let i, glyph, width, spacingLength;
+
+    if (isTextInvisible || fontSize === 0) {
+      return;
+    }
+
+    this._cachedGetSinglePixelWidth = null;
+    ctx.save();
+    ctx.transform.apply(ctx, current.textMatrix);
+    ctx.translate(current.x, current.y);
+    ctx.scale(textHScale, fontDirection);
+
+    for (i = 0; i < glyphsLength; ++i) {
+      glyph = glyphs[i];
+
+      if ((0, _util.isNum)(glyph)) {
+        spacingLength = spacingDir * glyph * fontSize / 1000;
+        this.ctx.translate(spacingLength, 0);
+        current.x += spacingLength * textHScale;
+        continue;
+      }
+
+      const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
+      const operatorList = font.charProcOperatorList[glyph.operatorListId];
+
+      if (!operatorList) {
+        (0, _util.warn)(`Type3 character "${glyph.operatorListId}" is not available.`);
+        continue;
+      }
+
+      if (this.contentVisible) {
+        this.processingType3 = glyph;
+        this.save();
+        ctx.scale(fontSize, fontSize);
+        ctx.transform.apply(ctx, fontMatrix);
+        this.executeOperatorList(operatorList);
+        this.restore();
+      }
+
+      const transformed = _util.Util.applyTransform([glyph.width, 0], fontMatrix);
+
+      width = transformed[0] * fontSize + spacing;
+      ctx.translate(width, 0);
+      current.x += width * textHScale;
+    }
+
+    ctx.restore();
+    this.processingType3 = null;
+  }
+
+  setCharWidth(xWidth, yWidth) {}
+
+  setCharWidthAndBounds(xWidth, yWidth, llx, lly, urx, ury) {
+    this.ctx.rect(llx, lly, urx - llx, ury - lly);
+    this.clip();
+    this.endPath();
+  }
+
+  getColorN_Pattern(IR) {
+    let pattern;
+
+    if (IR[0] === "TilingPattern") {
+      const color = IR[1];
+      const baseTransform = this.baseTransform || this.ctx.mozCurrentTransform.slice();
+      const canvasGraphicsFactory = {
+        createCanvasGraphics: ctx => {
+          return new CanvasGraphics(ctx, this.commonObjs, this.objs, this.canvasFactory);
+        }
+      };
+      pattern = new _pattern_helper.TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform);
+    } else {
+      pattern = this._getPattern(IR[1], IR[2]);
+    }
+
+    return pattern;
+  }
+
+  setStrokeColorN() {
+    this.current.strokeColor = this.getColorN_Pattern(arguments);
+  }
+
+  setFillColorN() {
+    this.current.fillColor = this.getColorN_Pattern(arguments);
+    this.current.patternFill = true;
+  }
+
+  setStrokeRGBColor(r, g, b) {
+    const color = _util.Util.makeHexColor(r, g, b);
+
+    this.ctx.strokeStyle = color;
+    this.current.strokeColor = color;
+  }
+
+  setFillRGBColor(r, g, b) {
+    const color = _util.Util.makeHexColor(r, g, b);
+
+    this.ctx.fillStyle = color;
+    this.current.fillColor = color;
+    this.current.patternFill = false;
+  }
+
+  _getPattern(objId, matrix = null) {
+    let pattern;
+
+    if (this.cachedPatterns.has(objId)) {
+      pattern = this.cachedPatterns.get(objId);
+    } else {
+      pattern = (0, _pattern_helper.getShadingPattern)(this.objs.get(objId));
+      this.cachedPatterns.set(objId, pattern);
+    }
+
+    if (matrix) {
+      pattern.matrix = matrix;
+    }
+
+    return pattern;
+  }
+
+  shadingFill(objId) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    const ctx = this.ctx;
+    this.save();
+
+    const pattern = this._getPattern(objId);
+
+    ctx.fillStyle = pattern.getPattern(ctx, this, ctx.mozCurrentTransformInverse, _pattern_helper.PathType.SHADING);
+    const inv = ctx.mozCurrentTransformInverse;
+
+    if (inv) {
+      const canvas = ctx.canvas;
+      const width = canvas.width;
+      const height = canvas.height;
+
+      const bl = _util.Util.applyTransform([0, 0], inv);
+
+      const br = _util.Util.applyTransform([0, height], inv);
+
+      const ul = _util.Util.applyTransform([width, 0], inv);
+
+      const ur = _util.Util.applyTransform([width, height], inv);
+
+      const x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
+      const y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
+      const x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
+      const y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
+      this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
+    } else {
+      this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
+    }
+
+    this.compose(this.current.getClippedPathBoundingBox());
+    this.restore();
+  }
+
+  beginInlineImage() {
+    (0, _util.unreachable)("Should not call beginInlineImage");
+  }
+
+  beginImageData() {
+    (0, _util.unreachable)("Should not call beginImageData");
+  }
+
+  paintFormXObjectBegin(matrix, bbox) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    this.save();
+    this.baseTransformStack.push(this.baseTransform);
+
+    if (Array.isArray(matrix) && matrix.length === 6) {
+      this.transform.apply(this, matrix);
+    }
+
+    this.baseTransform = this.ctx.mozCurrentTransform;
+
+    if (bbox) {
+      const width = bbox[2] - bbox[0];
+      const height = bbox[3] - bbox[1];
+      this.ctx.rect(bbox[0], bbox[1], width, height);
+      this.current.updatePathMinMax(this.ctx.mozCurrentTransform, bbox[0], bbox[1]);
+      this.current.updatePathMinMax(this.ctx.mozCurrentTransform, bbox[2], bbox[3]);
+      this.clip();
+      this.endPath();
+    }
+  }
+
+  paintFormXObjectEnd() {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    this.restore();
+    this.baseTransform = this.baseTransformStack.pop();
+  }
+
+  beginGroup(group) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    this.save();
+    const suspendedCtx = this.suspendedCtx;
+
+    if (this.current.activeSMask) {
+      this.suspendedCtx = null;
+      this.current.activeSMask = null;
+    }
+
+    const currentCtx = this.ctx;
+
+    if (!group.isolated) {
+      (0, _util.info)("TODO: Support non-isolated groups.");
+    }
+
+    if (group.knockout) {
+      (0, _util.warn)("Knockout groups not supported.");
+    }
+
+    const currentTransform = currentCtx.mozCurrentTransform;
+
+    if (group.matrix) {
+      currentCtx.transform.apply(currentCtx, group.matrix);
+    }
+
+    if (!group.bbox) {
+      throw new Error("Bounding box is required.");
+    }
+
+    let bounds = _util.Util.getAxialAlignedBoundingBox(group.bbox, currentCtx.mozCurrentTransform);
+
+    const canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height];
+    bounds = _util.Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0];
+    const offsetX = Math.floor(bounds[0]);
+    const offsetY = Math.floor(bounds[1]);
+    let drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1);
+    let drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1);
+    let scaleX = 1,
+        scaleY = 1;
+
+    if (drawnWidth > MAX_GROUP_SIZE) {
+      scaleX = drawnWidth / MAX_GROUP_SIZE;
+      drawnWidth = MAX_GROUP_SIZE;
+    }
+
+    if (drawnHeight > MAX_GROUP_SIZE) {
+      scaleY = drawnHeight / MAX_GROUP_SIZE;
+      drawnHeight = MAX_GROUP_SIZE;
+    }
+
+    this.current.startNewPathAndClipBox([0, 0, drawnWidth, drawnHeight]);
+    let cacheId = "groupAt" + this.groupLevel;
+
+    if (group.smask) {
+      cacheId += "_smask_" + this.smaskCounter++ % 2;
+    }
+
+    const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight, true);
+    const groupCtx = scratchCanvas.context;
+    groupCtx.scale(1 / scaleX, 1 / scaleY);
+    groupCtx.translate(-offsetX, -offsetY);
+    groupCtx.transform.apply(groupCtx, currentTransform);
+
+    if (group.smask) {
+      this.smaskStack.push({
+        canvas: scratchCanvas.canvas,
+        context: groupCtx,
+        offsetX,
+        offsetY,
+        scaleX,
+        scaleY,
+        subtype: group.smask.subtype,
+        backdrop: group.smask.backdrop,
+        transferMap: group.smask.transferMap || null,
+        startTransformInverse: null
+      });
+    } else {
+      currentCtx.setTransform(1, 0, 0, 1, 0, 0);
+      currentCtx.translate(offsetX, offsetY);
+      currentCtx.scale(scaleX, scaleY);
+      currentCtx.save();
+    }
+
+    copyCtxState(currentCtx, groupCtx);
+    this.ctx = groupCtx;
+    this.setGState([["BM", "source-over"], ["ca", 1], ["CA", 1]]);
+    this.groupStack.push({
+      ctx: currentCtx,
+      suspendedCtx
+    });
+    this.groupLevel++;
+  }
+
+  endGroup(group) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    this.groupLevel--;
+    const groupCtx = this.ctx;
+    const {
+      ctx,
+      suspendedCtx
+    } = this.groupStack.pop();
+    this.ctx = ctx;
+    this.ctx.imageSmoothingEnabled = false;
+
+    if (suspendedCtx) {
+      this.suspendedCtx = suspendedCtx;
+    }
+
+    if (group.smask) {
+      this.tempSMask = this.smaskStack.pop();
+      this.restore();
+    } else {
+      this.ctx.restore();
+      const currentMtx = this.ctx.mozCurrentTransform;
+      this.restore();
+      this.ctx.save();
+      this.ctx.setTransform.apply(this.ctx, currentMtx);
+
+      const dirtyBox = _util.Util.getAxialAlignedBoundingBox([0, 0, groupCtx.canvas.width, groupCtx.canvas.height], currentMtx);
+
+      this.ctx.drawImage(groupCtx.canvas, 0, 0);
+      this.ctx.restore();
+      this.compose(dirtyBox);
+    }
+  }
+
+  beginAnnotations() {
+    this.save();
+
+    if (this.baseTransform) {
+      this.ctx.setTransform.apply(this.ctx, this.baseTransform);
+    }
+  }
+
+  endAnnotations() {
+    this.restore();
+  }
+
+  beginAnnotation(id, rect, transform, matrix, hasOwnCanvas) {
+    this.save();
+
+    if (Array.isArray(rect) && rect.length === 4) {
+      const width = rect[2] - rect[0];
+      const height = rect[3] - rect[1];
+
+      if (hasOwnCanvas && this.annotationCanvasMap) {
+        transform = transform.slice();
+        transform[4] -= rect[0];
+        transform[5] -= rect[1];
+        rect = rect.slice();
+        rect[0] = rect[1] = 0;
+        rect[2] = width;
+        rect[3] = height;
+
+        const [scaleX, scaleY] = _util.Util.singularValueDecompose2dScale(this.ctx.mozCurrentTransform);
+
+        const {
+          viewportScale
+        } = this;
+        const canvasWidth = Math.ceil(width * this.outputScaleX * viewportScale);
+        const canvasHeight = Math.ceil(height * this.outputScaleY * viewportScale);
+        this.annotationCanvas = this.canvasFactory.create(canvasWidth, canvasHeight);
+        const {
+          canvas,
+          context
+        } = this.annotationCanvas;
+        canvas.style.width = `calc(${width}px * var(--viewport-scale-factor))`;
+        canvas.style.height = `calc(${height}px * var(--viewport-scale-factor))`;
+        this.annotationCanvasMap.set(id, canvas);
+        this.annotationCanvas.savedCtx = this.ctx;
+        this.ctx = context;
+        this.ctx.setTransform(scaleX, 0, 0, -scaleY, 0, height * scaleY);
+        addContextCurrentTransform(this.ctx);
+        resetCtxToDefault(this.ctx);
+      } else {
+        resetCtxToDefault(this.ctx);
+        this.ctx.rect(rect[0], rect[1], width, height);
+        this.clip();
+        this.endPath();
+      }
+    }
+
+    this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height);
+    this.transform.apply(this, transform);
+    this.transform.apply(this, matrix);
+  }
+
+  endAnnotation() {
+    if (this.annotationCanvas) {
+      this.ctx = this.annotationCanvas.savedCtx;
+      delete this.annotationCanvas.savedCtx;
+      delete this.annotationCanvas;
+    }
+
+    this.restore();
+  }
+
+  paintImageMaskXObject(img) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    const ctx = this.ctx;
+    const width = img.width,
+          height = img.height;
+    const glyph = this.processingType3;
+
+    if (COMPILE_TYPE3_GLYPHS && glyph && glyph.compiled === undefined) {
+      if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) {
+        glyph.compiled = compileType3Glyph({
+          data: img.data,
+          width,
+          height
+        });
+      } else {
+        glyph.compiled = null;
+      }
+    }
+
+    if (glyph?.compiled) {
+      glyph.compiled(ctx);
+      return;
+    }
+
+    const mask = this._createMaskCanvas(img);
+
+    const maskCanvas = mask.canvas;
+    ctx.save();
+    ctx.setTransform(1, 0, 0, 1, 0, 0);
+    ctx.drawImage(maskCanvas, mask.offsetX, mask.offsetY);
+    ctx.restore();
+    this.compose();
+  }
+
+  paintImageMaskXObjectRepeat(imgData, scaleX, skewX = 0, skewY = 0, scaleY, positions) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    const ctx = this.ctx;
+    ctx.save();
+    const currentTransform = ctx.mozCurrentTransform;
+    ctx.transform(scaleX, skewX, skewY, scaleY, 0, 0);
+
+    const mask = this._createMaskCanvas(imgData);
+
+    ctx.setTransform(1, 0, 0, 1, 0, 0);
+
+    for (let i = 0, ii = positions.length; i < ii; i += 2) {
+      const trans = _util.Util.transform(currentTransform, [scaleX, skewX, skewY, scaleY, positions[i], positions[i + 1]]);
+
+      const [x, y] = _util.Util.applyTransform([0, 0], trans);
+
+      ctx.drawImage(mask.canvas, x, y);
+    }
+
+    ctx.restore();
+    this.compose();
+  }
+
+  paintImageMaskXObjectGroup(images) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    const ctx = this.ctx;
+    const fillColor = this.current.fillColor;
+    const isPatternFill = this.current.patternFill;
+
+    for (let i = 0, ii = images.length; i < ii; i++) {
+      const image = images[i];
+      const width = image.width,
+            height = image.height;
+      const maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height);
+      const maskCtx = maskCanvas.context;
+      maskCtx.save();
+      putBinaryImageMask(maskCtx, image);
+      maskCtx.globalCompositeOperation = "source-in";
+      maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, ctx.mozCurrentTransformInverse, _pattern_helper.PathType.FILL) : fillColor;
+      maskCtx.fillRect(0, 0, width, height);
+      maskCtx.restore();
+      ctx.save();
+      ctx.transform.apply(ctx, image.transform);
+      ctx.scale(1, -1);
+      ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
+      ctx.restore();
+    }
+
+    this.compose();
+  }
+
+  paintImageXObject(objId) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    const imgData = objId.startsWith("g_") ? this.commonObjs.get(objId) : this.objs.get(objId);
+
+    if (!imgData) {
+      (0, _util.warn)("Dependent image isn't ready yet");
+      return;
+    }
+
+    this.paintInlineImageXObject(imgData);
+  }
+
+  paintImageXObjectRepeat(objId, scaleX, scaleY, positions) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    const imgData = objId.startsWith("g_") ? this.commonObjs.get(objId) : this.objs.get(objId);
+
+    if (!imgData) {
+      (0, _util.warn)("Dependent image isn't ready yet");
+      return;
+    }
+
+    const width = imgData.width;
+    const height = imgData.height;
+    const map = [];
+
+    for (let i = 0, ii = positions.length; i < ii; i += 2) {
+      map.push({
+        transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]],
+        x: 0,
+        y: 0,
+        w: width,
+        h: height
+      });
+    }
+
+    this.paintInlineImageXObjectGroup(imgData, map);
+  }
+
+  paintInlineImageXObject(imgData) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    const width = imgData.width;
+    const height = imgData.height;
+    const ctx = this.ctx;
+    this.save();
+    ctx.scale(1 / width, -1 / height);
+    let imgToPaint;
+
+    if (typeof HTMLElement === "function" && imgData instanceof HTMLElement || !imgData.data) {
+      imgToPaint = imgData;
+    } else {
+      const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height);
+      const tmpCtx = tmpCanvas.context;
+      putBinaryImageData(tmpCtx, imgData, this.current.transferMaps);
+      imgToPaint = tmpCanvas.canvas;
+    }
+
+    const scaled = this._scaleImage(imgToPaint, ctx.mozCurrentTransformInverse);
+
+    ctx.imageSmoothingEnabled = getImageSmoothingEnabled(ctx.mozCurrentTransform, imgData.interpolate);
+    ctx.drawImage(scaled.img, 0, 0, scaled.paintWidth, scaled.paintHeight, 0, -height, width, height);
+
+    if (this.imageLayer) {
+      const position = this.getCanvasPosition(0, -height);
+      this.imageLayer.appendImage({
+        imgData,
+        left: position[0],
+        top: position[1],
+        width: width / ctx.mozCurrentTransformInverse[0],
+        height: height / ctx.mozCurrentTransformInverse[3]
+      });
+    }
+
+    this.compose();
+    this.restore();
+  }
+
+  paintInlineImageXObjectGroup(imgData, map) {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    const ctx = this.ctx;
+    const w = imgData.width;
+    const h = imgData.height;
+    const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", w, h);
+    const tmpCtx = tmpCanvas.context;
+    putBinaryImageData(tmpCtx, imgData, this.current.transferMaps);
+
+    for (let i = 0, ii = map.length; i < ii; i++) {
+      const entry = map[i];
+      ctx.save();
+      ctx.transform.apply(ctx, entry.transform);
+      ctx.scale(1, -1);
+      ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1);
+
+      if (this.imageLayer) {
+        const position = this.getCanvasPosition(entry.x, entry.y);
+        this.imageLayer.appendImage({
+          imgData,
+          left: position[0],
+          top: position[1],
+          width: w,
+          height: h
+        });
+      }
+
+      ctx.restore();
+    }
+
+    this.compose();
+  }
+
+  paintSolidColorImageMask() {
+    if (!this.contentVisible) {
+      return;
+    }
+
+    this.ctx.fillRect(0, 0, 1, 1);
+    this.compose();
+  }
+
+  markPoint(tag) {}
+
+  markPointProps(tag, properties) {}
+
+  beginMarkedContent(tag) {
+    this.markedContentStack.push({
+      visible: true
+    });
+  }
+
+  beginMarkedContentProps(tag, properties) {
+    if (tag === "OC") {
+      this.markedContentStack.push({
+        visible: this.optionalContentConfig.isVisible(properties)
+      });
+    } else {
+      this.markedContentStack.push({
+        visible: true
+      });
+    }
+
+    this.contentVisible = this.isContentVisible();
+  }
+
+  endMarkedContent() {
+    this.markedContentStack.pop();
+    this.contentVisible = this.isContentVisible();
+  }
+
+  beginCompat() {}
+
+  endCompat() {}
+
+  consumePath(clipBox) {
+    if (this.pendingClip) {
+      this.current.updateClipFromPath();
+    }
+
+    if (!this.pendingClip) {
+      this.compose(clipBox);
+    }
+
+    const ctx = this.ctx;
+
+    if (this.pendingClip) {
+      if (this.pendingClip === EO_CLIP) {
+        ctx.clip("evenodd");
+      } else {
+        ctx.clip();
+      }
+
+      this.pendingClip = null;
+    }
+
+    this.current.startNewPathAndClipBox(this.current.clipBox);
+    ctx.beginPath();
+  }
+
+  getSinglePixelWidth() {
+    if (this._cachedGetSinglePixelWidth === null) {
+      const m = this.ctx.mozCurrentTransform;
+      const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]);
+      const sqNorm1 = m[0] ** 2 + m[2] ** 2;
+      const sqNorm2 = m[1] ** 2 + m[3] ** 2;
+      const pixelHeight = Math.sqrt(Math.max(sqNorm1, sqNorm2)) / absDet;
+
+      if (sqNorm1 !== sqNorm2 && this._combinedScaleFactor * pixelHeight > 1) {
+        this._cachedGetSinglePixelWidth = -(this._combinedScaleFactor * pixelHeight);
+      } else if (absDet > Number.EPSILON) {
+        this._cachedGetSinglePixelWidth = pixelHeight;
+      } else {
+        this._cachedGetSinglePixelWidth = 1;
+      }
+    }
+
+    return this._cachedGetSinglePixelWidth;
+  }
+
+  getCanvasPosition(x, y) {
+    const transform = this.ctx.mozCurrentTransform;
+    return [transform[0] * x + transform[2] * y + transform[4], transform[1] * x + transform[3] * y + transform[5]];
+  }
+
+  isContentVisible() {
+    for (let i = this.markedContentStack.length - 1; i >= 0; i--) {
+      if (!this.markedContentStack[i].visible) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+}
+
+exports.CanvasGraphics = CanvasGraphics;
+
+for (const op in _util.OPS) {
+  if (CanvasGraphics.prototype[op] !== undefined) {
+    CanvasGraphics.prototype[_util.OPS[op]] = CanvasGraphics.prototype[op];
+  }
+}
+
+/***/ }),
+/* 11 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.TilingPattern = exports.PathType = void 0;
+exports.getShadingPattern = getShadingPattern;
+
+var _util = __w_pdfjs_require__(2);
+
+const PathType = {
+  FILL: "Fill",
+  STROKE: "Stroke",
+  SHADING: "Shading"
+};
+exports.PathType = PathType;
+
+function applyBoundingBox(ctx, bbox) {
+  if (!bbox || typeof Path2D === "undefined") {
+    return;
+  }
+
+  const width = bbox[2] - bbox[0];
+  const height = bbox[3] - bbox[1];
+  const region = new Path2D();
+  region.rect(bbox[0], bbox[1], width, height);
+  ctx.clip(region);
+}
+
+class BaseShadingPattern {
+  constructor() {
+    if (this.constructor === BaseShadingPattern) {
+      (0, _util.unreachable)("Cannot initialize BaseShadingPattern.");
+    }
+  }
+
+  getPattern() {
+    (0, _util.unreachable)("Abstract method `getPattern` called.");
+  }
+
+}
+
+class RadialAxialShadingPattern extends BaseShadingPattern {
+  constructor(IR) {
+    super();
+    this._type = IR[1];
+    this._bbox = IR[2];
+    this._colorStops = IR[3];
+    this._p0 = IR[4];
+    this._p1 = IR[5];
+    this._r0 = IR[6];
+    this._r1 = IR[7];
+    this.matrix = null;
+  }
+
+  _createGradient(ctx) {
+    let grad;
+
+    if (this._type === "axial") {
+      grad = ctx.createLinearGradient(this._p0[0], this._p0[1], this._p1[0], this._p1[1]);
+    } else if (this._type === "radial") {
+      grad = ctx.createRadialGradient(this._p0[0], this._p0[1], this._r0, this._p1[0], this._p1[1], this._r1);
+    }
+
+    for (const colorStop of this._colorStops) {
+      grad.addColorStop(colorStop[0], colorStop[1]);
+    }
+
+    return grad;
+  }
+
+  getPattern(ctx, owner, inverse, pathType) {
+    let pattern;
+
+    if (pathType === PathType.STROKE || pathType === PathType.FILL) {
+      const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, ctx.mozCurrentTransform) || [0, 0, 0, 0];
+      const width = Math.ceil(ownerBBox[2] - ownerBBox[0]) || 1;
+      const height = Math.ceil(ownerBBox[3] - ownerBBox[1]) || 1;
+      const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", width, height, true);
+      const tmpCtx = tmpCanvas.context;
+      tmpCtx.clearRect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height);
+      tmpCtx.beginPath();
+      tmpCtx.rect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height);
+      tmpCtx.translate(-ownerBBox[0], -ownerBBox[1]);
+      inverse = _util.Util.transform(inverse, [1, 0, 0, 1, ownerBBox[0], ownerBBox[1]]);
+      tmpCtx.transform.apply(tmpCtx, owner.baseTransform);
+
+      if (this.matrix) {
+        tmpCtx.transform.apply(tmpCtx, this.matrix);
+      }
+
+      applyBoundingBox(tmpCtx, this._bbox);
+      tmpCtx.fillStyle = this._createGradient(tmpCtx);
+      tmpCtx.fill();
+      pattern = ctx.createPattern(tmpCanvas.canvas, "no-repeat");
+      const domMatrix = new DOMMatrix(inverse);
+
+      try {
+        pattern.setTransform(domMatrix);
+      } catch (ex) {
+        (0, _util.warn)(`RadialAxialShadingPattern.getPattern: "${ex?.message}".`);
+      }
+    } else {
+      applyBoundingBox(ctx, this._bbox);
+      pattern = this._createGradient(ctx);
+    }
+
+    return pattern;
+  }
+
+}
+
+function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
+  const coords = context.coords,
+        colors = context.colors;
+  const bytes = data.data,
+        rowSize = data.width * 4;
+  let tmp;
+
+  if (coords[p1 + 1] > coords[p2 + 1]) {
+    tmp = p1;
+    p1 = p2;
+    p2 = tmp;
+    tmp = c1;
+    c1 = c2;
+    c2 = tmp;
+  }
+
+  if (coords[p2 + 1] > coords[p3 + 1]) {
+    tmp = p2;
+    p2 = p3;
+    p3 = tmp;
+    tmp = c2;
+    c2 = c3;
+    c3 = tmp;
+  }
+
+  if (coords[p1 + 1] > coords[p2 + 1]) {
+    tmp = p1;
+    p1 = p2;
+    p2 = tmp;
+    tmp = c1;
+    c1 = c2;
+    c2 = tmp;
+  }
+
+  const x1 = (coords[p1] + context.offsetX) * context.scaleX;
+  const y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
+  const x2 = (coords[p2] + context.offsetX) * context.scaleX;
+  const y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY;
+  const x3 = (coords[p3] + context.offsetX) * context.scaleX;
+  const y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY;
+
+  if (y1 >= y3) {
+    return;
+  }
+
+  const c1r = colors[c1],
+        c1g = colors[c1 + 1],
+        c1b = colors[c1 + 2];
+  const c2r = colors[c2],
+        c2g = colors[c2 + 1],
+        c2b = colors[c2 + 2];
+  const c3r = colors[c3],
+        c3g = colors[c3 + 1],
+        c3b = colors[c3 + 2];
+  const minY = Math.round(y1),
+        maxY = Math.round(y3);
+  let xa, car, cag, cab;
+  let xb, cbr, cbg, cbb;
+
+  for (let y = minY; y <= maxY; y++) {
+    if (y < y2) {
+      let k;
+
+      if (y < y1) {
+        k = 0;
+      } else {
+        k = (y1 - y) / (y1 - y2);
+      }
+
+      xa = x1 - (x1 - x2) * k;
+      car = c1r - (c1r - c2r) * k;
+      cag = c1g - (c1g - c2g) * k;
+      cab = c1b - (c1b - c2b) * k;
+    } else {
+      let k;
+
+      if (y > y3) {
+        k = 1;
+      } else if (y2 === y3) {
+        k = 0;
+      } else {
+        k = (y2 - y) / (y2 - y3);
+      }
+
+      xa = x2 - (x2 - x3) * k;
+      car = c2r - (c2r - c3r) * k;
+      cag = c2g - (c2g - c3g) * k;
+      cab = c2b - (c2b - c3b) * k;
+    }
+
+    let k;
+
+    if (y < y1) {
+      k = 0;
+    } else if (y > y3) {
+      k = 1;
+    } else {
+      k = (y1 - y) / (y1 - y3);
+    }
+
+    xb = x1 - (x1 - x3) * k;
+    cbr = c1r - (c1r - c3r) * k;
+    cbg = c1g - (c1g - c3g) * k;
+    cbb = c1b - (c1b - c3b) * k;
+    const x1_ = Math.round(Math.min(xa, xb));
+    const x2_ = Math.round(Math.max(xa, xb));
+    let j = rowSize * y + x1_ * 4;
+
+    for (let x = x1_; x <= x2_; x++) {
+      k = (xa - x) / (xa - xb);
+
+      if (k < 0) {
+        k = 0;
+      } else if (k > 1) {
+        k = 1;
+      }
+
+      bytes[j++] = car - (car - cbr) * k | 0;
+      bytes[j++] = cag - (cag - cbg) * k | 0;
+      bytes[j++] = cab - (cab - cbb) * k | 0;
+      bytes[j++] = 255;
+    }
+  }
+}
+
+function drawFigure(data, figure, context) {
+  const ps = figure.coords;
+  const cs = figure.colors;
+  let i, ii;
+
+  switch (figure.type) {
+    case "lattice":
+      const verticesPerRow = figure.verticesPerRow;
+      const rows = Math.floor(ps.length / verticesPerRow) - 1;
+      const cols = verticesPerRow - 1;
+
+      for (i = 0; i < rows; i++) {
+        let q = i * verticesPerRow;
+
+        for (let j = 0; j < cols; j++, q++) {
+          drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]);
+          drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]);
+        }
+      }
+
+      break;
+
+    case "triangles":
+      for (i = 0, ii = ps.length; i < ii; i += 3) {
+        drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]);
+      }
+
+      break;
+
+    default:
+      throw new Error("illegal figure");
+  }
+}
+
+class MeshShadingPattern extends BaseShadingPattern {
+  constructor(IR) {
+    super();
+    this._coords = IR[2];
+    this._colors = IR[3];
+    this._figures = IR[4];
+    this._bounds = IR[5];
+    this._bbox = IR[7];
+    this._background = IR[8];
+    this.matrix = null;
+  }
+
+  _createMeshCanvas(combinedScale, backgroundColor, cachedCanvases) {
+    const EXPECTED_SCALE = 1.1;
+    const MAX_PATTERN_SIZE = 3000;
+    const BORDER_SIZE = 2;
+    const offsetX = Math.floor(this._bounds[0]);
+    const offsetY = Math.floor(this._bounds[1]);
+    const boundsWidth = Math.ceil(this._bounds[2]) - offsetX;
+    const boundsHeight = Math.ceil(this._bounds[3]) - offsetY;
+    const width = Math.min(Math.ceil(Math.abs(boundsWidth * combinedScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
+    const height = Math.min(Math.ceil(Math.abs(boundsHeight * combinedScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
+    const scaleX = boundsWidth / width;
+    const scaleY = boundsHeight / height;
+    const context = {
+      coords: this._coords,
+      colors: this._colors,
+      offsetX: -offsetX,
+      offsetY: -offsetY,
+      scaleX: 1 / scaleX,
+      scaleY: 1 / scaleY
+    };
+    const paddedWidth = width + BORDER_SIZE * 2;
+    const paddedHeight = height + BORDER_SIZE * 2;
+    const tmpCanvas = cachedCanvases.getCanvas("mesh", paddedWidth, paddedHeight, false);
+    const tmpCtx = tmpCanvas.context;
+    const data = tmpCtx.createImageData(width, height);
+
+    if (backgroundColor) {
+      const bytes = data.data;
+
+      for (let i = 0, ii = bytes.length; i < ii; i += 4) {
+        bytes[i] = backgroundColor[0];
+        bytes[i + 1] = backgroundColor[1];
+        bytes[i + 2] = backgroundColor[2];
+        bytes[i + 3] = 255;
+      }
+    }
+
+    for (const figure of this._figures) {
+      drawFigure(data, figure, context);
+    }
+
+    tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE);
+    const canvas = tmpCanvas.canvas;
+    return {
+      canvas,
+      offsetX: offsetX - BORDER_SIZE * scaleX,
+      offsetY: offsetY - BORDER_SIZE * scaleY,
+      scaleX,
+      scaleY
+    };
+  }
+
+  getPattern(ctx, owner, inverse, pathType) {
+    applyBoundingBox(ctx, this._bbox);
+    let scale;
+
+    if (pathType === PathType.SHADING) {
+      scale = _util.Util.singularValueDecompose2dScale(ctx.mozCurrentTransform);
+    } else {
+      scale = _util.Util.singularValueDecompose2dScale(owner.baseTransform);
+
+      if (this.matrix) {
+        const matrixScale = _util.Util.singularValueDecompose2dScale(this.matrix);
+
+        scale = [scale[0] * matrixScale[0], scale[1] * matrixScale[1]];
+      }
+    }
+
+    const temporaryPatternCanvas = this._createMeshCanvas(scale, pathType === PathType.SHADING ? null : this._background, owner.cachedCanvases);
+
+    if (pathType !== PathType.SHADING) {
+      ctx.setTransform.apply(ctx, owner.baseTransform);
+
+      if (this.matrix) {
+        ctx.transform.apply(ctx, this.matrix);
+      }
+    }
+
+    ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
+    ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY);
+    return ctx.createPattern(temporaryPatternCanvas.canvas, "no-repeat");
+  }
+
+}
+
+class DummyShadingPattern extends BaseShadingPattern {
+  getPattern() {
+    return "hotpink";
+  }
+
+}
+
+function getShadingPattern(IR) {
+  switch (IR[0]) {
+    case "RadialAxial":
+      return new RadialAxialShadingPattern(IR);
+
+    case "Mesh":
+      return new MeshShadingPattern(IR);
+
+    case "Dummy":
+      return new DummyShadingPattern();
+  }
+
+  throw new Error(`Unknown IR type: ${IR[0]}`);
+}
+
+const PaintType = {
+  COLORED: 1,
+  UNCOLORED: 2
+};
+
+class TilingPattern {
+  static get MAX_PATTERN_SIZE() {
+    return (0, _util.shadow)(this, "MAX_PATTERN_SIZE", 3000);
+  }
+
+  constructor(IR, color, ctx, canvasGraphicsFactory, baseTransform) {
+    this.operatorList = IR[2];
+    this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
+    this.bbox = IR[4];
+    this.xstep = IR[5];
+    this.ystep = IR[6];
+    this.paintType = IR[7];
+    this.tilingType = IR[8];
+    this.color = color;
+    this.ctx = ctx;
+    this.canvasGraphicsFactory = canvasGraphicsFactory;
+    this.baseTransform = baseTransform;
+  }
+
+  createPatternCanvas(owner) {
+    const operatorList = this.operatorList;
+    const bbox = this.bbox;
+    const xstep = this.xstep;
+    const ystep = this.ystep;
+    const paintType = this.paintType;
+    const tilingType = this.tilingType;
+    const color = this.color;
+    const canvasGraphicsFactory = this.canvasGraphicsFactory;
+    (0, _util.info)("TilingType: " + tilingType);
+    const x0 = bbox[0],
+          y0 = bbox[1],
+          x1 = bbox[2],
+          y1 = bbox[3];
+
+    const matrixScale = _util.Util.singularValueDecompose2dScale(this.matrix);
+
+    const curMatrixScale = _util.Util.singularValueDecompose2dScale(this.baseTransform);
+
+    const combinedScale = [matrixScale[0] * curMatrixScale[0], matrixScale[1] * curMatrixScale[1]];
+    const dimx = this.getSizeAndScale(xstep, this.ctx.canvas.width, combinedScale[0]);
+    const dimy = this.getSizeAndScale(ystep, this.ctx.canvas.height, combinedScale[1]);
+    const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", dimx.size, dimy.size, true);
+    const tmpCtx = tmpCanvas.context;
+    const graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);
+    graphics.groupLevel = owner.groupLevel;
+    this.setFillAndStrokeStyleToContext(graphics, paintType, color);
+    let adjustedX0 = x0;
+    let adjustedY0 = y0;
+    let adjustedX1 = x1;
+    let adjustedY1 = y1;
+
+    if (x0 < 0) {
+      adjustedX0 = 0;
+      adjustedX1 += Math.abs(x0);
+    }
+
+    if (y0 < 0) {
+      adjustedY0 = 0;
+      adjustedY1 += Math.abs(y0);
+    }
+
+    tmpCtx.translate(-(dimx.scale * adjustedX0), -(dimy.scale * adjustedY0));
+    graphics.transform(dimx.scale, 0, 0, dimy.scale, 0, 0);
+    this.clipBbox(graphics, adjustedX0, adjustedY0, adjustedX1, adjustedY1);
+    graphics.baseTransform = graphics.ctx.mozCurrentTransform.slice();
+    graphics.executeOperatorList(operatorList);
+    graphics.endDrawing();
+    return {
+      canvas: tmpCanvas.canvas,
+      scaleX: dimx.scale,
+      scaleY: dimy.scale,
+      offsetX: adjustedX0,
+      offsetY: adjustedY0
+    };
+  }
+
+  getSizeAndScale(step, realOutputSize, scale) {
+    step = Math.abs(step);
+    const maxSize = Math.max(TilingPattern.MAX_PATTERN_SIZE, realOutputSize);
+    let size = Math.ceil(step * scale);
+
+    if (size >= maxSize) {
+      size = maxSize;
+    } else {
+      scale = size / step;
+    }
+
+    return {
+      scale,
+      size
+    };
+  }
+
+  clipBbox(graphics, x0, y0, x1, y1) {
+    const bboxWidth = x1 - x0;
+    const bboxHeight = y1 - y0;
+    graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight);
+    graphics.clip();
+    graphics.endPath();
+  }
+
+  setFillAndStrokeStyleToContext(graphics, paintType, color) {
+    const context = graphics.ctx,
+          current = graphics.current;
+
+    switch (paintType) {
+      case PaintType.COLORED:
+        const ctx = this.ctx;
+        context.fillStyle = ctx.fillStyle;
+        context.strokeStyle = ctx.strokeStyle;
+        current.fillColor = ctx.fillStyle;
+        current.strokeColor = ctx.strokeStyle;
+        break;
+
+      case PaintType.UNCOLORED:
+        const cssColor = _util.Util.makeHexColor(color[0], color[1], color[2]);
+
+        context.fillStyle = cssColor;
+        context.strokeStyle = cssColor;
+        current.fillColor = cssColor;
+        current.strokeColor = cssColor;
+        break;
+
+      default:
+        throw new _util.FormatError(`Unsupported paint type: ${paintType}`);
+    }
+  }
+
+  getPattern(ctx, owner, inverse, pathType) {
+    let matrix = inverse;
+
+    if (pathType !== PathType.SHADING) {
+      matrix = _util.Util.transform(matrix, owner.baseTransform);
+
+      if (this.matrix) {
+        matrix = _util.Util.transform(matrix, this.matrix);
+      }
+    }
+
+    const temporaryPatternCanvas = this.createPatternCanvas(owner);
+    let domMatrix = new DOMMatrix(matrix);
+    domMatrix = domMatrix.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
+    domMatrix = domMatrix.scale(1 / temporaryPatternCanvas.scaleX, 1 / temporaryPatternCanvas.scaleY);
+    const pattern = ctx.createPattern(temporaryPatternCanvas.canvas, "repeat");
+
+    try {
+      pattern.setTransform(domMatrix);
+    } catch (ex) {
+      (0, _util.warn)(`TilingPattern.getPattern: "${ex?.message}".`);
+    }
+
+    return pattern;
+  }
+
+}
+
+exports.TilingPattern = TilingPattern;
+
+/***/ }),
+/* 12 */
+/***/ ((__unused_webpack_module, exports) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.GlobalWorkerOptions = void 0;
+const GlobalWorkerOptions = Object.create(null);
+exports.GlobalWorkerOptions = GlobalWorkerOptions;
+GlobalWorkerOptions.workerPort = GlobalWorkerOptions.workerPort === undefined ? null : GlobalWorkerOptions.workerPort;
+GlobalWorkerOptions.workerSrc = GlobalWorkerOptions.workerSrc === undefined ? "" : GlobalWorkerOptions.workerSrc;
+
+/***/ }),
+/* 13 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.MessageHandler = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+const CallbackKind = {
+  UNKNOWN: 0,
+  DATA: 1,
+  ERROR: 2
+};
+const StreamKind = {
+  UNKNOWN: 0,
+  CANCEL: 1,
+  CANCEL_COMPLETE: 2,
+  CLOSE: 3,
+  ENQUEUE: 4,
+  ERROR: 5,
+  PULL: 6,
+  PULL_COMPLETE: 7,
+  START_COMPLETE: 8
+};
+
+function wrapReason(reason) {
+  if (!(reason instanceof Error || typeof reason === "object" && reason !== null)) {
+    (0, _util.warn)('wrapReason: Expected "reason" to be a (possibly cloned) Error.');
+    return reason;
+  }
+
+  switch (reason.name) {
+    case "AbortException":
+      return new _util.AbortException(reason.message);
+
+    case "MissingPDFException":
+      return new _util.MissingPDFException(reason.message);
+
+    case "PasswordException":
+      return new _util.PasswordException(reason.message, reason.code);
+
+    case "UnexpectedResponseException":
+      return new _util.UnexpectedResponseException(reason.message, reason.status);
+
+    case "UnknownErrorException":
+      return new _util.UnknownErrorException(reason.message, reason.details);
+
+    default:
+      return new _util.UnknownErrorException(reason.message, reason.toString());
+  }
+}
+
+class MessageHandler {
+  constructor(sourceName, targetName, comObj) {
+    this.sourceName = sourceName;
+    this.targetName = targetName;
+    this.comObj = comObj;
+    this.callbackId = 1;
+    this.streamId = 1;
+    this.streamSinks = Object.create(null);
+    this.streamControllers = Object.create(null);
+    this.callbackCapabilities = Object.create(null);
+    this.actionHandler = Object.create(null);
+
+    this._onComObjOnMessage = event => {
+      const data = event.data;
+
+      if (data.targetName !== this.sourceName) {
+        return;
+      }
+
+      if (data.stream) {
+        this._processStreamMessage(data);
+
+        return;
+      }
+
+      if (data.callback) {
+        const callbackId = data.callbackId;
+        const capability = this.callbackCapabilities[callbackId];
+
+        if (!capability) {
+          throw new Error(`Cannot resolve callback ${callbackId}`);
+        }
+
+        delete this.callbackCapabilities[callbackId];
+
+        if (data.callback === CallbackKind.DATA) {
+          capability.resolve(data.data);
+        } else if (data.callback === CallbackKind.ERROR) {
+          capability.reject(wrapReason(data.reason));
+        } else {
+          throw new Error("Unexpected callback case");
+        }
+
+        return;
+      }
+
+      const action = this.actionHandler[data.action];
+
+      if (!action) {
+        throw new Error(`Unknown action from worker: ${data.action}`);
+      }
+
+      if (data.callbackId) {
+        const cbSourceName = this.sourceName;
+        const cbTargetName = data.sourceName;
+        new Promise(function (resolve) {
+          resolve(action(data.data));
+        }).then(function (result) {
+          comObj.postMessage({
+            sourceName: cbSourceName,
+            targetName: cbTargetName,
+            callback: CallbackKind.DATA,
+            callbackId: data.callbackId,
+            data: result
+          });
+        }, function (reason) {
+          comObj.postMessage({
+            sourceName: cbSourceName,
+            targetName: cbTargetName,
+            callback: CallbackKind.ERROR,
+            callbackId: data.callbackId,
+            reason: wrapReason(reason)
+          });
+        });
+        return;
+      }
+
+      if (data.streamId) {
+        this._createStreamSink(data);
+
+        return;
+      }
+
+      action(data.data);
+    };
+
+    comObj.addEventListener("message", this._onComObjOnMessage);
+  }
+
+  on(actionName, handler) {
+    const ah = this.actionHandler;
+
+    if (ah[actionName]) {
+      throw new Error(`There is already an actionName called "${actionName}"`);
+    }
+
+    ah[actionName] = handler;
+  }
+
+  send(actionName, data, transfers) {
+    this.comObj.postMessage({
+      sourceName: this.sourceName,
+      targetName: this.targetName,
+      action: actionName,
+      data
+    }, transfers);
+  }
+
+  sendWithPromise(actionName, data, transfers) {
+    const callbackId = this.callbackId++;
+    const capability = (0, _util.createPromiseCapability)();
+    this.callbackCapabilities[callbackId] = capability;
+
+    try {
+      this.comObj.postMessage({
+        sourceName: this.sourceName,
+        targetName: this.targetName,
+        action: actionName,
+        callbackId,
+        data
+      }, transfers);
+    } catch (ex) {
+      capability.reject(ex);
+    }
+
+    return capability.promise;
+  }
+
+  sendWithStream(actionName, data, queueingStrategy, transfers) {
+    const streamId = this.streamId++,
+          sourceName = this.sourceName,
+          targetName = this.targetName,
+          comObj = this.comObj;
+    return new ReadableStream({
+      start: controller => {
+        const startCapability = (0, _util.createPromiseCapability)();
+        this.streamControllers[streamId] = {
+          controller,
+          startCall: startCapability,
+          pullCall: null,
+          cancelCall: null,
+          isClosed: false
+        };
+        comObj.postMessage({
+          sourceName,
+          targetName,
+          action: actionName,
+          streamId,
+          data,
+          desiredSize: controller.desiredSize
+        }, transfers);
+        return startCapability.promise;
+      },
+      pull: controller => {
+        const pullCapability = (0, _util.createPromiseCapability)();
+        this.streamControllers[streamId].pullCall = pullCapability;
+        comObj.postMessage({
+          sourceName,
+          targetName,
+          stream: StreamKind.PULL,
+          streamId,
+          desiredSize: controller.desiredSize
+        });
+        return pullCapability.promise;
+      },
+      cancel: reason => {
+        (0, _util.assert)(reason instanceof Error, "cancel must have a valid reason");
+        const cancelCapability = (0, _util.createPromiseCapability)();
+        this.streamControllers[streamId].cancelCall = cancelCapability;
+        this.streamControllers[streamId].isClosed = true;
+        comObj.postMessage({
+          sourceName,
+          targetName,
+          stream: StreamKind.CANCEL,
+          streamId,
+          reason: wrapReason(reason)
+        });
+        return cancelCapability.promise;
+      }
+    }, queueingStrategy);
+  }
+
+  _createStreamSink(data) {
+    const streamId = data.streamId,
+          sourceName = this.sourceName,
+          targetName = data.sourceName,
+          comObj = this.comObj;
+    const self = this,
+          action = this.actionHandler[data.action];
+    const streamSink = {
+      enqueue(chunk, size = 1, transfers) {
+        if (this.isCancelled) {
+          return;
+        }
+
+        const lastDesiredSize = this.desiredSize;
+        this.desiredSize -= size;
+
+        if (lastDesiredSize > 0 && this.desiredSize <= 0) {
+          this.sinkCapability = (0, _util.createPromiseCapability)();
+          this.ready = this.sinkCapability.promise;
+        }
+
+        comObj.postMessage({
+          sourceName,
+          targetName,
+          stream: StreamKind.ENQUEUE,
+          streamId,
+          chunk
+        }, transfers);
+      },
+
+      close() {
+        if (this.isCancelled) {
+          return;
+        }
+
+        this.isCancelled = true;
+        comObj.postMessage({
+          sourceName,
+          targetName,
+          stream: StreamKind.CLOSE,
+          streamId
+        });
+        delete self.streamSinks[streamId];
+      },
+
+      error(reason) {
+        (0, _util.assert)(reason instanceof Error, "error must have a valid reason");
+
+        if (this.isCancelled) {
+          return;
+        }
+
+        this.isCancelled = true;
+        comObj.postMessage({
+          sourceName,
+          targetName,
+          stream: StreamKind.ERROR,
+          streamId,
+          reason: wrapReason(reason)
+        });
+      },
+
+      sinkCapability: (0, _util.createPromiseCapability)(),
+      onPull: null,
+      onCancel: null,
+      isCancelled: false,
+      desiredSize: data.desiredSize,
+      ready: null
+    };
+    streamSink.sinkCapability.resolve();
+    streamSink.ready = streamSink.sinkCapability.promise;
+    this.streamSinks[streamId] = streamSink;
+    new Promise(function (resolve) {
+      resolve(action(data.data, streamSink));
+    }).then(function () {
+      comObj.postMessage({
+        sourceName,
+        targetName,
+        stream: StreamKind.START_COMPLETE,
+        streamId,
+        success: true
+      });
+    }, function (reason) {
+      comObj.postMessage({
+        sourceName,
+        targetName,
+        stream: StreamKind.START_COMPLETE,
+        streamId,
+        reason: wrapReason(reason)
+      });
+    });
+  }
+
+  _processStreamMessage(data) {
+    const streamId = data.streamId,
+          sourceName = this.sourceName,
+          targetName = data.sourceName,
+          comObj = this.comObj;
+    const streamController = this.streamControllers[streamId],
+          streamSink = this.streamSinks[streamId];
+
+    switch (data.stream) {
+      case StreamKind.START_COMPLETE:
+        if (data.success) {
+          streamController.startCall.resolve();
+        } else {
+          streamController.startCall.reject(wrapReason(data.reason));
+        }
+
+        break;
+
+      case StreamKind.PULL_COMPLETE:
+        if (data.success) {
+          streamController.pullCall.resolve();
+        } else {
+          streamController.pullCall.reject(wrapReason(data.reason));
+        }
+
+        break;
+
+      case StreamKind.PULL:
+        if (!streamSink) {
+          comObj.postMessage({
+            sourceName,
+            targetName,
+            stream: StreamKind.PULL_COMPLETE,
+            streamId,
+            success: true
+          });
+          break;
+        }
+
+        if (streamSink.desiredSize <= 0 && data.desiredSize > 0) {
+          streamSink.sinkCapability.resolve();
+        }
+
+        streamSink.desiredSize = data.desiredSize;
+        new Promise(function (resolve) {
+          resolve(streamSink.onPull && streamSink.onPull());
+        }).then(function () {
+          comObj.postMessage({
+            sourceName,
+            targetName,
+            stream: StreamKind.PULL_COMPLETE,
+            streamId,
+            success: true
+          });
+        }, function (reason) {
+          comObj.postMessage({
+            sourceName,
+            targetName,
+            stream: StreamKind.PULL_COMPLETE,
+            streamId,
+            reason: wrapReason(reason)
+          });
+        });
+        break;
+
+      case StreamKind.ENQUEUE:
+        (0, _util.assert)(streamController, "enqueue should have stream controller");
+
+        if (streamController.isClosed) {
+          break;
+        }
+
+        streamController.controller.enqueue(data.chunk);
+        break;
+
+      case StreamKind.CLOSE:
+        (0, _util.assert)(streamController, "close should have stream controller");
+
+        if (streamController.isClosed) {
+          break;
+        }
+
+        streamController.isClosed = true;
+        streamController.controller.close();
+
+        this._deleteStreamController(streamController, streamId);
+
+        break;
+
+      case StreamKind.ERROR:
+        (0, _util.assert)(streamController, "error should have stream controller");
+        streamController.controller.error(wrapReason(data.reason));
+
+        this._deleteStreamController(streamController, streamId);
+
+        break;
+
+      case StreamKind.CANCEL_COMPLETE:
+        if (data.success) {
+          streamController.cancelCall.resolve();
+        } else {
+          streamController.cancelCall.reject(wrapReason(data.reason));
+        }
+
+        this._deleteStreamController(streamController, streamId);
+
+        break;
+
+      case StreamKind.CANCEL:
+        if (!streamSink) {
+          break;
+        }
+
+        new Promise(function (resolve) {
+          resolve(streamSink.onCancel && streamSink.onCancel(wrapReason(data.reason)));
+        }).then(function () {
+          comObj.postMessage({
+            sourceName,
+            targetName,
+            stream: StreamKind.CANCEL_COMPLETE,
+            streamId,
+            success: true
+          });
+        }, function (reason) {
+          comObj.postMessage({
+            sourceName,
+            targetName,
+            stream: StreamKind.CANCEL_COMPLETE,
+            streamId,
+            reason: wrapReason(reason)
+          });
+        });
+        streamSink.sinkCapability.reject(wrapReason(data.reason));
+        streamSink.isCancelled = true;
+        delete this.streamSinks[streamId];
+        break;
+
+      default:
+        throw new Error("Unexpected stream case");
+    }
+  }
+
+  async _deleteStreamController(streamController, streamId) {
+    await Promise.allSettled([streamController.startCall && streamController.startCall.promise, streamController.pullCall && streamController.pullCall.promise, streamController.cancelCall && streamController.cancelCall.promise]);
+    delete this.streamControllers[streamId];
+  }
+
+  destroy() {
+    this.comObj.removeEventListener("message", this._onComObjOnMessage);
+  }
+
+}
+
+exports.MessageHandler = MessageHandler;
+
+/***/ }),
+/* 14 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.Metadata = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+class Metadata {
+  #metadataMap;
+  #data;
+
+  constructor({
+    parsedData,
+    rawData
+  }) {
+    this.#metadataMap = parsedData;
+    this.#data = rawData;
+  }
+
+  getRaw() {
+    return this.#data;
+  }
+
+  get(name) {
+    return this.#metadataMap.get(name) ?? null;
+  }
+
+  getAll() {
+    return (0, _util.objectFromMap)(this.#metadataMap);
+  }
+
+  has(name) {
+    return this.#metadataMap.has(name);
+  }
+
+}
+
+exports.Metadata = Metadata;
+
+/***/ }),
+/* 15 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.OptionalContentConfig = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+class OptionalContentGroup {
+  constructor(name, intent) {
+    this.visible = true;
+    this.name = name;
+    this.intent = intent;
+  }
+
+}
+
+class OptionalContentConfig {
+  constructor(data) {
+    this.name = null;
+    this.creator = null;
+    this._order = null;
+    this._groups = new Map();
+
+    if (data === null) {
+      return;
+    }
+
+    this.name = data.name;
+    this.creator = data.creator;
+    this._order = data.order;
+
+    for (const group of data.groups) {
+      this._groups.set(group.id, new OptionalContentGroup(group.name, group.intent));
+    }
+
+    if (data.baseState === "OFF") {
+      for (const group of this._groups) {
+        group.visible = false;
+      }
+    }
+
+    for (const on of data.on) {
+      this._groups.get(on).visible = true;
+    }
+
+    for (const off of data.off) {
+      this._groups.get(off).visible = false;
+    }
+  }
+
+  _evaluateVisibilityExpression(array) {
+    const length = array.length;
+
+    if (length < 2) {
+      return true;
+    }
+
+    const operator = array[0];
+
+    for (let i = 1; i < length; i++) {
+      const element = array[i];
+      let state;
+
+      if (Array.isArray(element)) {
+        state = this._evaluateVisibilityExpression(element);
+      } else if (this._groups.has(element)) {
+        state = this._groups.get(element).visible;
+      } else {
+        (0, _util.warn)(`Optional content group not found: ${element}`);
+        return true;
+      }
+
+      switch (operator) {
+        case "And":
+          if (!state) {
+            return false;
+          }
+
+          break;
+
+        case "Or":
+          if (state) {
+            return true;
+          }
+
+          break;
+
+        case "Not":
+          return !state;
+
+        default:
+          return true;
+      }
+    }
+
+    return operator === "And";
+  }
+
+  isVisible(group) {
+    if (this._groups.size === 0) {
+      return true;
+    }
+
+    if (!group) {
+      (0, _util.warn)("Optional content group not defined.");
+      return true;
+    }
+
+    if (group.type === "OCG") {
+      if (!this._groups.has(group.id)) {
+        (0, _util.warn)(`Optional content group not found: ${group.id}`);
+        return true;
+      }
+
+      return this._groups.get(group.id).visible;
+    } else if (group.type === "OCMD") {
+      if (group.expression) {
+        return this._evaluateVisibilityExpression(group.expression);
+      }
+
+      if (!group.policy || group.policy === "AnyOn") {
+        for (const id of group.ids) {
+          if (!this._groups.has(id)) {
+            (0, _util.warn)(`Optional content group not found: ${id}`);
+            return true;
+          }
+
+          if (this._groups.get(id).visible) {
+            return true;
+          }
+        }
+
+        return false;
+      } else if (group.policy === "AllOn") {
+        for (const id of group.ids) {
+          if (!this._groups.has(id)) {
+            (0, _util.warn)(`Optional content group not found: ${id}`);
+            return true;
+          }
+
+          if (!this._groups.get(id).visible) {
+            return false;
+          }
+        }
+
+        return true;
+      } else if (group.policy === "AnyOff") {
+        for (const id of group.ids) {
+          if (!this._groups.has(id)) {
+            (0, _util.warn)(`Optional content group not found: ${id}`);
+            return true;
+          }
+
+          if (!this._groups.get(id).visible) {
+            return true;
+          }
+        }
+
+        return false;
+      } else if (group.policy === "AllOff") {
+        for (const id of group.ids) {
+          if (!this._groups.has(id)) {
+            (0, _util.warn)(`Optional content group not found: ${id}`);
+            return true;
+          }
+
+          if (this._groups.get(id).visible) {
+            return false;
+          }
+        }
+
+        return true;
+      }
+
+      (0, _util.warn)(`Unknown optional content policy ${group.policy}.`);
+      return true;
+    }
+
+    (0, _util.warn)(`Unknown group type ${group.type}.`);
+    return true;
+  }
+
+  setVisibility(id, visible = true) {
+    if (!this._groups.has(id)) {
+      (0, _util.warn)(`Optional content group not found: ${id}`);
+      return;
+    }
+
+    this._groups.get(id).visible = !!visible;
+  }
+
+  getOrder() {
+    if (!this._groups.size) {
+      return null;
+    }
+
+    if (this._order) {
+      return this._order.slice();
+    }
+
+    return Array.from(this._groups.keys());
+  }
+
+  getGroups() {
+    return this._groups.size > 0 ? (0, _util.objectFromMap)(this._groups) : null;
+  }
+
+  getGroup(id) {
+    return this._groups.get(id) || null;
+  }
+
+}
+
+exports.OptionalContentConfig = OptionalContentConfig;
+
+/***/ }),
+/* 16 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.PDFDataTransportStream = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+var _display_utils = __w_pdfjs_require__(1);
+
+class PDFDataTransportStream {
+  constructor(params, pdfDataRangeTransport) {
+    (0, _util.assert)(pdfDataRangeTransport, 'PDFDataTransportStream - missing required "pdfDataRangeTransport" argument.');
+    this._queuedChunks = [];
+    this._progressiveDone = params.progressiveDone || false;
+    this._contentDispositionFilename = params.contentDispositionFilename || null;
+    const initialData = params.initialData;
+
+    if (initialData?.length > 0) {
+      const buffer = new Uint8Array(initialData).buffer;
+
+      this._queuedChunks.push(buffer);
+    }
+
+    this._pdfDataRangeTransport = pdfDataRangeTransport;
+    this._isStreamingSupported = !params.disableStream;
+    this._isRangeSupported = !params.disableRange;
+    this._contentLength = params.length;
+    this._fullRequestReader = null;
+    this._rangeReaders = [];
+
+    this._pdfDataRangeTransport.addRangeListener((begin, chunk) => {
+      this._onReceiveData({
+        begin,
+        chunk
+      });
+    });
+
+    this._pdfDataRangeTransport.addProgressListener((loaded, total) => {
+      this._onProgress({
+        loaded,
+        total
+      });
+    });
+
+    this._pdfDataRangeTransport.addProgressiveReadListener(chunk => {
+      this._onReceiveData({
+        chunk
+      });
+    });
+
+    this._pdfDataRangeTransport.addProgressiveDoneListener(() => {
+      this._onProgressiveDone();
+    });
+
+    this._pdfDataRangeTransport.transportReady();
+  }
+
+  _onReceiveData(args) {
+    const buffer = new Uint8Array(args.chunk).buffer;
+
+    if (args.begin === undefined) {
+      if (this._fullRequestReader) {
+        this._fullRequestReader._enqueue(buffer);
+      } else {
+        this._queuedChunks.push(buffer);
+      }
+    } else {
+      const found = this._rangeReaders.some(function (rangeReader) {
+        if (rangeReader._begin !== args.begin) {
+          return false;
+        }
+
+        rangeReader._enqueue(buffer);
+
+        return true;
+      });
+
+      (0, _util.assert)(found, "_onReceiveData - no `PDFDataTransportStreamRangeReader` instance found.");
+    }
+  }
+
+  get _progressiveDataLength() {
+    return this._fullRequestReader?._loaded ?? 0;
+  }
+
+  _onProgress(evt) {
+    if (evt.total === undefined) {
+      const firstReader = this._rangeReaders[0];
+
+      if (firstReader?.onProgress) {
+        firstReader.onProgress({
+          loaded: evt.loaded
+        });
+      }
+    } else {
+      const fullReader = this._fullRequestReader;
+
+      if (fullReader?.onProgress) {
+        fullReader.onProgress({
+          loaded: evt.loaded,
+          total: evt.total
+        });
+      }
+    }
+  }
+
+  _onProgressiveDone() {
+    if (this._fullRequestReader) {
+      this._fullRequestReader.progressiveDone();
+    }
+
+    this._progressiveDone = true;
+  }
+
+  _removeRangeReader(reader) {
+    const i = this._rangeReaders.indexOf(reader);
+
+    if (i >= 0) {
+      this._rangeReaders.splice(i, 1);
+    }
+  }
+
+  getFullReader() {
+    (0, _util.assert)(!this._fullRequestReader, "PDFDataTransportStream.getFullReader can only be called once.");
+    const queuedChunks = this._queuedChunks;
+    this._queuedChunks = null;
+    return new PDFDataTransportStreamReader(this, queuedChunks, this._progressiveDone, this._contentDispositionFilename);
+  }
+
+  getRangeReader(begin, end) {
+    if (end <= this._progressiveDataLength) {
+      return null;
+    }
+
+    const reader = new PDFDataTransportStreamRangeReader(this, begin, end);
+
+    this._pdfDataRangeTransport.requestDataRange(begin, end);
+
+    this._rangeReaders.push(reader);
+
+    return reader;
+  }
+
+  cancelAllRequests(reason) {
+    if (this._fullRequestReader) {
+      this._fullRequestReader.cancel(reason);
+    }
+
+    for (const reader of this._rangeReaders.slice(0)) {
+      reader.cancel(reason);
+    }
+
+    this._pdfDataRangeTransport.abort();
+  }
+
+}
+
+exports.PDFDataTransportStream = PDFDataTransportStream;
+
+class PDFDataTransportStreamReader {
+  constructor(stream, queuedChunks, progressiveDone = false, contentDispositionFilename = null) {
+    this._stream = stream;
+    this._done = progressiveDone || false;
+    this._filename = (0, _display_utils.isPdfFile)(contentDispositionFilename) ? contentDispositionFilename : null;
+    this._queuedChunks = queuedChunks || [];
+    this._loaded = 0;
+
+    for (const chunk of this._queuedChunks) {
+      this._loaded += chunk.byteLength;
+    }
+
+    this._requests = [];
+    this._headersReady = Promise.resolve();
+    stream._fullRequestReader = this;
+    this.onProgress = null;
+  }
+
+  _enqueue(chunk) {
+    if (this._done) {
+      return;
+    }
+
+    if (this._requests.length > 0) {
+      const requestCapability = this._requests.shift();
+
+      requestCapability.resolve({
+        value: chunk,
+        done: false
+      });
+    } else {
+      this._queuedChunks.push(chunk);
+    }
+
+    this._loaded += chunk.byteLength;
+  }
+
+  get headersReady() {
+    return this._headersReady;
+  }
+
+  get filename() {
+    return this._filename;
+  }
+
+  get isRangeSupported() {
+    return this._stream._isRangeSupported;
+  }
+
+  get isStreamingSupported() {
+    return this._stream._isStreamingSupported;
+  }
+
+  get contentLength() {
+    return this._stream._contentLength;
+  }
+
+  async read() {
+    if (this._queuedChunks.length > 0) {
+      const chunk = this._queuedChunks.shift();
+
+      return {
+        value: chunk,
+        done: false
+      };
+    }
+
+    if (this._done) {
+      return {
+        value: undefined,
+        done: true
+      };
+    }
+
+    const requestCapability = (0, _util.createPromiseCapability)();
+
+    this._requests.push(requestCapability);
+
+    return requestCapability.promise;
+  }
+
+  cancel(reason) {
+    this._done = true;
+
+    for (const requestCapability of this._requests) {
+      requestCapability.resolve({
+        value: undefined,
+        done: true
+      });
+    }
+
+    this._requests.length = 0;
+  }
+
+  progressiveDone() {
+    if (this._done) {
+      return;
+    }
+
+    this._done = true;
+  }
+
+}
+
+class PDFDataTransportStreamRangeReader {
+  constructor(stream, begin, end) {
+    this._stream = stream;
+    this._begin = begin;
+    this._end = end;
+    this._queuedChunk = null;
+    this._requests = [];
+    this._done = false;
+    this.onProgress = null;
+  }
+
+  _enqueue(chunk) {
+    if (this._done) {
+      return;
+    }
+
+    if (this._requests.length === 0) {
+      this._queuedChunk = chunk;
+    } else {
+      const requestsCapability = this._requests.shift();
+
+      requestsCapability.resolve({
+        value: chunk,
+        done: false
+      });
+
+      for (const requestCapability of this._requests) {
+        requestCapability.resolve({
+          value: undefined,
+          done: true
+        });
+      }
+
+      this._requests.length = 0;
+    }
+
+    this._done = true;
+
+    this._stream._removeRangeReader(this);
+  }
+
+  get isStreamingSupported() {
+    return false;
+  }
+
+  async read() {
+    if (this._queuedChunk) {
+      const chunk = this._queuedChunk;
+      this._queuedChunk = null;
+      return {
+        value: chunk,
+        done: false
+      };
+    }
+
+    if (this._done) {
+      return {
+        value: undefined,
+        done: true
+      };
+    }
+
+    const requestCapability = (0, _util.createPromiseCapability)();
+
+    this._requests.push(requestCapability);
+
+    return requestCapability.promise;
+  }
+
+  cancel(reason) {
+    this._done = true;
+
+    for (const requestCapability of this._requests) {
+      requestCapability.resolve({
+        value: undefined,
+        done: true
+      });
+    }
+
+    this._requests.length = 0;
+
+    this._stream._removeRangeReader(this);
+  }
+
+}
+
+/***/ }),
+/* 17 */
+/***/ ((__unused_webpack_module, exports) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.XfaText = void 0;
+
+class XfaText {
+  static textContent(xfa) {
+    const items = [];
+    const output = {
+      items,
+      styles: Object.create(null)
+    };
+
+    function walk(node) {
+      if (!node) {
+        return;
+      }
+
+      let str = null;
+      const name = node.name;
+
+      if (name === "#text") {
+        str = node.value;
+      } else if (!XfaText.shouldBuildText(name)) {
+        return;
+      } else if (node?.attributes?.textContent) {
+        str = node.attributes.textContent;
+      } else if (node.value) {
+        str = node.value;
+      }
+
+      if (str !== null) {
+        items.push({
+          str
+        });
+      }
+
+      if (!node.children) {
+        return;
+      }
+
+      for (const child of node.children) {
+        walk(child);
+      }
+    }
+
+    walk(xfa);
+    return output;
+  }
+
+  static shouldBuildText(name) {
+    return !(name === "textarea" || name === "input" || name === "option" || name === "select");
+  }
+
+}
+
+exports.XfaText = XfaText;
+
+/***/ }),
+/* 18 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.AnnotationLayer = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+var _display_utils = __w_pdfjs_require__(1);
+
+var _annotation_storage = __w_pdfjs_require__(9);
+
+var _scripting_utils = __w_pdfjs_require__(19);
+
+var _xfa_layer = __w_pdfjs_require__(20);
+
+const DEFAULT_TAB_INDEX = 1000;
+const GetElementsByNameSet = new WeakSet();
+
+class AnnotationElementFactory {
+  static create(parameters) {
+    const subtype = parameters.data.annotationType;
+
+    switch (subtype) {
+      case _util.AnnotationType.LINK:
+        return new LinkAnnotationElement(parameters);
+
+      case _util.AnnotationType.TEXT:
+        return new TextAnnotationElement(parameters);
+
+      case _util.AnnotationType.WIDGET:
+        const fieldType = parameters.data.fieldType;
+
+        switch (fieldType) {
+          case "Tx":
+            return new TextWidgetAnnotationElement(parameters);
+
+          case "Btn":
+            if (parameters.data.radioButton) {
+              return new RadioButtonWidgetAnnotationElement(parameters);
+            } else if (parameters.data.checkBox) {
+              return new CheckboxWidgetAnnotationElement(parameters);
+            }
+
+            return new PushButtonWidgetAnnotationElement(parameters);
+
+          case "Ch":
+            return new ChoiceWidgetAnnotationElement(parameters);
+        }
+
+        return new WidgetAnnotationElement(parameters);
+
+      case _util.AnnotationType.POPUP:
+        return new PopupAnnotationElement(parameters);
+
+      case _util.AnnotationType.FREETEXT:
+        return new FreeTextAnnotationElement(parameters);
+
+      case _util.AnnotationType.LINE:
+        return new LineAnnotationElement(parameters);
+
+      case _util.AnnotationType.SQUARE:
+        return new SquareAnnotationElement(parameters);
+
+      case _util.AnnotationType.CIRCLE:
+        return new CircleAnnotationElement(parameters);
+
+      case _util.AnnotationType.POLYLINE:
+        return new PolylineAnnotationElement(parameters);
+
+      case _util.AnnotationType.CARET:
+        return new CaretAnnotationElement(parameters);
+
+      case _util.AnnotationType.INK:
+        return new InkAnnotationElement(parameters);
+
+      case _util.AnnotationType.POLYGON:
+        return new PolygonAnnotationElement(parameters);
+
+      case _util.AnnotationType.HIGHLIGHT:
+        return new HighlightAnnotationElement(parameters);
+
+      case _util.AnnotationType.UNDERLINE:
+        return new UnderlineAnnotationElement(parameters);
+
+      case _util.AnnotationType.SQUIGGLY:
+        return new SquigglyAnnotationElement(parameters);
+
+      case _util.AnnotationType.STRIKEOUT:
+        return new StrikeOutAnnotationElement(parameters);
+
+      case _util.AnnotationType.STAMP:
+        return new StampAnnotationElement(parameters);
+
+      case _util.AnnotationType.FILEATTACHMENT:
+        return new FileAttachmentAnnotationElement(parameters);
+
+      default:
+        return new AnnotationElement(parameters);
+    }
+  }
+
+}
+
+class AnnotationElement {
+  constructor(parameters, {
+    isRenderable = false,
+    ignoreBorder = false,
+    createQuadrilaterals = false
+  } = {}) {
+    this.isRenderable = isRenderable;
+    this.data = parameters.data;
+    this.layer = parameters.layer;
+    this.page = parameters.page;
+    this.viewport = parameters.viewport;
+    this.linkService = parameters.linkService;
+    this.downloadManager = parameters.downloadManager;
+    this.imageResourcesPath = parameters.imageResourcesPath;
+    this.renderForms = parameters.renderForms;
+    this.svgFactory = parameters.svgFactory;
+    this.annotationStorage = parameters.annotationStorage;
+    this.enableScripting = parameters.enableScripting;
+    this.hasJSActions = parameters.hasJSActions;
+    this._fieldObjects = parameters.fieldObjects;
+    this._mouseState = parameters.mouseState;
+
+    if (isRenderable) {
+      this.container = this._createContainer(ignoreBorder);
+    }
+
+    if (createQuadrilaterals) {
+      this.quadrilaterals = this._createQuadrilaterals(ignoreBorder);
+    }
+  }
+
+  _createContainer(ignoreBorder = false) {
+    const data = this.data,
+          page = this.page,
+          viewport = this.viewport;
+    const container = document.createElement("section");
+    let width = data.rect[2] - data.rect[0];
+    let height = data.rect[3] - data.rect[1];
+    container.setAttribute("data-annotation-id", data.id);
+
+    const rect = _util.Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]);
+
+    if (data.hasOwnCanvas) {
+      const transform = viewport.transform.slice();
+
+      const [scaleX, scaleY] = _util.Util.singularValueDecompose2dScale(transform);
+
+      width = Math.ceil(width * scaleX);
+      height = Math.ceil(height * scaleY);
+      rect[0] *= scaleX;
+      rect[1] *= scaleY;
+
+      for (let i = 0; i < 4; i++) {
+        transform[i] = Math.sign(transform[i]);
+      }
+
+      container.style.transform = `matrix(${transform.join(",")})`;
+    } else {
+      container.style.transform = `matrix(${viewport.transform.join(",")})`;
+    }
+
+    container.style.transformOrigin = `${-rect[0]}px ${-rect[1]}px`;
+
+    if (!ignoreBorder && data.borderStyle.width > 0) {
+      container.style.borderWidth = `${data.borderStyle.width}px`;
+
+      if (data.borderStyle.style !== _util.AnnotationBorderStyleType.UNDERLINE) {
+        width -= 2 * data.borderStyle.width;
+        height -= 2 * data.borderStyle.width;
+      }
+
+      const horizontalRadius = data.borderStyle.horizontalCornerRadius;
+      const verticalRadius = data.borderStyle.verticalCornerRadius;
+
+      if (horizontalRadius > 0 || verticalRadius > 0) {
+        const radius = `${horizontalRadius}px / ${verticalRadius}px`;
+        container.style.borderRadius = radius;
+      }
+
+      switch (data.borderStyle.style) {
+        case _util.AnnotationBorderStyleType.SOLID:
+          container.style.borderStyle = "solid";
+          break;
+
+        case _util.AnnotationBorderStyleType.DASHED:
+          container.style.borderStyle = "dashed";
+          break;
+
+        case _util.AnnotationBorderStyleType.BEVELED:
+          (0, _util.warn)("Unimplemented border style: beveled");
+          break;
+
+        case _util.AnnotationBorderStyleType.INSET:
+          (0, _util.warn)("Unimplemented border style: inset");
+          break;
+
+        case _util.AnnotationBorderStyleType.UNDERLINE:
+          container.style.borderBottomStyle = "solid";
+          break;
+
+        default:
+          break;
+      }
+
+      const borderColor = data.borderColor || data.color || null;
+
+      if (borderColor) {
+        container.style.borderColor = _util.Util.makeHexColor(data.color[0] | 0, data.color[1] | 0, data.color[2] | 0);
+      } else {
+        container.style.borderWidth = 0;
+      }
+    }
+
+    container.style.left = `${rect[0]}px`;
+    container.style.top = `${rect[1]}px`;
+
+    if (data.hasOwnCanvas) {
+      container.style.width = container.style.height = "auto";
+    } else {
+      container.style.width = `${width}px`;
+      container.style.height = `${height}px`;
+    }
+
+    return container;
+  }
+
+  _createQuadrilaterals(ignoreBorder = false) {
+    if (!this.data.quadPoints) {
+      return null;
+    }
+
+    const quadrilaterals = [];
+    const savedRect = this.data.rect;
+
+    for (const quadPoint of this.data.quadPoints) {
+      this.data.rect = [quadPoint[2].x, quadPoint[2].y, quadPoint[1].x, quadPoint[1].y];
+      quadrilaterals.push(this._createContainer(ignoreBorder));
+    }
+
+    this.data.rect = savedRect;
+    return quadrilaterals;
+  }
+
+  _createPopup(trigger, data) {
+    let container = this.container;
+
+    if (this.quadrilaterals) {
+      trigger = trigger || this.quadrilaterals;
+      container = this.quadrilaterals[0];
+    }
+
+    if (!trigger) {
+      trigger = document.createElement("div");
+      trigger.style.height = container.style.height;
+      trigger.style.width = container.style.width;
+      container.appendChild(trigger);
+    }
+
+    const popupElement = new PopupElement({
+      container,
+      trigger,
+      color: data.color,
+      titleObj: data.titleObj,
+      modificationDate: data.modificationDate,
+      contentsObj: data.contentsObj,
+      richText: data.richText,
+      hideWrapper: true
+    });
+    const popup = popupElement.render();
+    popup.style.left = container.style.width;
+    container.appendChild(popup);
+  }
+
+  _renderQuadrilaterals(className) {
+    for (const quadrilateral of this.quadrilaterals) {
+      quadrilateral.className = className;
+    }
+
+    return this.quadrilaterals;
+  }
+
+  render() {
+    (0, _util.unreachable)("Abstract method `AnnotationElement.render` called");
+  }
+
+  _getElementsByName(name, skipId = null) {
+    const fields = [];
+
+    if (this._fieldObjects) {
+      const fieldObj = this._fieldObjects[name];
+
+      if (fieldObj) {
+        for (const {
+          page,
+          id,
+          exportValues
+        } of fieldObj) {
+          if (page === -1) {
+            continue;
+          }
+
+          if (id === skipId) {
+            continue;
+          }
+
+          const exportValue = typeof exportValues === "string" ? exportValues : null;
+          const domElement = document.getElementById(id);
+
+          if (domElement && !GetElementsByNameSet.has(domElement)) {
+            (0, _util.warn)(`_getElementsByName - element not allowed: ${id}`);
+            continue;
+          }
+
+          fields.push({
+            id,
+            exportValue,
+            domElement
+          });
+        }
+      }
+
+      return fields;
+    }
+
+    for (const domElement of document.getElementsByName(name)) {
+      const {
+        id,
+        exportValue
+      } = domElement;
+
+      if (id === skipId) {
+        continue;
+      }
+
+      if (!GetElementsByNameSet.has(domElement)) {
+        continue;
+      }
+
+      fields.push({
+        id,
+        exportValue,
+        domElement
+      });
+    }
+
+    return fields;
+  }
+
+  static get platform() {
+    const platform = typeof navigator !== "undefined" ? navigator.platform : "";
+    return (0, _util.shadow)(this, "platform", {
+      isWin: platform.includes("Win"),
+      isMac: platform.includes("Mac")
+    });
+  }
+
+}
+
+class LinkAnnotationElement extends AnnotationElement {
+  constructor(parameters, options = null) {
+    const isRenderable = !!(parameters.data.url || parameters.data.dest || parameters.data.action || parameters.data.isTooltipOnly || parameters.data.resetForm || parameters.data.actions && (parameters.data.actions.Action || parameters.data.actions["Mouse Up"] || parameters.data.actions["Mouse Down"]));
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: !!options?.ignoreBorder,
+      createQuadrilaterals: true
+    });
+  }
+
+  render() {
+    const {
+      data,
+      linkService
+    } = this;
+    const link = document.createElement("a");
+
+    if (data.url) {
+      if (!linkService.addLinkAttributes) {
+        (0, _util.warn)("LinkAnnotationElement.render - missing `addLinkAttributes`-method on the `linkService`-instance.");
+      }
+
+      linkService.addLinkAttributes?.(link, data.url, data.newWindow);
+    } else if (data.action) {
+      this._bindNamedAction(link, data.action);
+    } else if (data.dest) {
+      this._bindLink(link, data.dest);
+    } else {
+      let hasClickAction = false;
+
+      if (data.actions && (data.actions.Action || data.actions["Mouse Up"] || data.actions["Mouse Down"]) && this.enableScripting && this.hasJSActions) {
+        hasClickAction = true;
+
+        this._bindJSAction(link, data);
+      }
+
+      if (data.resetForm) {
+        this._bindResetFormAction(link, data.resetForm);
+      } else if (!hasClickAction) {
+        this._bindLink(link, "");
+      }
+    }
+
+    if (this.quadrilaterals) {
+      return this._renderQuadrilaterals("linkAnnotation").map((quadrilateral, index) => {
+        const linkElement = index === 0 ? link : link.cloneNode();
+        quadrilateral.appendChild(linkElement);
+        return quadrilateral;
+      });
+    }
+
+    this.container.className = "linkAnnotation";
+    this.container.appendChild(link);
+    return this.container;
+  }
+
+  _bindLink(link, destination) {
+    link.href = this.linkService.getDestinationHash(destination);
+
+    link.onclick = () => {
+      if (destination) {
+        this.linkService.goToDestination(destination);
+      }
+
+      return false;
+    };
+
+    if (destination || destination === "") {
+      link.className = "internalLink";
+    }
+  }
+
+  _bindNamedAction(link, action) {
+    link.href = this.linkService.getAnchorUrl("");
+
+    link.onclick = () => {
+      this.linkService.executeNamedAction(action);
+      return false;
+    };
+
+    link.className = "internalLink";
+  }
+
+  _bindJSAction(link, data) {
+    link.href = this.linkService.getAnchorUrl("");
+    const map = new Map([["Action", "onclick"], ["Mouse Up", "onmouseup"], ["Mouse Down", "onmousedown"]]);
+
+    for (const name of Object.keys(data.actions)) {
+      const jsName = map.get(name);
+
+      if (!jsName) {
+        continue;
+      }
+
+      link[jsName] = () => {
+        this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+          source: this,
+          detail: {
+            id: data.id,
+            name
+          }
+        });
+        return false;
+      };
+    }
+
+    if (!link.onclick) {
+      link.onclick = () => false;
+    }
+
+    link.className = "internalLink";
+  }
+
+  _bindResetFormAction(link, resetForm) {
+    const otherClickAction = link.onclick;
+
+    if (!otherClickAction) {
+      link.href = this.linkService.getAnchorUrl("");
+    }
+
+    link.className = "internalLink";
+
+    if (!this._fieldObjects) {
+      (0, _util.warn)(`_bindResetFormAction - "resetForm" action not supported, ` + "ensure that the `fieldObjects` parameter is provided.");
+
+      if (!otherClickAction) {
+        link.onclick = () => false;
+      }
+
+      return;
+    }
+
+    link.onclick = () => {
+      if (otherClickAction) {
+        otherClickAction();
+      }
+
+      const {
+        fields: resetFormFields,
+        refs: resetFormRefs,
+        include
+      } = resetForm;
+      const allFields = [];
+
+      if (resetFormFields.length !== 0 || resetFormRefs.length !== 0) {
+        const fieldIds = new Set(resetFormRefs);
+
+        for (const fieldName of resetFormFields) {
+          const fields = this._fieldObjects[fieldName] || [];
+
+          for (const {
+            id
+          } of fields) {
+            fieldIds.add(id);
+          }
+        }
+
+        for (const fields of Object.values(this._fieldObjects)) {
+          for (const field of fields) {
+            if (fieldIds.has(field.id) === include) {
+              allFields.push(field);
+            }
+          }
+        }
+      } else {
+        for (const fields of Object.values(this._fieldObjects)) {
+          allFields.push(...fields);
+        }
+      }
+
+      const storage = this.annotationStorage;
+      const allIds = [];
+
+      for (const field of allFields) {
+        const {
+          id
+        } = field;
+        allIds.push(id);
+
+        switch (field.type) {
+          case "text":
+            {
+              const value = field.defaultValue || "";
+              storage.setValue(id, {
+                value,
+                valueAsString: value
+              });
+              break;
+            }
+
+          case "checkbox":
+          case "radiobutton":
+            {
+              const value = field.defaultValue === field.exportValues;
+              storage.setValue(id, {
+                value
+              });
+              break;
+            }
+
+          case "combobox":
+          case "listbox":
+            {
+              const value = field.defaultValue || "";
+              storage.setValue(id, {
+                value
+              });
+              break;
+            }
+
+          default:
+            continue;
+        }
+
+        const domElement = document.getElementById(id);
+
+        if (!domElement || !GetElementsByNameSet.has(domElement)) {
+          continue;
+        }
+
+        domElement.dispatchEvent(new Event("resetform"));
+      }
+
+      if (this.enableScripting) {
+        this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+          source: this,
+          detail: {
+            id: "app",
+            ids: allIds,
+            name: "ResetForm"
+          }
+        });
+      }
+
+      return false;
+    };
+  }
+
+}
+
+class TextAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable
+    });
+  }
+
+  render() {
+    this.container.className = "textAnnotation";
+    const image = document.createElement("img");
+    image.style.height = this.container.style.height;
+    image.style.width = this.container.style.width;
+    image.src = this.imageResourcesPath + "annotation-" + this.data.name.toLowerCase() + ".svg";
+    image.alt = "[{{type}} Annotation]";
+    image.dataset.l10nId = "text_annotation_type";
+    image.dataset.l10nArgs = JSON.stringify({
+      type: this.data.name
+    });
+
+    if (!this.data.hasPopup) {
+      this._createPopup(image, this.data);
+    }
+
+    this.container.appendChild(image);
+    return this.container;
+  }
+
+}
+
+class WidgetAnnotationElement extends AnnotationElement {
+  render() {
+    if (this.data.alternativeText) {
+      this.container.title = this.data.alternativeText;
+    }
+
+    return this.container;
+  }
+
+  _getKeyModifier(event) {
+    const {
+      isWin,
+      isMac
+    } = AnnotationElement.platform;
+    return isWin && event.ctrlKey || isMac && event.metaKey;
+  }
+
+  _setEventListener(element, baseName, eventName, valueGetter) {
+    if (baseName.includes("mouse")) {
+      element.addEventListener(baseName, event => {
+        this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+          source: this,
+          detail: {
+            id: this.data.id,
+            name: eventName,
+            value: valueGetter(event),
+            shift: event.shiftKey,
+            modifier: this._getKeyModifier(event)
+          }
+        });
+      });
+    } else {
+      element.addEventListener(baseName, event => {
+        this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+          source: this,
+          detail: {
+            id: this.data.id,
+            name: eventName,
+            value: event.target.checked
+          }
+        });
+      });
+    }
+  }
+
+  _setEventListeners(element, names, getter) {
+    for (const [baseName, eventName] of names) {
+      if (eventName === "Action" || this.data.actions?.[eventName]) {
+        this._setEventListener(element, baseName, eventName, getter);
+      }
+    }
+  }
+
+  _setBackgroundColor(element) {
+    const color = this.data.backgroundColor || null;
+    element.style.backgroundColor = color === null ? "transparent" : _util.Util.makeHexColor(color[0], color[1], color[2]);
+  }
+
+  _dispatchEventFromSandbox(actions, jsEvent) {
+    const setColor = (jsName, styleName, event) => {
+      const color = event.detail[jsName];
+      event.target.style[styleName] = _scripting_utils.ColorConverters[`${color[0]}_HTML`](color.slice(1));
+    };
+
+    const commonActions = {
+      display: event => {
+        const hidden = event.detail.display % 2 === 1;
+        event.target.style.visibility = hidden ? "hidden" : "visible";
+        this.annotationStorage.setValue(this.data.id, {
+          hidden,
+          print: event.detail.display === 0 || event.detail.display === 3
+        });
+      },
+      print: event => {
+        this.annotationStorage.setValue(this.data.id, {
+          print: event.detail.print
+        });
+      },
+      hidden: event => {
+        event.target.style.visibility = event.detail.hidden ? "hidden" : "visible";
+        this.annotationStorage.setValue(this.data.id, {
+          hidden: event.detail.hidden
+        });
+      },
+      focus: event => {
+        setTimeout(() => event.target.focus({
+          preventScroll: false
+        }), 0);
+      },
+      userName: event => {
+        event.target.title = event.detail.userName;
+      },
+      readonly: event => {
+        if (event.detail.readonly) {
+          event.target.setAttribute("readonly", "");
+        } else {
+          event.target.removeAttribute("readonly");
+        }
+      },
+      required: event => {
+        if (event.detail.required) {
+          event.target.setAttribute("required", "");
+        } else {
+          event.target.removeAttribute("required");
+        }
+      },
+      bgColor: event => {
+        setColor("bgColor", "backgroundColor", event);
+      },
+      fillColor: event => {
+        setColor("fillColor", "backgroundColor", event);
+      },
+      fgColor: event => {
+        setColor("fgColor", "color", event);
+      },
+      textColor: event => {
+        setColor("textColor", "color", event);
+      },
+      borderColor: event => {
+        setColor("borderColor", "borderColor", event);
+      },
+      strokeColor: event => {
+        setColor("strokeColor", "borderColor", event);
+      }
+    };
+
+    for (const name of Object.keys(jsEvent.detail)) {
+      const action = actions[name] || commonActions[name];
+
+      if (action) {
+        action(jsEvent);
+      }
+    }
+  }
+
+}
+
+class TextWidgetAnnotationElement extends WidgetAnnotationElement {
+  constructor(parameters) {
+    const isRenderable = parameters.renderForms || !parameters.data.hasAppearance && !!parameters.data.fieldValue;
+    super(parameters, {
+      isRenderable
+    });
+  }
+
+  setPropertyOnSiblings(base, key, value, keyInStorage) {
+    const storage = this.annotationStorage;
+
+    for (const element of this._getElementsByName(base.name, base.id)) {
+      if (element.domElement) {
+        element.domElement[key] = value;
+      }
+
+      storage.setValue(element.id, {
+        [keyInStorage]: value
+      });
+    }
+  }
+
+  render() {
+    const storage = this.annotationStorage;
+    const id = this.data.id;
+    this.container.className = "textWidgetAnnotation";
+    let element = null;
+
+    if (this.renderForms) {
+      const storedData = storage.getValue(id, {
+        value: this.data.fieldValue,
+        valueAsString: this.data.fieldValue
+      });
+      const textContent = storedData.valueAsString || storedData.value || "";
+      const elementData = {
+        userValue: null,
+        formattedValue: null,
+        beforeInputSelectionRange: null,
+        beforeInputValue: null
+      };
+
+      if (this.data.multiLine) {
+        element = document.createElement("textarea");
+        element.textContent = textContent;
+      } else {
+        element = document.createElement("input");
+        element.type = "text";
+        element.setAttribute("value", textContent);
+      }
+
+      GetElementsByNameSet.add(element);
+      element.disabled = this.data.readOnly;
+      element.name = this.data.fieldName;
+      element.tabIndex = DEFAULT_TAB_INDEX;
+      elementData.userValue = textContent;
+      element.setAttribute("id", id);
+      element.addEventListener("input", event => {
+        storage.setValue(id, {
+          value: event.target.value
+        });
+        this.setPropertyOnSiblings(element, "value", event.target.value, "value");
+      });
+      element.addEventListener("resetform", event => {
+        const defaultValue = this.data.defaultFieldValue || "";
+        element.value = elementData.userValue = defaultValue;
+        delete elementData.formattedValue;
+      });
+
+      let blurListener = event => {
+        if (elementData.formattedValue) {
+          event.target.value = elementData.formattedValue;
+        }
+
+        event.target.scrollLeft = 0;
+        elementData.beforeInputSelectionRange = null;
+      };
+
+      if (this.enableScripting && this.hasJSActions) {
+        element.addEventListener("focus", event => {
+          if (elementData.userValue) {
+            event.target.value = elementData.userValue;
+          }
+        });
+        element.addEventListener("updatefromsandbox", jsEvent => {
+          const actions = {
+            value(event) {
+              elementData.userValue = event.detail.value || "";
+              storage.setValue(id, {
+                value: elementData.userValue.toString()
+              });
+
+              if (!elementData.formattedValue) {
+                event.target.value = elementData.userValue;
+              }
+            },
+
+            valueAsString(event) {
+              elementData.formattedValue = event.detail.valueAsString || "";
+
+              if (event.target !== document.activeElement) {
+                event.target.value = elementData.formattedValue;
+              }
+
+              storage.setValue(id, {
+                formattedValue: elementData.formattedValue
+              });
+            },
+
+            selRange(event) {
+              const [selStart, selEnd] = event.detail.selRange;
+
+              if (selStart >= 0 && selEnd < event.target.value.length) {
+                event.target.setSelectionRange(selStart, selEnd);
+              }
+            }
+
+          };
+
+          this._dispatchEventFromSandbox(actions, jsEvent);
+        });
+        element.addEventListener("keydown", event => {
+          elementData.beforeInputValue = event.target.value;
+          let commitKey = -1;
+
+          if (event.key === "Escape") {
+            commitKey = 0;
+          } else if (event.key === "Enter") {
+            commitKey = 2;
+          } else if (event.key === "Tab") {
+            commitKey = 3;
+          }
+
+          if (commitKey === -1) {
+            return;
+          }
+
+          elementData.userValue = event.target.value;
+          this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+            source: this,
+            detail: {
+              id,
+              name: "Keystroke",
+              value: event.target.value,
+              willCommit: true,
+              commitKey,
+              selStart: event.target.selectionStart,
+              selEnd: event.target.selectionEnd
+            }
+          });
+        });
+        const _blurListener = blurListener;
+        blurListener = null;
+        element.addEventListener("blur", event => {
+          if (this._mouseState.isDown) {
+            elementData.userValue = event.target.value;
+            this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+              source: this,
+              detail: {
+                id,
+                name: "Keystroke",
+                value: event.target.value,
+                willCommit: true,
+                commitKey: 1,
+                selStart: event.target.selectionStart,
+                selEnd: event.target.selectionEnd
+              }
+            });
+          }
+
+          _blurListener(event);
+        });
+        element.addEventListener("mousedown", event => {
+          elementData.beforeInputValue = event.target.value;
+          elementData.beforeInputSelectionRange = null;
+        });
+        element.addEventListener("keyup", event => {
+          if (event.target.selectionStart === event.target.selectionEnd) {
+            elementData.beforeInputSelectionRange = null;
+          }
+        });
+        element.addEventListener("select", event => {
+          elementData.beforeInputSelectionRange = [event.target.selectionStart, event.target.selectionEnd];
+        });
+
+        if (this.data.actions?.Keystroke) {
+          element.addEventListener("input", event => {
+            let selStart = -1;
+            let selEnd = -1;
+
+            if (elementData.beforeInputSelectionRange) {
+              [selStart, selEnd] = elementData.beforeInputSelectionRange;
+            }
+
+            this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+              source: this,
+              detail: {
+                id,
+                name: "Keystroke",
+                value: elementData.beforeInputValue,
+                change: event.data,
+                willCommit: false,
+                selStart,
+                selEnd
+              }
+            });
+          });
+        }
+
+        this._setEventListeners(element, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.value);
+      }
+
+      if (blurListener) {
+        element.addEventListener("blur", blurListener);
+      }
+
+      if (this.data.maxLen !== null) {
+        element.maxLength = this.data.maxLen;
+      }
+
+      if (this.data.comb) {
+        const fieldWidth = this.data.rect[2] - this.data.rect[0];
+        const combWidth = fieldWidth / this.data.maxLen;
+        element.classList.add("comb");
+        element.style.letterSpacing = `calc(${combWidth}px - 1ch)`;
+      }
+    } else {
+      element = document.createElement("div");
+      element.textContent = this.data.fieldValue;
+      element.style.verticalAlign = "middle";
+      element.style.display = "table-cell";
+    }
+
+    this._setTextStyle(element);
+
+    this._setBackgroundColor(element);
+
+    this.container.appendChild(element);
+    return this.container;
+  }
+
+  _setTextStyle(element) {
+    const TEXT_ALIGNMENT = ["left", "center", "right"];
+    const {
+      fontSize,
+      fontColor
+    } = this.data.defaultAppearanceData;
+    const style = element.style;
+
+    if (fontSize) {
+      style.fontSize = `${fontSize}px`;
+    }
+
+    style.color = _util.Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]);
+
+    if (this.data.textAlignment !== null) {
+      style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];
+    }
+  }
+
+}
+
+class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
+  constructor(parameters) {
+    super(parameters, {
+      isRenderable: parameters.renderForms
+    });
+  }
+
+  render() {
+    const storage = this.annotationStorage;
+    const data = this.data;
+    const id = data.id;
+    let value = storage.getValue(id, {
+      value: data.exportValue === data.fieldValue
+    }).value;
+
+    if (typeof value === "string") {
+      value = value !== "Off";
+      storage.setValue(id, {
+        value
+      });
+    }
+
+    this.container.className = "buttonWidgetAnnotation checkBox";
+    const element = document.createElement("input");
+    GetElementsByNameSet.add(element);
+    element.disabled = data.readOnly;
+    element.type = "checkbox";
+    element.name = data.fieldName;
+
+    if (value) {
+      element.setAttribute("checked", true);
+    }
+
+    element.setAttribute("id", id);
+    element.setAttribute("exportValue", data.exportValue);
+    element.tabIndex = DEFAULT_TAB_INDEX;
+    element.addEventListener("change", event => {
+      const {
+        name,
+        checked
+      } = event.target;
+
+      for (const checkbox of this._getElementsByName(name, id)) {
+        const curChecked = checked && checkbox.exportValue === data.exportValue;
+
+        if (checkbox.domElement) {
+          checkbox.domElement.checked = curChecked;
+        }
+
+        storage.setValue(checkbox.id, {
+          value: curChecked
+        });
+      }
+
+      storage.setValue(id, {
+        value: checked
+      });
+    });
+    element.addEventListener("resetform", event => {
+      const defaultValue = data.defaultFieldValue || "Off";
+      event.target.checked = defaultValue === data.exportValue;
+    });
+
+    if (this.enableScripting && this.hasJSActions) {
+      element.addEventListener("updatefromsandbox", jsEvent => {
+        const actions = {
+          value(event) {
+            event.target.checked = event.detail.value !== "Off";
+            storage.setValue(id, {
+              value: event.target.checked
+            });
+          }
+
+        };
+
+        this._dispatchEventFromSandbox(actions, jsEvent);
+      });
+
+      this._setEventListeners(element, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked);
+    }
+
+    this._setBackgroundColor(element);
+
+    this.container.appendChild(element);
+    return this.container;
+  }
+
+}
+
+class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
+  constructor(parameters) {
+    super(parameters, {
+      isRenderable: parameters.renderForms
+    });
+  }
+
+  render() {
+    this.container.className = "buttonWidgetAnnotation radioButton";
+    const storage = this.annotationStorage;
+    const data = this.data;
+    const id = data.id;
+    let value = storage.getValue(id, {
+      value: data.fieldValue === data.buttonValue
+    }).value;
+
+    if (typeof value === "string") {
+      value = value !== data.buttonValue;
+      storage.setValue(id, {
+        value
+      });
+    }
+
+    const element = document.createElement("input");
+    GetElementsByNameSet.add(element);
+    element.disabled = data.readOnly;
+    element.type = "radio";
+    element.name = data.fieldName;
+
+    if (value) {
+      element.setAttribute("checked", true);
+    }
+
+    element.setAttribute("id", id);
+    element.tabIndex = DEFAULT_TAB_INDEX;
+    element.addEventListener("change", event => {
+      const {
+        name,
+        checked
+      } = event.target;
+
+      for (const radio of this._getElementsByName(name, id)) {
+        storage.setValue(radio.id, {
+          value: false
+        });
+      }
+
+      storage.setValue(id, {
+        value: checked
+      });
+    });
+    element.addEventListener("resetform", event => {
+      const defaultValue = data.defaultFieldValue;
+      event.target.checked = defaultValue !== null && defaultValue !== undefined && defaultValue === data.buttonValue;
+    });
+
+    if (this.enableScripting && this.hasJSActions) {
+      const pdfButtonValue = data.buttonValue;
+      element.addEventListener("updatefromsandbox", jsEvent => {
+        const actions = {
+          value: event => {
+            const checked = pdfButtonValue === event.detail.value;
+
+            for (const radio of this._getElementsByName(event.target.name)) {
+              const curChecked = checked && radio.id === id;
+
+              if (radio.domElement) {
+                radio.domElement.checked = curChecked;
+              }
+
+              storage.setValue(radio.id, {
+                value: curChecked
+              });
+            }
+          }
+        };
+
+        this._dispatchEventFromSandbox(actions, jsEvent);
+      });
+
+      this._setEventListeners(element, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked);
+    }
+
+    this._setBackgroundColor(element);
+
+    this.container.appendChild(element);
+    return this.container;
+  }
+
+}
+
+class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
+  constructor(parameters) {
+    super(parameters, {
+      ignoreBorder: parameters.data.hasAppearance
+    });
+  }
+
+  render() {
+    const container = super.render();
+    container.className = "buttonWidgetAnnotation pushButton";
+
+    if (this.data.alternativeText) {
+      container.title = this.data.alternativeText;
+    }
+
+    return container;
+  }
+
+}
+
+class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
+  constructor(parameters) {
+    super(parameters, {
+      isRenderable: parameters.renderForms
+    });
+  }
+
+  render() {
+    this.container.className = "choiceWidgetAnnotation";
+    const storage = this.annotationStorage;
+    const id = this.data.id;
+    storage.getValue(id, {
+      value: this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : undefined
+    });
+    let {
+      fontSize
+    } = this.data.defaultAppearanceData;
+
+    if (!fontSize) {
+      fontSize = 9;
+    }
+
+    const fontSizeStyle = `calc(${fontSize}px * var(--zoom-factor))`;
+    const selectElement = document.createElement("select");
+    GetElementsByNameSet.add(selectElement);
+    selectElement.disabled = this.data.readOnly;
+    selectElement.name = this.data.fieldName;
+    selectElement.setAttribute("id", id);
+    selectElement.tabIndex = DEFAULT_TAB_INDEX;
+    selectElement.style.fontSize = `${fontSize}px`;
+
+    if (!this.data.combo) {
+      selectElement.size = this.data.options.length;
+
+      if (this.data.multiSelect) {
+        selectElement.multiple = true;
+      }
+    }
+
+    selectElement.addEventListener("resetform", event => {
+      const defaultValue = this.data.defaultFieldValue;
+
+      for (const option of selectElement.options) {
+        option.selected = option.value === defaultValue;
+      }
+    });
+
+    for (const option of this.data.options) {
+      const optionElement = document.createElement("option");
+      optionElement.textContent = option.displayValue;
+      optionElement.value = option.exportValue;
+
+      if (this.data.combo) {
+        optionElement.style.fontSize = fontSizeStyle;
+      }
+
+      if (this.data.fieldValue.includes(option.exportValue)) {
+        optionElement.setAttribute("selected", true);
+      }
+
+      selectElement.appendChild(optionElement);
+    }
+
+    const getValue = (event, isExport) => {
+      const name = isExport ? "value" : "textContent";
+      const options = event.target.options;
+
+      if (!event.target.multiple) {
+        return options.selectedIndex === -1 ? null : options[options.selectedIndex][name];
+      }
+
+      return Array.prototype.filter.call(options, option => option.selected).map(option => option[name]);
+    };
+
+    const getItems = event => {
+      const options = event.target.options;
+      return Array.prototype.map.call(options, option => {
+        return {
+          displayValue: option.textContent,
+          exportValue: option.value
+        };
+      });
+    };
+
+    if (this.enableScripting && this.hasJSActions) {
+      selectElement.addEventListener("updatefromsandbox", jsEvent => {
+        const actions = {
+          value(event) {
+            const value = event.detail.value;
+            const values = new Set(Array.isArray(value) ? value : [value]);
+
+            for (const option of selectElement.options) {
+              option.selected = values.has(option.value);
+            }
+
+            storage.setValue(id, {
+              value: getValue(event, true)
+            });
+          },
+
+          multipleSelection(event) {
+            selectElement.multiple = true;
+          },
+
+          remove(event) {
+            const options = selectElement.options;
+            const index = event.detail.remove;
+            options[index].selected = false;
+            selectElement.remove(index);
+
+            if (options.length > 0) {
+              const i = Array.prototype.findIndex.call(options, option => option.selected);
+
+              if (i === -1) {
+                options[0].selected = true;
+              }
+            }
+
+            storage.setValue(id, {
+              value: getValue(event, true),
+              items: getItems(event)
+            });
+          },
+
+          clear(event) {
+            while (selectElement.length !== 0) {
+              selectElement.remove(0);
+            }
+
+            storage.setValue(id, {
+              value: null,
+              items: []
+            });
+          },
+
+          insert(event) {
+            const {
+              index,
+              displayValue,
+              exportValue
+            } = event.detail.insert;
+            const optionElement = document.createElement("option");
+            optionElement.textContent = displayValue;
+            optionElement.value = exportValue;
+            selectElement.insertBefore(optionElement, selectElement.children[index]);
+            storage.setValue(id, {
+              value: getValue(event, true),
+              items: getItems(event)
+            });
+          },
+
+          items(event) {
+            const {
+              items
+            } = event.detail;
+
+            while (selectElement.length !== 0) {
+              selectElement.remove(0);
+            }
+
+            for (const item of items) {
+              const {
+                displayValue,
+                exportValue
+              } = item;
+              const optionElement = document.createElement("option");
+              optionElement.textContent = displayValue;
+              optionElement.value = exportValue;
+              selectElement.appendChild(optionElement);
+            }
+
+            if (selectElement.options.length > 0) {
+              selectElement.options[0].selected = true;
+            }
+
+            storage.setValue(id, {
+              value: getValue(event, true),
+              items: getItems(event)
+            });
+          },
+
+          indices(event) {
+            const indices = new Set(event.detail.indices);
+
+            for (const option of event.target.options) {
+              option.selected = indices.has(option.index);
+            }
+
+            storage.setValue(id, {
+              value: getValue(event, true)
+            });
+          },
+
+          editable(event) {
+            event.target.disabled = !event.detail.editable;
+          }
+
+        };
+
+        this._dispatchEventFromSandbox(actions, jsEvent);
+      });
+      selectElement.addEventListener("input", event => {
+        const exportValue = getValue(event, true);
+        const value = getValue(event, false);
+        storage.setValue(id, {
+          value: exportValue
+        });
+        this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
+          source: this,
+          detail: {
+            id,
+            name: "Keystroke",
+            value,
+            changeEx: exportValue,
+            willCommit: true,
+            commitKey: 1,
+            keyDown: false
+          }
+        });
+      });
+
+      this._setEventListeners(selectElement, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"], ["input", "Action"]], event => event.target.checked);
+    } else {
+      selectElement.addEventListener("input", function (event) {
+        storage.setValue(id, {
+          value: getValue(event)
+        });
+      });
+    }
+
+    this._setBackgroundColor(selectElement);
+
+    this.container.appendChild(selectElement);
+    return this.container;
+  }
+
+}
+
+class PopupAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable
+    });
+  }
+
+  render() {
+    const IGNORE_TYPES = ["Line", "Square", "Circle", "PolyLine", "Polygon", "Ink"];
+    this.container.className = "popupAnnotation";
+
+    if (IGNORE_TYPES.includes(this.data.parentType)) {
+      return this.container;
+    }
+
+    const selector = `[data-annotation-id="${this.data.parentId}"]`;
+    const parentElements = this.layer.querySelectorAll(selector);
+
+    if (parentElements.length === 0) {
+      return this.container;
+    }
+
+    const popup = new PopupElement({
+      container: this.container,
+      trigger: Array.from(parentElements),
+      color: this.data.color,
+      titleObj: this.data.titleObj,
+      modificationDate: this.data.modificationDate,
+      contentsObj: this.data.contentsObj,
+      richText: this.data.richText
+    });
+    const page = this.page;
+
+    const rect = _util.Util.normalizeRect([this.data.parentRect[0], page.view[3] - this.data.parentRect[1] + page.view[1], this.data.parentRect[2], page.view[3] - this.data.parentRect[3] + page.view[1]]);
+
+    const popupLeft = rect[0] + this.data.parentRect[2] - this.data.parentRect[0];
+    const popupTop = rect[1];
+    this.container.style.transformOrigin = `${-popupLeft}px ${-popupTop}px`;
+    this.container.style.left = `${popupLeft}px`;
+    this.container.style.top = `${popupTop}px`;
+    this.container.appendChild(popup.render());
+    return this.container;
+  }
+
+}
+
+class PopupElement {
+  constructor(parameters) {
+    this.container = parameters.container;
+    this.trigger = parameters.trigger;
+    this.color = parameters.color;
+    this.titleObj = parameters.titleObj;
+    this.modificationDate = parameters.modificationDate;
+    this.contentsObj = parameters.contentsObj;
+    this.richText = parameters.richText;
+    this.hideWrapper = parameters.hideWrapper || false;
+    this.pinned = false;
+  }
+
+  render() {
+    const BACKGROUND_ENLIGHT = 0.7;
+    const wrapper = document.createElement("div");
+    wrapper.className = "popupWrapper";
+    this.hideElement = this.hideWrapper ? wrapper : this.container;
+    this.hideElement.hidden = true;
+    const popup = document.createElement("div");
+    popup.className = "popup";
+    const color = this.color;
+
+    if (color) {
+      const r = BACKGROUND_ENLIGHT * (255 - color[0]) + color[0];
+      const g = BACKGROUND_ENLIGHT * (255 - color[1]) + color[1];
+      const b = BACKGROUND_ENLIGHT * (255 - color[2]) + color[2];
+      popup.style.backgroundColor = _util.Util.makeHexColor(r | 0, g | 0, b | 0);
+    }
+
+    const title = document.createElement("h1");
+    title.dir = this.titleObj.dir;
+    title.textContent = this.titleObj.str;
+    popup.appendChild(title);
+
+    const dateObject = _display_utils.PDFDateString.toDateObject(this.modificationDate);
+
+    if (dateObject) {
+      const modificationDate = document.createElement("span");
+      modificationDate.className = "popupDate";
+      modificationDate.textContent = "{{date}}, {{time}}";
+      modificationDate.dataset.l10nId = "annotation_date_string";
+      modificationDate.dataset.l10nArgs = JSON.stringify({
+        date: dateObject.toLocaleDateString(),
+        time: dateObject.toLocaleTimeString()
+      });
+      popup.appendChild(modificationDate);
+    }
+
+    if (this.richText?.str && (!this.contentsObj?.str || this.contentsObj.str === this.richText.str)) {
+      _xfa_layer.XfaLayer.render({
+        xfaHtml: this.richText.html,
+        intent: "richText",
+        div: popup
+      });
+
+      popup.lastChild.className = "richText popupContent";
+    } else {
+      const contents = this._formatContents(this.contentsObj);
+
+      popup.appendChild(contents);
+    }
+
+    if (!Array.isArray(this.trigger)) {
+      this.trigger = [this.trigger];
+    }
+
+    for (const element of this.trigger) {
+      element.addEventListener("click", this._toggle.bind(this));
+      element.addEventListener("mouseover", this._show.bind(this, false));
+      element.addEventListener("mouseout", this._hide.bind(this, false));
+    }
+
+    popup.addEventListener("click", this._hide.bind(this, true));
+    wrapper.appendChild(popup);
+    return wrapper;
+  }
+
+  _formatContents({
+    str,
+    dir
+  }) {
+    const p = document.createElement("p");
+    p.className = "popupContent";
+    p.dir = dir;
+    const lines = str.split(/(?:\r\n?|\n)/);
+
+    for (let i = 0, ii = lines.length; i < ii; ++i) {
+      const line = lines[i];
+      p.appendChild(document.createTextNode(line));
+
+      if (i < ii - 1) {
+        p.appendChild(document.createElement("br"));
+      }
+    }
+
+    return p;
+  }
+
+  _toggle() {
+    if (this.pinned) {
+      this._hide(true);
+    } else {
+      this._show(true);
+    }
+  }
+
+  _show(pin = false) {
+    if (pin) {
+      this.pinned = true;
+    }
+
+    if (this.hideElement.hidden) {
+      this.hideElement.hidden = false;
+      this.container.style.zIndex += 1;
+    }
+  }
+
+  _hide(unpin = true) {
+    if (unpin) {
+      this.pinned = false;
+    }
+
+    if (!this.hideElement.hidden && !this.pinned) {
+      this.hideElement.hidden = true;
+      this.container.style.zIndex -= 1;
+    }
+  }
+
+}
+
+class FreeTextAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true
+    });
+  }
+
+  render() {
+    this.container.className = "freeTextAnnotation";
+
+    if (!this.data.hasPopup) {
+      this._createPopup(null, this.data);
+    }
+
+    return this.container;
+  }
+
+}
+
+class LineAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true
+    });
+  }
+
+  render() {
+    this.container.className = "lineAnnotation";
+    const data = this.data;
+    const width = data.rect[2] - data.rect[0];
+    const height = data.rect[3] - data.rect[1];
+    const svg = this.svgFactory.create(width, height);
+    const line = this.svgFactory.createElement("svg:line");
+    line.setAttribute("x1", data.rect[2] - data.lineCoordinates[0]);
+    line.setAttribute("y1", data.rect[3] - data.lineCoordinates[1]);
+    line.setAttribute("x2", data.rect[2] - data.lineCoordinates[2]);
+    line.setAttribute("y2", data.rect[3] - data.lineCoordinates[3]);
+    line.setAttribute("stroke-width", data.borderStyle.width || 1);
+    line.setAttribute("stroke", "transparent");
+    line.setAttribute("fill", "transparent");
+    svg.appendChild(line);
+    this.container.append(svg);
+
+    this._createPopup(line, data);
+
+    return this.container;
+  }
+
+}
+
+class SquareAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true
+    });
+  }
+
+  render() {
+    this.container.className = "squareAnnotation";
+    const data = this.data;
+    const width = data.rect[2] - data.rect[0];
+    const height = data.rect[3] - data.rect[1];
+    const svg = this.svgFactory.create(width, height);
+    const borderWidth = data.borderStyle.width;
+    const square = this.svgFactory.createElement("svg:rect");
+    square.setAttribute("x", borderWidth / 2);
+    square.setAttribute("y", borderWidth / 2);
+    square.setAttribute("width", width - borderWidth);
+    square.setAttribute("height", height - borderWidth);
+    square.setAttribute("stroke-width", borderWidth || 1);
+    square.setAttribute("stroke", "transparent");
+    square.setAttribute("fill", "transparent");
+    svg.appendChild(square);
+    this.container.append(svg);
+
+    this._createPopup(square, data);
+
+    return this.container;
+  }
+
+}
+
+class CircleAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true
+    });
+  }
+
+  render() {
+    this.container.className = "circleAnnotation";
+    const data = this.data;
+    const width = data.rect[2] - data.rect[0];
+    const height = data.rect[3] - data.rect[1];
+    const svg = this.svgFactory.create(width, height);
+    const borderWidth = data.borderStyle.width;
+    const circle = this.svgFactory.createElement("svg:ellipse");
+    circle.setAttribute("cx", width / 2);
+    circle.setAttribute("cy", height / 2);
+    circle.setAttribute("rx", width / 2 - borderWidth / 2);
+    circle.setAttribute("ry", height / 2 - borderWidth / 2);
+    circle.setAttribute("stroke-width", borderWidth || 1);
+    circle.setAttribute("stroke", "transparent");
+    circle.setAttribute("fill", "transparent");
+    svg.appendChild(circle);
+    this.container.append(svg);
+
+    this._createPopup(circle, data);
+
+    return this.container;
+  }
+
+}
+
+class PolylineAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true
+    });
+    this.containerClassName = "polylineAnnotation";
+    this.svgElementName = "svg:polyline";
+  }
+
+  render() {
+    this.container.className = this.containerClassName;
+    const data = this.data;
+    const width = data.rect[2] - data.rect[0];
+    const height = data.rect[3] - data.rect[1];
+    const svg = this.svgFactory.create(width, height);
+    let points = [];
+
+    for (const coordinate of data.vertices) {
+      const x = coordinate.x - data.rect[0];
+      const y = data.rect[3] - coordinate.y;
+      points.push(x + "," + y);
+    }
+
+    points = points.join(" ");
+    const polyline = this.svgFactory.createElement(this.svgElementName);
+    polyline.setAttribute("points", points);
+    polyline.setAttribute("stroke-width", data.borderStyle.width || 1);
+    polyline.setAttribute("stroke", "transparent");
+    polyline.setAttribute("fill", "transparent");
+    svg.appendChild(polyline);
+    this.container.append(svg);
+
+    this._createPopup(polyline, data);
+
+    return this.container;
+  }
+
+}
+
+class PolygonAnnotationElement extends PolylineAnnotationElement {
+  constructor(parameters) {
+    super(parameters);
+    this.containerClassName = "polygonAnnotation";
+    this.svgElementName = "svg:polygon";
+  }
+
+}
+
+class CaretAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true
+    });
+  }
+
+  render() {
+    this.container.className = "caretAnnotation";
+
+    if (!this.data.hasPopup) {
+      this._createPopup(null, this.data);
+    }
+
+    return this.container;
+  }
+
+}
+
+class InkAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true
+    });
+    this.containerClassName = "inkAnnotation";
+    this.svgElementName = "svg:polyline";
+  }
+
+  render() {
+    this.container.className = this.containerClassName;
+    const data = this.data;
+    const width = data.rect[2] - data.rect[0];
+    const height = data.rect[3] - data.rect[1];
+    const svg = this.svgFactory.create(width, height);
+
+    for (const inkList of data.inkLists) {
+      let points = [];
+
+      for (const coordinate of inkList) {
+        const x = coordinate.x - data.rect[0];
+        const y = data.rect[3] - coordinate.y;
+        points.push(`${x},${y}`);
+      }
+
+      points = points.join(" ");
+      const polyline = this.svgFactory.createElement(this.svgElementName);
+      polyline.setAttribute("points", points);
+      polyline.setAttribute("stroke-width", data.borderStyle.width || 1);
+      polyline.setAttribute("stroke", "transparent");
+      polyline.setAttribute("fill", "transparent");
+
+      this._createPopup(polyline, data);
+
+      svg.appendChild(polyline);
+    }
+
+    this.container.append(svg);
+    return this.container;
+  }
+
+}
+
+class HighlightAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true,
+      createQuadrilaterals: true
+    });
+  }
+
+  render() {
+    if (!this.data.hasPopup) {
+      this._createPopup(null, this.data);
+    }
+
+    if (this.quadrilaterals) {
+      return this._renderQuadrilaterals("highlightAnnotation");
+    }
+
+    this.container.className = "highlightAnnotation";
+    return this.container;
+  }
+
+}
+
+class UnderlineAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true,
+      createQuadrilaterals: true
+    });
+  }
+
+  render() {
+    if (!this.data.hasPopup) {
+      this._createPopup(null, this.data);
+    }
+
+    if (this.quadrilaterals) {
+      return this._renderQuadrilaterals("underlineAnnotation");
+    }
+
+    this.container.className = "underlineAnnotation";
+    return this.container;
+  }
+
+}
+
+class SquigglyAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true,
+      createQuadrilaterals: true
+    });
+  }
+
+  render() {
+    if (!this.data.hasPopup) {
+      this._createPopup(null, this.data);
+    }
+
+    if (this.quadrilaterals) {
+      return this._renderQuadrilaterals("squigglyAnnotation");
+    }
+
+    this.container.className = "squigglyAnnotation";
+    return this.container;
+  }
+
+}
+
+class StrikeOutAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true,
+      createQuadrilaterals: true
+    });
+  }
+
+  render() {
+    if (!this.data.hasPopup) {
+      this._createPopup(null, this.data);
+    }
+
+    if (this.quadrilaterals) {
+      return this._renderQuadrilaterals("strikeoutAnnotation");
+    }
+
+    this.container.className = "strikeoutAnnotation";
+    return this.container;
+  }
+
+}
+
+class StampAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    const isRenderable = !!(parameters.data.hasPopup || parameters.data.titleObj?.str || parameters.data.contentsObj?.str || parameters.data.richText?.str);
+    super(parameters, {
+      isRenderable,
+      ignoreBorder: true
+    });
+  }
+
+  render() {
+    this.container.className = "stampAnnotation";
+
+    if (!this.data.hasPopup) {
+      this._createPopup(null, this.data);
+    }
+
+    return this.container;
+  }
+
+}
+
+class FileAttachmentAnnotationElement extends AnnotationElement {
+  constructor(parameters) {
+    super(parameters, {
+      isRenderable: true
+    });
+    const {
+      filename,
+      content
+    } = this.data.file;
+    this.filename = (0, _display_utils.getFilenameFromUrl)(filename);
+    this.content = content;
+    this.linkService.eventBus?.dispatch("fileattachmentannotation", {
+      source: this,
+      id: (0, _util.stringToPDFString)(filename),
+      filename,
+      content
+    });
+  }
+
+  render() {
+    this.container.className = "fileAttachmentAnnotation";
+    const trigger = document.createElement("div");
+    trigger.style.height = this.container.style.height;
+    trigger.style.width = this.container.style.width;
+    trigger.addEventListener("dblclick", this._download.bind(this));
+
+    if (!this.data.hasPopup && (this.data.titleObj?.str || this.data.contentsObj?.str || this.data.richText)) {
+      this._createPopup(trigger, this.data);
+    }
+
+    this.container.appendChild(trigger);
+    return this.container;
+  }
+
+  _download() {
+    this.downloadManager?.openOrDownloadData(this.container, this.content, this.filename);
+  }
+
+}
+
+class AnnotationLayer {
+  static render(parameters) {
+    const sortedAnnotations = [],
+          popupAnnotations = [];
+
+    for (const data of parameters.annotations) {
+      if (!data) {
+        continue;
+      }
+
+      if (data.annotationType === _util.AnnotationType.POPUP) {
+        popupAnnotations.push(data);
+        continue;
+      }
+
+      sortedAnnotations.push(data);
+    }
+
+    if (popupAnnotations.length) {
+      sortedAnnotations.push(...popupAnnotations);
+    }
+
+    const div = parameters.div;
+
+    for (const data of sortedAnnotations) {
+      const element = AnnotationElementFactory.create({
+        data,
+        layer: div,
+        page: parameters.page,
+        viewport: parameters.viewport,
+        linkService: parameters.linkService,
+        downloadManager: parameters.downloadManager,
+        imageResourcesPath: parameters.imageResourcesPath || "",
+        renderForms: parameters.renderForms !== false,
+        svgFactory: new _display_utils.DOMSVGFactory(),
+        annotationStorage: parameters.annotationStorage || new _annotation_storage.AnnotationStorage(),
+        enableScripting: parameters.enableScripting,
+        hasJSActions: parameters.hasJSActions,
+        fieldObjects: parameters.fieldObjects,
+        mouseState: parameters.mouseState || {
+          isDown: false
+        }
+      });
+
+      if (element.isRenderable) {
+        const rendered = element.render();
+
+        if (data.hidden) {
+          rendered.style.visibility = "hidden";
+        }
+
+        if (Array.isArray(rendered)) {
+          for (const renderedElement of rendered) {
+            div.appendChild(renderedElement);
+          }
+        } else {
+          if (element instanceof PopupAnnotationElement) {
+            div.prepend(rendered);
+          } else {
+            div.appendChild(rendered);
+          }
+        }
+      }
+    }
+
+    this.#setAnnotationCanvasMap(div, parameters.annotationCanvasMap);
+  }
+
+  static update(parameters) {
+    const {
+      page,
+      viewport,
+      annotations,
+      annotationCanvasMap,
+      div
+    } = parameters;
+    const transform = viewport.transform;
+    const matrix = `matrix(${transform.join(",")})`;
+    let scale, ownMatrix;
+
+    for (const data of annotations) {
+      const elements = div.querySelectorAll(`[data-annotation-id="${data.id}"]`);
+
+      if (elements) {
+        for (const element of elements) {
+          if (data.hasOwnCanvas) {
+            const rect = _util.Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]);
+
+            if (!ownMatrix) {
+              scale = Math.abs(transform[0] || transform[1]);
+              const ownTransform = transform.slice();
+
+              for (let i = 0; i < 4; i++) {
+                ownTransform[i] = Math.sign(ownTransform[i]);
+              }
+
+              ownMatrix = `matrix(${ownTransform.join(",")})`;
+            }
+
+            const left = rect[0] * scale;
+            const top = rect[1] * scale;
+            element.style.left = `${left}px`;
+            element.style.top = `${top}px`;
+            element.style.transformOrigin = `${-left}px ${-top}px`;
+            element.style.transform = ownMatrix;
+          } else {
+            element.style.transform = matrix;
+          }
+        }
+      }
+    }
+
+    this.#setAnnotationCanvasMap(div, annotationCanvasMap);
+    div.hidden = false;
+  }
+
+  static #setAnnotationCanvasMap(div, annotationCanvasMap) {
+    if (!annotationCanvasMap) {
+      return;
+    }
+
+    for (const [id, canvas] of annotationCanvasMap) {
+      const element = div.querySelector(`[data-annotation-id="${id}"]`);
+
+      if (!element) {
+        continue;
+      }
+
+      const {
+        firstChild
+      } = element;
+
+      if (firstChild.nodeName === "CANVAS") {
+        element.replaceChild(canvas, firstChild);
+      } else {
+        element.insertBefore(canvas, firstChild);
+      }
+    }
+
+    annotationCanvasMap.clear();
+  }
+
+}
+
+exports.AnnotationLayer = AnnotationLayer;
+
+/***/ }),
+/* 19 */
+/***/ ((__unused_webpack_module, exports) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.ColorConverters = void 0;
+
+function makeColorComp(n) {
+  return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, "0");
+}
+
+class ColorConverters {
+  static CMYK_G([c, y, m, k]) {
+    return ["G", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)];
+  }
+
+  static G_CMYK([g]) {
+    return ["CMYK", 0, 0, 0, 1 - g];
+  }
+
+  static G_RGB([g]) {
+    return ["RGB", g, g, g];
+  }
+
+  static G_HTML([g]) {
+    const G = makeColorComp(g);
+    return `#${G}${G}${G}`;
+  }
+
+  static RGB_G([r, g, b]) {
+    return ["G", 0.3 * r + 0.59 * g + 0.11 * b];
+  }
+
+  static RGB_HTML([r, g, b]) {
+    const R = makeColorComp(r);
+    const G = makeColorComp(g);
+    const B = makeColorComp(b);
+    return `#${R}${G}${B}`;
+  }
+
+  static T_HTML() {
+    return "#00000000";
+  }
+
+  static CMYK_RGB([c, y, m, k]) {
+    return ["RGB", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)];
+  }
+
+  static CMYK_HTML(components) {
+    return this.RGB_HTML(this.CMYK_RGB(components));
+  }
+
+  static RGB_CMYK([r, g, b]) {
+    const c = 1 - r;
+    const m = 1 - g;
+    const y = 1 - b;
+    const k = Math.min(c, m, y);
+    return ["CMYK", c, m, y, k];
+  }
+
+}
+
+exports.ColorConverters = ColorConverters;
+
+/***/ }),
+/* 20 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.XfaLayer = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+var _xfa_text = __w_pdfjs_require__(17);
+
+class XfaLayer {
+  static setupStorage(html, id, element, storage, intent) {
+    const storedData = storage.getValue(id, {
+      value: null
+    });
+
+    switch (element.name) {
+      case "textarea":
+        if (storedData.value !== null) {
+          html.textContent = storedData.value;
+        }
+
+        if (intent === "print") {
+          break;
+        }
+
+        html.addEventListener("input", event => {
+          storage.setValue(id, {
+            value: event.target.value
+          });
+        });
+        break;
+
+      case "input":
+        if (element.attributes.type === "radio" || element.attributes.type === "checkbox") {
+          if (storedData.value === element.attributes.xfaOn) {
+            html.setAttribute("checked", true);
+          } else if (storedData.value === element.attributes.xfaOff) {
+            html.removeAttribute("checked");
+          }
+
+          if (intent === "print") {
+            break;
+          }
+
+          html.addEventListener("change", event => {
+            storage.setValue(id, {
+              value: event.target.checked ? event.target.getAttribute("xfaOn") : event.target.getAttribute("xfaOff")
+            });
+          });
+        } else {
+          if (storedData.value !== null) {
+            html.setAttribute("value", storedData.value);
+          }
+
+          if (intent === "print") {
+            break;
+          }
+
+          html.addEventListener("input", event => {
+            storage.setValue(id, {
+              value: event.target.value
+            });
+          });
+        }
+
+        break;
+
+      case "select":
+        if (storedData.value !== null) {
+          for (const option of element.children) {
+            if (option.attributes.value === storedData.value) {
+              option.attributes.selected = true;
+            }
+          }
+        }
+
+        html.addEventListener("input", event => {
+          const options = event.target.options;
+          const value = options.selectedIndex === -1 ? "" : options[options.selectedIndex].value;
+          storage.setValue(id, {
+            value
+          });
+        });
+        break;
+    }
+  }
+
+  static setAttributes({
+    html,
+    element,
+    storage = null,
+    intent,
+    linkService
+  }) {
+    const {
+      attributes
+    } = element;
+    const isHTMLAnchorElement = html instanceof HTMLAnchorElement;
+
+    if (attributes.type === "radio") {
+      attributes.name = `${attributes.name}-${intent}`;
+    }
+
+    for (const [key, value] of Object.entries(attributes)) {
+      if (value === null || value === undefined || key === "dataId") {
+        continue;
+      }
+
+      if (key !== "style") {
+        if (key === "textContent") {
+          html.textContent = value;
+        } else if (key === "class") {
+          if (value.length) {
+            html.setAttribute(key, value.join(" "));
+          }
+        } else {
+          if (isHTMLAnchorElement && (key === "href" || key === "newWindow")) {
+            continue;
+          }
+
+          html.setAttribute(key, value);
+        }
+      } else {
+        Object.assign(html.style, value);
+      }
+    }
+
+    if (isHTMLAnchorElement) {
+      if (!linkService.addLinkAttributes) {
+        (0, _util.warn)("XfaLayer.setAttribute - missing `addLinkAttributes`-method on the `linkService`-instance.");
+      }
+
+      linkService.addLinkAttributes?.(html, attributes.href, attributes.newWindow);
+    }
+
+    if (storage && attributes.dataId) {
+      this.setupStorage(html, attributes.dataId, element, storage);
+    }
+  }
+
+  static render(parameters) {
+    const storage = parameters.annotationStorage;
+    const linkService = parameters.linkService;
+    const root = parameters.xfaHtml;
+    const intent = parameters.intent || "display";
+    const rootHtml = document.createElement(root.name);
+
+    if (root.attributes) {
+      this.setAttributes({
+        html: rootHtml,
+        element: root,
+        intent,
+        linkService
+      });
+    }
+
+    const stack = [[root, -1, rootHtml]];
+    const rootDiv = parameters.div;
+    rootDiv.appendChild(rootHtml);
+
+    if (parameters.viewport) {
+      const transform = `matrix(${parameters.viewport.transform.join(",")})`;
+      rootDiv.style.transform = transform;
+    }
+
+    if (intent !== "richText") {
+      rootDiv.setAttribute("class", "xfaLayer xfaFont");
+    }
+
+    const textDivs = [];
+
+    while (stack.length > 0) {
+      const [parent, i, html] = stack[stack.length - 1];
+
+      if (i + 1 === parent.children.length) {
+        stack.pop();
+        continue;
+      }
+
+      const child = parent.children[++stack[stack.length - 1][1]];
+
+      if (child === null) {
+        continue;
+      }
+
+      const {
+        name
+      } = child;
+
+      if (name === "#text") {
+        const node = document.createTextNode(child.value);
+        textDivs.push(node);
+        html.appendChild(node);
+        continue;
+      }
+
+      let childHtml;
+
+      if (child?.attributes?.xmlns) {
+        childHtml = document.createElementNS(child.attributes.xmlns, name);
+      } else {
+        childHtml = document.createElement(name);
+      }
+
+      html.appendChild(childHtml);
+
+      if (child.attributes) {
+        this.setAttributes({
+          html: childHtml,
+          element: child,
+          storage,
+          intent,
+          linkService
+        });
+      }
+
+      if (child.children && child.children.length > 0) {
+        stack.push([child, -1, childHtml]);
+      } else if (child.value) {
+        const node = document.createTextNode(child.value);
+
+        if (_xfa_text.XfaText.shouldBuildText(name)) {
+          textDivs.push(node);
+        }
+
+        childHtml.appendChild(node);
+      }
+    }
+
+    for (const el of rootDiv.querySelectorAll(".xfaNonInteractive input, .xfaNonInteractive textarea")) {
+      el.setAttribute("readOnly", true);
+    }
+
+    return {
+      textDivs
+    };
+  }
+
+  static update(parameters) {
+    const transform = `matrix(${parameters.viewport.transform.join(",")})`;
+    parameters.div.style.transform = transform;
+    parameters.div.hidden = false;
+  }
+
+}
+
+exports.XfaLayer = XfaLayer;
+
+/***/ }),
+/* 21 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.renderTextLayer = renderTextLayer;
+
+var _util = __w_pdfjs_require__(2);
+
+const MAX_TEXT_DIVS_TO_RENDER = 100000;
+const DEFAULT_FONT_SIZE = 30;
+const DEFAULT_FONT_ASCENT = 0.8;
+const ascentCache = new Map();
+const AllWhitespaceRegexp = /^\s+$/g;
+
+function getAscent(fontFamily, ctx) {
+  const cachedAscent = ascentCache.get(fontFamily);
+
+  if (cachedAscent) {
+    return cachedAscent;
+  }
+
+  ctx.save();
+  ctx.font = `${DEFAULT_FONT_SIZE}px ${fontFamily}`;
+  const metrics = ctx.measureText("");
+  let ascent = metrics.fontBoundingBoxAscent;
+  let descent = Math.abs(metrics.fontBoundingBoxDescent);
+
+  if (ascent) {
+    ctx.restore();
+    const ratio = ascent / (ascent + descent);
+    ascentCache.set(fontFamily, ratio);
+    return ratio;
+  }
+
+  ctx.strokeStyle = "red";
+  ctx.clearRect(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE);
+  ctx.strokeText("g", 0, 0);
+  let pixels = ctx.getImageData(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE).data;
+  descent = 0;
+
+  for (let i = pixels.length - 1 - 3; i >= 0; i -= 4) {
+    if (pixels[i] > 0) {
+      descent = Math.ceil(i / 4 / DEFAULT_FONT_SIZE);
+      break;
+    }
+  }
+
+  ctx.clearRect(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE);
+  ctx.strokeText("A", 0, DEFAULT_FONT_SIZE);
+  pixels = ctx.getImageData(0, 0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE).data;
+  ascent = 0;
+
+  for (let i = 0, ii = pixels.length; i < ii; i += 4) {
+    if (pixels[i] > 0) {
+      ascent = DEFAULT_FONT_SIZE - Math.floor(i / 4 / DEFAULT_FONT_SIZE);
+      break;
+    }
+  }
+
+  ctx.restore();
+
+  if (ascent) {
+    const ratio = ascent / (ascent + descent);
+    ascentCache.set(fontFamily, ratio);
+    return ratio;
+  }
+
+  ascentCache.set(fontFamily, DEFAULT_FONT_ASCENT);
+  return DEFAULT_FONT_ASCENT;
+}
+
+function appendText(task, geom, styles, ctx) {
+  const textDiv = document.createElement("span");
+  const textDivProperties = task._enhanceTextSelection ? {
+    angle: 0,
+    canvasWidth: 0,
+    hasText: geom.str !== "",
+    hasEOL: geom.hasEOL,
+    originalTransform: null,
+    paddingBottom: 0,
+    paddingLeft: 0,
+    paddingRight: 0,
+    paddingTop: 0,
+    scale: 1
+  } : {
+    angle: 0,
+    canvasWidth: 0,
+    hasText: geom.str !== "",
+    hasEOL: geom.hasEOL
+  };
+
+  task._textDivs.push(textDiv);
+
+  const tx = _util.Util.transform(task._viewport.transform, geom.transform);
+
+  let angle = Math.atan2(tx[1], tx[0]);
+  const style = styles[geom.fontName];
+
+  if (style.vertical) {
+    angle += Math.PI / 2;
+  }
+
+  const fontHeight = Math.hypot(tx[2], tx[3]);
+  const fontAscent = fontHeight * getAscent(style.fontFamily, ctx);
+  let left, top;
+
+  if (angle === 0) {
+    left = tx[4];
+    top = tx[5] - fontAscent;
+  } else {
+    left = tx[4] + fontAscent * Math.sin(angle);
+    top = tx[5] - fontAscent * Math.cos(angle);
+  }
+
+  textDiv.style.left = `${left}px`;
+  textDiv.style.top = `${top}px`;
+  textDiv.style.fontSize = `${fontHeight}px`;
+  textDiv.style.fontFamily = style.fontFamily;
+  textDiv.setAttribute("role", "presentation");
+  textDiv.textContent = geom.str;
+  textDiv.dir = geom.dir;
+
+  if (task._fontInspectorEnabled) {
+    textDiv.dataset.fontName = geom.fontName;
+  }
+
+  if (angle !== 0) {
+    textDivProperties.angle = angle * (180 / Math.PI);
+  }
+
+  let shouldScaleText = false;
+
+  if (geom.str.length > 1 || task._enhanceTextSelection && AllWhitespaceRegexp.test(geom.str)) {
+    shouldScaleText = true;
+  } else if (geom.str !== " " && geom.transform[0] !== geom.transform[3]) {
+    const absScaleX = Math.abs(geom.transform[0]),
+          absScaleY = Math.abs(geom.transform[3]);
+
+    if (absScaleX !== absScaleY && Math.max(absScaleX, absScaleY) / Math.min(absScaleX, absScaleY) > 1.5) {
+      shouldScaleText = true;
+    }
+  }
+
+  if (shouldScaleText) {
+    if (style.vertical) {
+      textDivProperties.canvasWidth = geom.height * task._viewport.scale;
+    } else {
+      textDivProperties.canvasWidth = geom.width * task._viewport.scale;
+    }
+  }
+
+  task._textDivProperties.set(textDiv, textDivProperties);
+
+  if (task._textContentStream) {
+    task._layoutText(textDiv);
+  }
+
+  if (task._enhanceTextSelection && textDivProperties.hasText) {
+    let angleCos = 1,
+        angleSin = 0;
+
+    if (angle !== 0) {
+      angleCos = Math.cos(angle);
+      angleSin = Math.sin(angle);
+    }
+
+    const divWidth = (style.vertical ? geom.height : geom.width) * task._viewport.scale;
+    const divHeight = fontHeight;
+    let m, b;
+
+    if (angle !== 0) {
+      m = [angleCos, angleSin, -angleSin, angleCos, left, top];
+      b = _util.Util.getAxialAlignedBoundingBox([0, 0, divWidth, divHeight], m);
+    } else {
+      b = [left, top, left + divWidth, top + divHeight];
+    }
+
+    task._bounds.push({
+      left: b[0],
+      top: b[1],
+      right: b[2],
+      bottom: b[3],
+      div: textDiv,
+      size: [divWidth, divHeight],
+      m
+    });
+  }
+}
+
+function render(task) {
+  if (task._canceled) {
+    return;
+  }
+
+  const textDivs = task._textDivs;
+  const capability = task._capability;
+  const textDivsLength = textDivs.length;
+
+  if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
+    task._renderingDone = true;
+    capability.resolve();
+    return;
+  }
+
+  if (!task._textContentStream) {
+    for (let i = 0; i < textDivsLength; i++) {
+      task._layoutText(textDivs[i]);
+    }
+  }
+
+  task._renderingDone = true;
+  capability.resolve();
+}
+
+function findPositiveMin(ts, offset, count) {
+  let result = 0;
+
+  for (let i = 0; i < count; i++) {
+    const t = ts[offset++];
+
+    if (t > 0) {
+      result = result ? Math.min(t, result) : t;
+    }
+  }
+
+  return result;
+}
+
+function expand(task) {
+  const bounds = task._bounds;
+  const viewport = task._viewport;
+  const expanded = expandBounds(viewport.width, viewport.height, bounds);
+
+  for (let i = 0; i < expanded.length; i++) {
+    const div = bounds[i].div;
+
+    const divProperties = task._textDivProperties.get(div);
+
+    if (divProperties.angle === 0) {
+      divProperties.paddingLeft = bounds[i].left - expanded[i].left;
+      divProperties.paddingTop = bounds[i].top - expanded[i].top;
+      divProperties.paddingRight = expanded[i].right - bounds[i].right;
+      divProperties.paddingBottom = expanded[i].bottom - bounds[i].bottom;
+
+      task._textDivProperties.set(div, divProperties);
+
+      continue;
+    }
+
+    const e = expanded[i],
+          b = bounds[i];
+    const m = b.m,
+          c = m[0],
+          s = m[1];
+    const points = [[0, 0], [0, b.size[1]], [b.size[0], 0], b.size];
+    const ts = new Float64Array(64);
+
+    for (let j = 0, jj = points.length; j < jj; j++) {
+      const t = _util.Util.applyTransform(points[j], m);
+
+      ts[j + 0] = c && (e.left - t[0]) / c;
+      ts[j + 4] = s && (e.top - t[1]) / s;
+      ts[j + 8] = c && (e.right - t[0]) / c;
+      ts[j + 12] = s && (e.bottom - t[1]) / s;
+      ts[j + 16] = s && (e.left - t[0]) / -s;
+      ts[j + 20] = c && (e.top - t[1]) / c;
+      ts[j + 24] = s && (e.right - t[0]) / -s;
+      ts[j + 28] = c && (e.bottom - t[1]) / c;
+      ts[j + 32] = c && (e.left - t[0]) / -c;
+      ts[j + 36] = s && (e.top - t[1]) / -s;
+      ts[j + 40] = c && (e.right - t[0]) / -c;
+      ts[j + 44] = s && (e.bottom - t[1]) / -s;
+      ts[j + 48] = s && (e.left - t[0]) / s;
+      ts[j + 52] = c && (e.top - t[1]) / -c;
+      ts[j + 56] = s && (e.right - t[0]) / s;
+      ts[j + 60] = c && (e.bottom - t[1]) / -c;
+    }
+
+    const boxScale = 1 + Math.min(Math.abs(c), Math.abs(s));
+    divProperties.paddingLeft = findPositiveMin(ts, 32, 16) / boxScale;
+    divProperties.paddingTop = findPositiveMin(ts, 48, 16) / boxScale;
+    divProperties.paddingRight = findPositiveMin(ts, 0, 16) / boxScale;
+    divProperties.paddingBottom = findPositiveMin(ts, 16, 16) / boxScale;
+
+    task._textDivProperties.set(div, divProperties);
+  }
+}
+
+function expandBounds(width, height, boxes) {
+  const bounds = boxes.map(function (box, i) {
+    return {
+      x1: box.left,
+      y1: box.top,
+      x2: box.right,
+      y2: box.bottom,
+      index: i,
+      x1New: undefined,
+      x2New: undefined
+    };
+  });
+  expandBoundsLTR(width, bounds);
+  const expanded = new Array(boxes.length);
+
+  for (const b of bounds) {
+    const i = b.index;
+    expanded[i] = {
+      left: b.x1New,
+      top: 0,
+      right: b.x2New,
+      bottom: 0
+    };
+  }
+
+  boxes.map(function (box, i) {
+    const e = expanded[i],
+          b = bounds[i];
+    b.x1 = box.top;
+    b.y1 = width - e.right;
+    b.x2 = box.bottom;
+    b.y2 = width - e.left;
+    b.index = i;
+    b.x1New = undefined;
+    b.x2New = undefined;
+  });
+  expandBoundsLTR(height, bounds);
+
+  for (const b of bounds) {
+    const i = b.index;
+    expanded[i].top = b.x1New;
+    expanded[i].bottom = b.x2New;
+  }
+
+  return expanded;
+}
+
+function expandBoundsLTR(width, bounds) {
+  bounds.sort(function (a, b) {
+    return a.x1 - b.x1 || a.index - b.index;
+  });
+  const fakeBoundary = {
+    x1: -Infinity,
+    y1: -Infinity,
+    x2: 0,
+    y2: Infinity,
+    index: -1,
+    x1New: 0,
+    x2New: 0
+  };
+  const horizon = [{
+    start: -Infinity,
+    end: Infinity,
+    boundary: fakeBoundary
+  }];
+
+  for (const boundary of bounds) {
+    let i = 0;
+
+    while (i < horizon.length && horizon[i].end <= boundary.y1) {
+      i++;
+    }
+
+    let j = horizon.length - 1;
+
+    while (j >= 0 && horizon[j].start >= boundary.y2) {
+      j--;
+    }
+
+    let horizonPart, affectedBoundary;
+    let q,
+        k,
+        maxXNew = -Infinity;
+
+    for (q = i; q <= j; q++) {
+      horizonPart = horizon[q];
+      affectedBoundary = horizonPart.boundary;
+      let xNew;
+
+      if (affectedBoundary.x2 > boundary.x1) {
+        xNew = affectedBoundary.index > boundary.index ? affectedBoundary.x1New : boundary.x1;
+      } else if (affectedBoundary.x2New === undefined) {
+        xNew = (affectedBoundary.x2 + boundary.x1) / 2;
+      } else {
+        xNew = affectedBoundary.x2New;
+      }
+
+      if (xNew > maxXNew) {
+        maxXNew = xNew;
+      }
+    }
+
+    boundary.x1New = maxXNew;
+
+    for (q = i; q <= j; q++) {
+      horizonPart = horizon[q];
+      affectedBoundary = horizonPart.boundary;
+
+      if (affectedBoundary.x2New === undefined) {
+        if (affectedBoundary.x2 > boundary.x1) {
+          if (affectedBoundary.index > boundary.index) {
+            affectedBoundary.x2New = affectedBoundary.x2;
+          }
+        } else {
+          affectedBoundary.x2New = maxXNew;
+        }
+      } else if (affectedBoundary.x2New > maxXNew) {
+        affectedBoundary.x2New = Math.max(maxXNew, affectedBoundary.x2);
+      }
+    }
+
+    const changedHorizon = [];
+    let lastBoundary = null;
+
+    for (q = i; q <= j; q++) {
+      horizonPart = horizon[q];
+      affectedBoundary = horizonPart.boundary;
+      const useBoundary = affectedBoundary.x2 > boundary.x2 ? affectedBoundary : boundary;
+
+      if (lastBoundary === useBoundary) {
+        changedHorizon[changedHorizon.length - 1].end = horizonPart.end;
+      } else {
+        changedHorizon.push({
+          start: horizonPart.start,
+          end: horizonPart.end,
+          boundary: useBoundary
+        });
+        lastBoundary = useBoundary;
+      }
+    }
+
+    if (horizon[i].start < boundary.y1) {
+      changedHorizon[0].start = boundary.y1;
+      changedHorizon.unshift({
+        start: horizon[i].start,
+        end: boundary.y1,
+        boundary: horizon[i].boundary
+      });
+    }
+
+    if (boundary.y2 < horizon[j].end) {
+      changedHorizon[changedHorizon.length - 1].end = boundary.y2;
+      changedHorizon.push({
+        start: boundary.y2,
+        end: horizon[j].end,
+        boundary: horizon[j].boundary
+      });
+    }
+
+    for (q = i; q <= j; q++) {
+      horizonPart = horizon[q];
+      affectedBoundary = horizonPart.boundary;
+
+      if (affectedBoundary.x2New !== undefined) {
+        continue;
+      }
+
+      let used = false;
+
+      for (k = i - 1; !used && k >= 0 && horizon[k].start >= affectedBoundary.y1; k--) {
+        used = horizon[k].boundary === affectedBoundary;
+      }
+
+      for (k = j + 1; !used && k < horizon.length && horizon[k].end <= affectedBoundary.y2; k++) {
+        used = horizon[k].boundary === affectedBoundary;
+      }
+
+      for (k = 0; !used && k < changedHorizon.length; k++) {
+        used = changedHorizon[k].boundary === affectedBoundary;
+      }
+
+      if (!used) {
+        affectedBoundary.x2New = maxXNew;
+      }
+    }
+
+    Array.prototype.splice.apply(horizon, [i, j - i + 1].concat(changedHorizon));
+  }
+
+  for (const horizonPart of horizon) {
+    const affectedBoundary = horizonPart.boundary;
+
+    if (affectedBoundary.x2New === undefined) {
+      affectedBoundary.x2New = Math.max(width, affectedBoundary.x2);
+    }
+  }
+}
+
+class TextLayerRenderTask {
+  constructor({
+    textContent,
+    textContentStream,
+    container,
+    viewport,
+    textDivs,
+    textContentItemsStr,
+    enhanceTextSelection
+  }) {
+    this._textContent = textContent;
+    this._textContentStream = textContentStream;
+    this._container = container;
+    this._document = container.ownerDocument;
+    this._viewport = viewport;
+    this._textDivs = textDivs || [];
+    this._textContentItemsStr = textContentItemsStr || [];
+    this._enhanceTextSelection = !!enhanceTextSelection;
+    this._fontInspectorEnabled = !!globalThis.FontInspector?.enabled;
+    this._reader = null;
+    this._layoutTextLastFontSize = null;
+    this._layoutTextLastFontFamily = null;
+    this._layoutTextCtx = null;
+    this._textDivProperties = new WeakMap();
+    this._renderingDone = false;
+    this._canceled = false;
+    this._capability = (0, _util.createPromiseCapability)();
+    this._renderTimer = null;
+    this._bounds = [];
+
+    this._capability.promise.finally(() => {
+      if (!this._enhanceTextSelection) {
+        this._textDivProperties = null;
+      }
+
+      if (this._layoutTextCtx) {
+        this._layoutTextCtx.canvas.width = 0;
+        this._layoutTextCtx.canvas.height = 0;
+        this._layoutTextCtx = null;
+      }
+    }).catch(() => {});
+  }
+
+  get promise() {
+    return this._capability.promise;
+  }
+
+  cancel() {
+    this._canceled = true;
+
+    if (this._reader) {
+      this._reader.cancel(new _util.AbortException("TextLayer task cancelled.")).catch(() => {});
+
+      this._reader = null;
+    }
+
+    if (this._renderTimer !== null) {
+      clearTimeout(this._renderTimer);
+      this._renderTimer = null;
+    }
+
+    this._capability.reject(new Error("TextLayer task cancelled."));
+  }
+
+  _processItems(items, styleCache) {
+    for (let i = 0, len = items.length; i < len; i++) {
+      if (items[i].str === undefined) {
+        if (items[i].type === "beginMarkedContentProps" || items[i].type === "beginMarkedContent") {
+          const parent = this._container;
+          this._container = document.createElement("span");
+
+          this._container.classList.add("markedContent");
+
+          if (items[i].id !== null) {
+            this._container.setAttribute("id", `${items[i].id}`);
+          }
+
+          parent.appendChild(this._container);
+        } else if (items[i].type === "endMarkedContent") {
+          this._container = this._container.parentNode;
+        }
+
+        continue;
+      }
+
+      this._textContentItemsStr.push(items[i].str);
+
+      appendText(this, items[i], styleCache, this._layoutTextCtx);
+    }
+  }
+
+  _layoutText(textDiv) {
+    const textDivProperties = this._textDivProperties.get(textDiv);
+
+    let transform = "";
+
+    if (textDivProperties.canvasWidth !== 0 && textDivProperties.hasText) {
+      const {
+        fontSize,
+        fontFamily
+      } = textDiv.style;
+
+      if (fontSize !== this._layoutTextLastFontSize || fontFamily !== this._layoutTextLastFontFamily) {
+        this._layoutTextCtx.font = `${fontSize} ${fontFamily}`;
+        this._layoutTextLastFontSize = fontSize;
+        this._layoutTextLastFontFamily = fontFamily;
+      }
+
+      const {
+        width
+      } = this._layoutTextCtx.measureText(textDiv.textContent);
+
+      if (width > 0) {
+        const scale = textDivProperties.canvasWidth / width;
+
+        if (this._enhanceTextSelection) {
+          textDivProperties.scale = scale;
+        }
+
+        transform = `scaleX(${scale})`;
+      }
+    }
+
+    if (textDivProperties.angle !== 0) {
+      transform = `rotate(${textDivProperties.angle}deg) ${transform}`;
+    }
+
+    if (transform.length > 0) {
+      if (this._enhanceTextSelection) {
+        textDivProperties.originalTransform = transform;
+      }
+
+      textDiv.style.transform = transform;
+    }
+
+    if (textDivProperties.hasText) {
+      this._container.appendChild(textDiv);
+    }
+
+    if (textDivProperties.hasEOL) {
+      const br = document.createElement("br");
+      br.setAttribute("role", "presentation");
+
+      this._container.appendChild(br);
+    }
+  }
+
+  _render(timeout = 0) {
+    const capability = (0, _util.createPromiseCapability)();
+    let styleCache = Object.create(null);
+
+    const canvas = this._document.createElement("canvas");
+
+    canvas.height = canvas.width = DEFAULT_FONT_SIZE;
+    canvas.mozOpaque = true;
+    this._layoutTextCtx = canvas.getContext("2d", {
+      alpha: false
+    });
+
+    if (this._textContent) {
+      const textItems = this._textContent.items;
+      const textStyles = this._textContent.styles;
+
+      this._processItems(textItems, textStyles);
+
+      capability.resolve();
+    } else if (this._textContentStream) {
+      const pump = () => {
+        this._reader.read().then(({
+          value,
+          done
+        }) => {
+          if (done) {
+            capability.resolve();
+            return;
+          }
+
+          Object.assign(styleCache, value.styles);
+
+          this._processItems(value.items, styleCache);
+
+          pump();
+        }, capability.reject);
+      };
+
+      this._reader = this._textContentStream.getReader();
+      pump();
+    } else {
+      throw new Error('Neither "textContent" nor "textContentStream" parameters specified.');
+    }
+
+    capability.promise.then(() => {
+      styleCache = null;
+
+      if (!timeout) {
+        render(this);
+      } else {
+        this._renderTimer = setTimeout(() => {
+          render(this);
+          this._renderTimer = null;
+        }, timeout);
+      }
+    }, this._capability.reject);
+  }
+
+  expandTextDivs(expandDivs = false) {
+    if (!this._enhanceTextSelection || !this._renderingDone) {
+      return;
+    }
+
+    if (this._bounds !== null) {
+      expand(this);
+      this._bounds = null;
+    }
+
+    const transformBuf = [],
+          paddingBuf = [];
+
+    for (let i = 0, ii = this._textDivs.length; i < ii; i++) {
+      const div = this._textDivs[i];
+
+      const divProps = this._textDivProperties.get(div);
+
+      if (!divProps.hasText) {
+        continue;
+      }
+
+      if (expandDivs) {
+        transformBuf.length = 0;
+        paddingBuf.length = 0;
+
+        if (divProps.originalTransform) {
+          transformBuf.push(divProps.originalTransform);
+        }
+
+        if (divProps.paddingTop > 0) {
+          paddingBuf.push(`${divProps.paddingTop}px`);
+          transformBuf.push(`translateY(${-divProps.paddingTop}px)`);
+        } else {
+          paddingBuf.push(0);
+        }
+
+        if (divProps.paddingRight > 0) {
+          paddingBuf.push(`${divProps.paddingRight / divProps.scale}px`);
+        } else {
+          paddingBuf.push(0);
+        }
+
+        if (divProps.paddingBottom > 0) {
+          paddingBuf.push(`${divProps.paddingBottom}px`);
+        } else {
+          paddingBuf.push(0);
+        }
+
+        if (divProps.paddingLeft > 0) {
+          paddingBuf.push(`${divProps.paddingLeft / divProps.scale}px`);
+          transformBuf.push(`translateX(${-divProps.paddingLeft / divProps.scale}px)`);
+        } else {
+          paddingBuf.push(0);
+        }
+
+        div.style.padding = paddingBuf.join(" ");
+
+        if (transformBuf.length) {
+          div.style.transform = transformBuf.join(" ");
+        }
+      } else {
+        div.style.padding = null;
+        div.style.transform = divProps.originalTransform;
+      }
+    }
+  }
+
+}
+
+function renderTextLayer(renderParameters) {
+  const task = new TextLayerRenderTask({
+    textContent: renderParameters.textContent,
+    textContentStream: renderParameters.textContentStream,
+    container: renderParameters.container,
+    viewport: renderParameters.viewport,
+    textDivs: renderParameters.textDivs,
+    textContentItemsStr: renderParameters.textContentItemsStr,
+    enhanceTextSelection: renderParameters.enhanceTextSelection
+  });
+
+  task._render(renderParameters.timeout);
+
+  return task;
+}
+
+/***/ }),
+/* 22 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.SVGGraphics = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+var _display_utils = __w_pdfjs_require__(1);
+
+var _is_node = __w_pdfjs_require__(4);
+
+let SVGGraphics = class {
+  constructor() {
+    (0, _util.unreachable)("Not implemented: SVGGraphics");
+  }
+
+};
+exports.SVGGraphics = SVGGraphics;
+{
+  const SVG_DEFAULTS = {
+    fontStyle: "normal",
+    fontWeight: "normal",
+    fillColor: "#000000"
+  };
+  const XML_NS = "http://www.w3.org/XML/1998/namespace";
+  const XLINK_NS = "http://www.w3.org/1999/xlink";
+  const LINE_CAP_STYLES = ["butt", "round", "square"];
+  const LINE_JOIN_STYLES = ["miter", "round", "bevel"];
+
+  const convertImgDataToPng = function () {
+    const PNG_HEADER = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
+    const CHUNK_WRAPPER_SIZE = 12;
+    const crcTable = new Int32Array(256);
+
+    for (let i = 0; i < 256; i++) {
+      let c = i;
+
+      for (let h = 0; h < 8; h++) {
+        if (c & 1) {
+          c = 0xedb88320 ^ c >> 1 & 0x7fffffff;
+        } else {
+          c = c >> 1 & 0x7fffffff;
+        }
+      }
+
+      crcTable[i] = c;
+    }
+
+    function crc32(data, start, end) {
+      let crc = -1;
+
+      for (let i = start; i < end; i++) {
+        const a = (crc ^ data[i]) & 0xff;
+        const b = crcTable[a];
+        crc = crc >>> 8 ^ b;
+      }
+
+      return crc ^ -1;
+    }
+
+    function writePngChunk(type, body, data, offset) {
+      let p = offset;
+      const len = body.length;
+      data[p] = len >> 24 & 0xff;
+      data[p + 1] = len >> 16 & 0xff;
+      data[p + 2] = len >> 8 & 0xff;
+      data[p + 3] = len & 0xff;
+      p += 4;
+      data[p] = type.charCodeAt(0) & 0xff;
+      data[p + 1] = type.charCodeAt(1) & 0xff;
+      data[p + 2] = type.charCodeAt(2) & 0xff;
+      data[p + 3] = type.charCodeAt(3) & 0xff;
+      p += 4;
+      data.set(body, p);
+      p += body.length;
+      const crc = crc32(data, offset + 4, p);
+      data[p] = crc >> 24 & 0xff;
+      data[p + 1] = crc >> 16 & 0xff;
+      data[p + 2] = crc >> 8 & 0xff;
+      data[p + 3] = crc & 0xff;
+    }
+
+    function adler32(data, start, end) {
+      let a = 1;
+      let b = 0;
+
+      for (let i = start; i < end; ++i) {
+        a = (a + (data[i] & 0xff)) % 65521;
+        b = (b + a) % 65521;
+      }
+
+      return b << 16 | a;
+    }
+
+    function deflateSync(literals) {
+      if (!_is_node.isNodeJS) {
+        return deflateSyncUncompressed(literals);
+      }
+
+      try {
+        let input;
+
+        if (parseInt(process.versions.node) >= 8) {
+          input = literals;
+        } else {
+          input = Buffer.from(literals);
+        }
+
+        const output = require("zlib").deflateSync(input, {
+          level: 9
+        });
+
+        return output instanceof Uint8Array ? output : new Uint8Array(output);
+      } catch (e) {
+        (0, _util.warn)("Not compressing PNG because zlib.deflateSync is unavailable: " + e);
+      }
+
+      return deflateSyncUncompressed(literals);
+    }
+
+    function deflateSyncUncompressed(literals) {
+      let len = literals.length;
+      const maxBlockLength = 0xffff;
+      const deflateBlocks = Math.ceil(len / maxBlockLength);
+      const idat = new Uint8Array(2 + len + deflateBlocks * 5 + 4);
+      let pi = 0;
+      idat[pi++] = 0x78;
+      idat[pi++] = 0x9c;
+      let pos = 0;
+
+      while (len > maxBlockLength) {
+        idat[pi++] = 0x00;
+        idat[pi++] = 0xff;
+        idat[pi++] = 0xff;
+        idat[pi++] = 0x00;
+        idat[pi++] = 0x00;
+        idat.set(literals.subarray(pos, pos + maxBlockLength), pi);
+        pi += maxBlockLength;
+        pos += maxBlockLength;
+        len -= maxBlockLength;
+      }
+
+      idat[pi++] = 0x01;
+      idat[pi++] = len & 0xff;
+      idat[pi++] = len >> 8 & 0xff;
+      idat[pi++] = ~len & 0xffff & 0xff;
+      idat[pi++] = (~len & 0xffff) >> 8 & 0xff;
+      idat.set(literals.subarray(pos), pi);
+      pi += literals.length - pos;
+      const adler = adler32(literals, 0, literals.length);
+      idat[pi++] = adler >> 24 & 0xff;
+      idat[pi++] = adler >> 16 & 0xff;
+      idat[pi++] = adler >> 8 & 0xff;
+      idat[pi++] = adler & 0xff;
+      return idat;
+    }
+
+    function encode(imgData, kind, forceDataSchema, isMask) {
+      const width = imgData.width;
+      const height = imgData.height;
+      let bitDepth, colorType, lineSize;
+      const bytes = imgData.data;
+
+      switch (kind) {
+        case _util.ImageKind.GRAYSCALE_1BPP:
+          colorType = 0;
+          bitDepth = 1;
+          lineSize = width + 7 >> 3;
+          break;
+
+        case _util.ImageKind.RGB_24BPP:
+          colorType = 2;
+          bitDepth = 8;
+          lineSize = width * 3;
+          break;
+
+        case _util.ImageKind.RGBA_32BPP:
+          colorType = 6;
+          bitDepth = 8;
+          lineSize = width * 4;
+          break;
+
+        default:
+          throw new Error("invalid format");
+      }
+
+      const literals = new Uint8Array((1 + lineSize) * height);
+      let offsetLiterals = 0,
+          offsetBytes = 0;
+
+      for (let y = 0; y < height; ++y) {
+        literals[offsetLiterals++] = 0;
+        literals.set(bytes.subarray(offsetBytes, offsetBytes + lineSize), offsetLiterals);
+        offsetBytes += lineSize;
+        offsetLiterals += lineSize;
+      }
+
+      if (kind === _util.ImageKind.GRAYSCALE_1BPP && isMask) {
+        offsetLiterals = 0;
+
+        for (let y = 0; y < height; y++) {
+          offsetLiterals++;
+
+          for (let i = 0; i < lineSize; i++) {
+            literals[offsetLiterals++] ^= 0xff;
+          }
+        }
+      }
+
+      const ihdr = new Uint8Array([width >> 24 & 0xff, width >> 16 & 0xff, width >> 8 & 0xff, width & 0xff, height >> 24 & 0xff, height >> 16 & 0xff, height >> 8 & 0xff, height & 0xff, bitDepth, colorType, 0x00, 0x00, 0x00]);
+      const idat = deflateSync(literals);
+      const pngLength = PNG_HEADER.length + CHUNK_WRAPPER_SIZE * 3 + ihdr.length + idat.length;
+      const data = new Uint8Array(pngLength);
+      let offset = 0;
+      data.set(PNG_HEADER, offset);
+      offset += PNG_HEADER.length;
+      writePngChunk("IHDR", ihdr, data, offset);
+      offset += CHUNK_WRAPPER_SIZE + ihdr.length;
+      writePngChunk("IDATA", idat, data, offset);
+      offset += CHUNK_WRAPPER_SIZE + idat.length;
+      writePngChunk("IEND", new Uint8Array(0), data, offset);
+      return (0, _util.createObjectURL)(data, "image/png", forceDataSchema);
+    }
+
+    return function convertImgDataToPng(imgData, forceDataSchema, isMask) {
+      const kind = imgData.kind === undefined ? _util.ImageKind.GRAYSCALE_1BPP : imgData.kind;
+      return encode(imgData, kind, forceDataSchema, isMask);
+    };
+  }();
+
+  class SVGExtraState {
+    constructor() {
+      this.fontSizeScale = 1;
+      this.fontWeight = SVG_DEFAULTS.fontWeight;
+      this.fontSize = 0;
+      this.textMatrix = _util.IDENTITY_MATRIX;
+      this.fontMatrix = _util.FONT_IDENTITY_MATRIX;
+      this.leading = 0;
+      this.textRenderingMode = _util.TextRenderingMode.FILL;
+      this.textMatrixScale = 1;
+      this.x = 0;
+      this.y = 0;
+      this.lineX = 0;
+      this.lineY = 0;
+      this.charSpacing = 0;
+      this.wordSpacing = 0;
+      this.textHScale = 1;
+      this.textRise = 0;
+      this.fillColor = SVG_DEFAULTS.fillColor;
+      this.strokeColor = "#000000";
+      this.fillAlpha = 1;
+      this.strokeAlpha = 1;
+      this.lineWidth = 1;
+      this.lineJoin = "";
+      this.lineCap = "";
+      this.miterLimit = 0;
+      this.dashArray = [];
+      this.dashPhase = 0;
+      this.dependencies = [];
+      this.activeClipUrl = null;
+      this.clipGroup = null;
+      this.maskId = "";
+    }
+
+    clone() {
+      return Object.create(this);
+    }
+
+    setCurrentPoint(x, y) {
+      this.x = x;
+      this.y = y;
+    }
+
+  }
+
+  function opListToTree(opList) {
+    let opTree = [];
+    const tmp = [];
+
+    for (const opListElement of opList) {
+      if (opListElement.fn === "save") {
+        opTree.push({
+          fnId: 92,
+          fn: "group",
+          items: []
+        });
+        tmp.push(opTree);
+        opTree = opTree[opTree.length - 1].items;
+        continue;
+      }
+
+      if (opListElement.fn === "restore") {
+        opTree = tmp.pop();
+      } else {
+        opTree.push(opListElement);
+      }
+    }
+
+    return opTree;
+  }
+
+  function pf(value) {
+    if (Number.isInteger(value)) {
+      return value.toString();
+    }
+
+    const s = value.toFixed(10);
+    let i = s.length - 1;
+
+    if (s[i] !== "0") {
+      return s;
+    }
+
+    do {
+      i--;
+    } while (s[i] === "0");
+
+    return s.substring(0, s[i] === "." ? i : i + 1);
+  }
+
+  function pm(m) {
+    if (m[4] === 0 && m[5] === 0) {
+      if (m[1] === 0 && m[2] === 0) {
+        if (m[0] === 1 && m[3] === 1) {
+          return "";
+        }
+
+        return `scale(${pf(m[0])} ${pf(m[3])})`;
+      }
+
+      if (m[0] === m[3] && m[1] === -m[2]) {
+        const a = Math.acos(m[0]) * 180 / Math.PI;
+        return `rotate(${pf(a)})`;
+      }
+    } else {
+      if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1) {
+        return `translate(${pf(m[4])} ${pf(m[5])})`;
+      }
+    }
+
+    return `matrix(${pf(m[0])} ${pf(m[1])} ${pf(m[2])} ${pf(m[3])} ${pf(m[4])} ` + `${pf(m[5])})`;
+  }
+
+  let clipCount = 0;
+  let maskCount = 0;
+  let shadingCount = 0;
+  exports.SVGGraphics = SVGGraphics = class {
+    constructor(commonObjs, objs, forceDataSchema = false) {
+      this.svgFactory = new _display_utils.DOMSVGFactory();
+      this.current = new SVGExtraState();
+      this.transformMatrix = _util.IDENTITY_MATRIX;
+      this.transformStack = [];
+      this.extraStack = [];
+      this.commonObjs = commonObjs;
+      this.objs = objs;
+      this.pendingClip = null;
+      this.pendingEOFill = false;
+      this.embedFonts = false;
+      this.embeddedFonts = Object.create(null);
+      this.cssStyle = null;
+      this.forceDataSchema = !!forceDataSchema;
+      this._operatorIdMapping = [];
+
+      for (const op in _util.OPS) {
+        this._operatorIdMapping[_util.OPS[op]] = op;
+      }
+    }
+
+    save() {
+      this.transformStack.push(this.transformMatrix);
+      const old = this.current;
+      this.extraStack.push(old);
+      this.current = old.clone();
+    }
+
+    restore() {
+      this.transformMatrix = this.transformStack.pop();
+      this.current = this.extraStack.pop();
+      this.pendingClip = null;
+      this.tgrp = null;
+    }
+
+    group(items) {
+      this.save();
+      this.executeOpTree(items);
+      this.restore();
+    }
+
+    loadDependencies(operatorList) {
+      const fnArray = operatorList.fnArray;
+      const argsArray = operatorList.argsArray;
+
+      for (let i = 0, ii = fnArray.length; i < ii; i++) {
+        if (fnArray[i] !== _util.OPS.dependency) {
+          continue;
+        }
+
+        for (const obj of argsArray[i]) {
+          const objsPool = obj.startsWith("g_") ? this.commonObjs : this.objs;
+          const promise = new Promise(resolve => {
+            objsPool.get(obj, resolve);
+          });
+          this.current.dependencies.push(promise);
+        }
+      }
+
+      return Promise.all(this.current.dependencies);
+    }
+
+    transform(a, b, c, d, e, f) {
+      const transformMatrix = [a, b, c, d, e, f];
+      this.transformMatrix = _util.Util.transform(this.transformMatrix, transformMatrix);
+      this.tgrp = null;
+    }
+
+    getSVG(operatorList, viewport) {
+      this.viewport = viewport;
+
+      const svgElement = this._initialize(viewport);
+
+      return this.loadDependencies(operatorList).then(() => {
+        this.transformMatrix = _util.IDENTITY_MATRIX;
+        this.executeOpTree(this.convertOpList(operatorList));
+        return svgElement;
+      });
+    }
+
+    convertOpList(operatorList) {
+      const operatorIdMapping = this._operatorIdMapping;
+      const argsArray = operatorList.argsArray;
+      const fnArray = operatorList.fnArray;
+      const opList = [];
+
+      for (let i = 0, ii = fnArray.length; i < ii; i++) {
+        const fnId = fnArray[i];
+        opList.push({
+          fnId,
+          fn: operatorIdMapping[fnId],
+          args: argsArray[i]
+        });
+      }
+
+      return opListToTree(opList);
+    }
+
+    executeOpTree(opTree) {
+      for (const opTreeElement of opTree) {
+        const fn = opTreeElement.fn;
+        const fnId = opTreeElement.fnId;
+        const args = opTreeElement.args;
+
+        switch (fnId | 0) {
+          case _util.OPS.beginText:
+            this.beginText();
+            break;
+
+          case _util.OPS.dependency:
+            break;
+
+          case _util.OPS.setLeading:
+            this.setLeading(args);
+            break;
+
+          case _util.OPS.setLeadingMoveText:
+            this.setLeadingMoveText(args[0], args[1]);
+            break;
+
+          case _util.OPS.setFont:
+            this.setFont(args);
+            break;
+
+          case _util.OPS.showText:
+            this.showText(args[0]);
+            break;
+
+          case _util.OPS.showSpacedText:
+            this.showText(args[0]);
+            break;
+
+          case _util.OPS.endText:
+            this.endText();
+            break;
+
+          case _util.OPS.moveText:
+            this.moveText(args[0], args[1]);
+            break;
+
+          case _util.OPS.setCharSpacing:
+            this.setCharSpacing(args[0]);
+            break;
+
+          case _util.OPS.setWordSpacing:
+            this.setWordSpacing(args[0]);
+            break;
+
+          case _util.OPS.setHScale:
+            this.setHScale(args[0]);
+            break;
+
+          case _util.OPS.setTextMatrix:
+            this.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
+            break;
+
+          case _util.OPS.setTextRise:
+            this.setTextRise(args[0]);
+            break;
+
+          case _util.OPS.setTextRenderingMode:
+            this.setTextRenderingMode(args[0]);
+            break;
+
+          case _util.OPS.setLineWidth:
+            this.setLineWidth(args[0]);
+            break;
+
+          case _util.OPS.setLineJoin:
+            this.setLineJoin(args[0]);
+            break;
+
+          case _util.OPS.setLineCap:
+            this.setLineCap(args[0]);
+            break;
+
+          case _util.OPS.setMiterLimit:
+            this.setMiterLimit(args[0]);
+            break;
+
+          case _util.OPS.setFillRGBColor:
+            this.setFillRGBColor(args[0], args[1], args[2]);
+            break;
+
+          case _util.OPS.setStrokeRGBColor:
+            this.setStrokeRGBColor(args[0], args[1], args[2]);
+            break;
+
+          case _util.OPS.setStrokeColorN:
+            this.setStrokeColorN(args);
+            break;
+
+          case _util.OPS.setFillColorN:
+            this.setFillColorN(args);
+            break;
+
+          case _util.OPS.shadingFill:
+            this.shadingFill(args[0]);
+            break;
+
+          case _util.OPS.setDash:
+            this.setDash(args[0], args[1]);
+            break;
+
+          case _util.OPS.setRenderingIntent:
+            this.setRenderingIntent(args[0]);
+            break;
+
+          case _util.OPS.setFlatness:
+            this.setFlatness(args[0]);
+            break;
+
+          case _util.OPS.setGState:
+            this.setGState(args[0]);
+            break;
+
+          case _util.OPS.fill:
+            this.fill();
+            break;
+
+          case _util.OPS.eoFill:
+            this.eoFill();
+            break;
+
+          case _util.OPS.stroke:
+            this.stroke();
+            break;
+
+          case _util.OPS.fillStroke:
+            this.fillStroke();
+            break;
+
+          case _util.OPS.eoFillStroke:
+            this.eoFillStroke();
+            break;
+
+          case _util.OPS.clip:
+            this.clip("nonzero");
+            break;
+
+          case _util.OPS.eoClip:
+            this.clip("evenodd");
+            break;
+
+          case _util.OPS.paintSolidColorImageMask:
+            this.paintSolidColorImageMask();
+            break;
+
+          case _util.OPS.paintImageXObject:
+            this.paintImageXObject(args[0]);
+            break;
+
+          case _util.OPS.paintInlineImageXObject:
+            this.paintInlineImageXObject(args[0]);
+            break;
+
+          case _util.OPS.paintImageMaskXObject:
+            this.paintImageMaskXObject(args[0]);
+            break;
+
+          case _util.OPS.paintFormXObjectBegin:
+            this.paintFormXObjectBegin(args[0], args[1]);
+            break;
+
+          case _util.OPS.paintFormXObjectEnd:
+            this.paintFormXObjectEnd();
+            break;
+
+          case _util.OPS.closePath:
+            this.closePath();
+            break;
+
+          case _util.OPS.closeStroke:
+            this.closeStroke();
+            break;
+
+          case _util.OPS.closeFillStroke:
+            this.closeFillStroke();
+            break;
+
+          case _util.OPS.closeEOFillStroke:
+            this.closeEOFillStroke();
+            break;
+
+          case _util.OPS.nextLine:
+            this.nextLine();
+            break;
+
+          case _util.OPS.transform:
+            this.transform(args[0], args[1], args[2], args[3], args[4], args[5]);
+            break;
+
+          case _util.OPS.constructPath:
+            this.constructPath(args[0], args[1]);
+            break;
+
+          case _util.OPS.endPath:
+            this.endPath();
+            break;
+
+          case 92:
+            this.group(opTreeElement.items);
+            break;
+
+          default:
+            (0, _util.warn)(`Unimplemented operator ${fn}`);
+            break;
+        }
+      }
+    }
+
+    setWordSpacing(wordSpacing) {
+      this.current.wordSpacing = wordSpacing;
+    }
+
+    setCharSpacing(charSpacing) {
+      this.current.charSpacing = charSpacing;
+    }
+
+    nextLine() {
+      this.moveText(0, this.current.leading);
+    }
+
+    setTextMatrix(a, b, c, d, e, f) {
+      const current = this.current;
+      current.textMatrix = current.lineMatrix = [a, b, c, d, e, f];
+      current.textMatrixScale = Math.hypot(a, b);
+      current.x = current.lineX = 0;
+      current.y = current.lineY = 0;
+      current.xcoords = [];
+      current.ycoords = [];
+      current.tspan = this.svgFactory.createElement("svg:tspan");
+      current.tspan.setAttributeNS(null, "font-family", current.fontFamily);
+      current.tspan.setAttributeNS(null, "font-size", `${pf(current.fontSize)}px`);
+      current.tspan.setAttributeNS(null, "y", pf(-current.y));
+      current.txtElement = this.svgFactory.createElement("svg:text");
+      current.txtElement.appendChild(current.tspan);
+    }
+
+    beginText() {
+      const current = this.current;
+      current.x = current.lineX = 0;
+      current.y = current.lineY = 0;
+      current.textMatrix = _util.IDENTITY_MATRIX;
+      current.lineMatrix = _util.IDENTITY_MATRIX;
+      current.textMatrixScale = 1;
+      current.tspan = this.svgFactory.createElement("svg:tspan");
+      current.txtElement = this.svgFactory.createElement("svg:text");
+      current.txtgrp = this.svgFactory.createElement("svg:g");
+      current.xcoords = [];
+      current.ycoords = [];
+    }
+
+    moveText(x, y) {
+      const current = this.current;
+      current.x = current.lineX += x;
+      current.y = current.lineY += y;
+      current.xcoords = [];
+      current.ycoords = [];
+      current.tspan = this.svgFactory.createElement("svg:tspan");
+      current.tspan.setAttributeNS(null, "font-family", current.fontFamily);
+      current.tspan.setAttributeNS(null, "font-size", `${pf(current.fontSize)}px`);
+      current.tspan.setAttributeNS(null, "y", pf(-current.y));
+    }
+
+    showText(glyphs) {
+      const current = this.current;
+      const font = current.font;
+      const fontSize = current.fontSize;
+
+      if (fontSize === 0) {
+        return;
+      }
+
+      const fontSizeScale = current.fontSizeScale;
+      const charSpacing = current.charSpacing;
+      const wordSpacing = current.wordSpacing;
+      const fontDirection = current.fontDirection;
+      const textHScale = current.textHScale * fontDirection;
+      const vertical = font.vertical;
+      const spacingDir = vertical ? 1 : -1;
+      const defaultVMetrics = font.defaultVMetrics;
+      const widthAdvanceScale = fontSize * current.fontMatrix[0];
+      let x = 0;
+
+      for (const glyph of glyphs) {
+        if (glyph === null) {
+          x += fontDirection * wordSpacing;
+          continue;
+        } else if ((0, _util.isNum)(glyph)) {
+          x += spacingDir * glyph * fontSize / 1000;
+          continue;
+        }
+
+        const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
+        const character = glyph.fontChar;
+        let scaledX, scaledY;
+        let width = glyph.width;
+
+        if (vertical) {
+          let vx;
+          const vmetric = glyph.vmetric || defaultVMetrics;
+          vx = glyph.vmetric ? vmetric[1] : width * 0.5;
+          vx = -vx * widthAdvanceScale;
+          const vy = vmetric[2] * widthAdvanceScale;
+          width = vmetric ? -vmetric[0] : width;
+          scaledX = vx / fontSizeScale;
+          scaledY = (x + vy) / fontSizeScale;
+        } else {
+          scaledX = x / fontSizeScale;
+          scaledY = 0;
+        }
+
+        if (glyph.isInFont || font.missingFile) {
+          current.xcoords.push(current.x + scaledX);
+
+          if (vertical) {
+            current.ycoords.push(-current.y + scaledY);
+          }
+
+          current.tspan.textContent += character;
+        } else {}
+
+        let charWidth;
+
+        if (vertical) {
+          charWidth = width * widthAdvanceScale - spacing * fontDirection;
+        } else {
+          charWidth = width * widthAdvanceScale + spacing * fontDirection;
+        }
+
+        x += charWidth;
+      }
+
+      current.tspan.setAttributeNS(null, "x", current.xcoords.map(pf).join(" "));
+
+      if (vertical) {
+        current.tspan.setAttributeNS(null, "y", current.ycoords.map(pf).join(" "));
+      } else {
+        current.tspan.setAttributeNS(null, "y", pf(-current.y));
+      }
+
+      if (vertical) {
+        current.y -= x;
+      } else {
+        current.x += x * textHScale;
+      }
+
+      current.tspan.setAttributeNS(null, "font-family", current.fontFamily);
+      current.tspan.setAttributeNS(null, "font-size", `${pf(current.fontSize)}px`);
+
+      if (current.fontStyle !== SVG_DEFAULTS.fontStyle) {
+        current.tspan.setAttributeNS(null, "font-style", current.fontStyle);
+      }
+
+      if (current.fontWeight !== SVG_DEFAULTS.fontWeight) {
+        current.tspan.setAttributeNS(null, "font-weight", current.fontWeight);
+      }
+
+      const fillStrokeMode = current.textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK;
+
+      if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+        if (current.fillColor !== SVG_DEFAULTS.fillColor) {
+          current.tspan.setAttributeNS(null, "fill", current.fillColor);
+        }
+
+        if (current.fillAlpha < 1) {
+          current.tspan.setAttributeNS(null, "fill-opacity", current.fillAlpha);
+        }
+      } else if (current.textRenderingMode === _util.TextRenderingMode.ADD_TO_PATH) {
+        current.tspan.setAttributeNS(null, "fill", "transparent");
+      } else {
+        current.tspan.setAttributeNS(null, "fill", "none");
+      }
+
+      if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+        const lineWidthScale = 1 / (current.textMatrixScale || 1);
+
+        this._setStrokeAttributes(current.tspan, lineWidthScale);
+      }
+
+      let textMatrix = current.textMatrix;
+
+      if (current.textRise !== 0) {
+        textMatrix = textMatrix.slice();
+        textMatrix[5] += current.textRise;
+      }
+
+      current.txtElement.setAttributeNS(null, "transform", `${pm(textMatrix)} scale(${pf(textHScale)}, -1)`);
+      current.txtElement.setAttributeNS(XML_NS, "xml:space", "preserve");
+      current.txtElement.appendChild(current.tspan);
+      current.txtgrp.appendChild(current.txtElement);
+
+      this._ensureTransformGroup().appendChild(current.txtElement);
+    }
+
+    setLeadingMoveText(x, y) {
+      this.setLeading(-y);
+      this.moveText(x, y);
+    }
+
+    addFontStyle(fontObj) {
+      if (!fontObj.data) {
+        throw new Error("addFontStyle: No font data available, " + 'ensure that the "fontExtraProperties" API parameter is set.');
+      }
+
+      if (!this.cssStyle) {
+        this.cssStyle = this.svgFactory.createElement("svg:style");
+        this.cssStyle.setAttributeNS(null, "type", "text/css");
+        this.defs.appendChild(this.cssStyle);
+      }
+
+      const url = (0, _util.createObjectURL)(fontObj.data, fontObj.mimetype, this.forceDataSchema);
+      this.cssStyle.textContent += `@font-face { font-family: "${fontObj.loadedName}";` + ` src: url(${url}); }\n`;
+    }
+
+    setFont(details) {
+      const current = this.current;
+      const fontObj = this.commonObjs.get(details[0]);
+      let size = details[1];
+      current.font = fontObj;
+
+      if (this.embedFonts && !fontObj.missingFile && !this.embeddedFonts[fontObj.loadedName]) {
+        this.addFontStyle(fontObj);
+        this.embeddedFonts[fontObj.loadedName] = fontObj;
+      }
+
+      current.fontMatrix = fontObj.fontMatrix || _util.FONT_IDENTITY_MATRIX;
+      let bold = "normal";
+
+      if (fontObj.black) {
+        bold = "900";
+      } else if (fontObj.bold) {
+        bold = "bold";
+      }
+
+      const italic = fontObj.italic ? "italic" : "normal";
+
+      if (size < 0) {
+        size = -size;
+        current.fontDirection = -1;
+      } else {
+        current.fontDirection = 1;
+      }
+
+      current.fontSize = size;
+      current.fontFamily = fontObj.loadedName;
+      current.fontWeight = bold;
+      current.fontStyle = italic;
+      current.tspan = this.svgFactory.createElement("svg:tspan");
+      current.tspan.setAttributeNS(null, "y", pf(-current.y));
+      current.xcoords = [];
+      current.ycoords = [];
+    }
+
+    endText() {
+      const current = this.current;
+
+      if (current.textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG && current.txtElement?.hasChildNodes()) {
+        current.element = current.txtElement;
+        this.clip("nonzero");
+        this.endPath();
+      }
+    }
+
+    setLineWidth(width) {
+      if (width > 0) {
+        this.current.lineWidth = width;
+      }
+    }
+
+    setLineCap(style) {
+      this.current.lineCap = LINE_CAP_STYLES[style];
+    }
+
+    setLineJoin(style) {
+      this.current.lineJoin = LINE_JOIN_STYLES[style];
+    }
+
+    setMiterLimit(limit) {
+      this.current.miterLimit = limit;
+    }
+
+    setStrokeAlpha(strokeAlpha) {
+      this.current.strokeAlpha = strokeAlpha;
+    }
+
+    setStrokeRGBColor(r, g, b) {
+      this.current.strokeColor = _util.Util.makeHexColor(r, g, b);
+    }
+
+    setFillAlpha(fillAlpha) {
+      this.current.fillAlpha = fillAlpha;
+    }
+
+    setFillRGBColor(r, g, b) {
+      this.current.fillColor = _util.Util.makeHexColor(r, g, b);
+      this.current.tspan = this.svgFactory.createElement("svg:tspan");
+      this.current.xcoords = [];
+      this.current.ycoords = [];
+    }
+
+    setStrokeColorN(args) {
+      this.current.strokeColor = this._makeColorN_Pattern(args);
+    }
+
+    setFillColorN(args) {
+      this.current.fillColor = this._makeColorN_Pattern(args);
+    }
+
+    shadingFill(args) {
+      const width = this.viewport.width;
+      const height = this.viewport.height;
+
+      const inv = _util.Util.inverseTransform(this.transformMatrix);
+
+      const bl = _util.Util.applyTransform([0, 0], inv);
+
+      const br = _util.Util.applyTransform([0, height], inv);
+
+      const ul = _util.Util.applyTransform([width, 0], inv);
+
+      const ur = _util.Util.applyTransform([width, height], inv);
+
+      const x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
+      const y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
+      const x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
+      const y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
+      const rect = this.svgFactory.createElement("svg:rect");
+      rect.setAttributeNS(null, "x", x0);
+      rect.setAttributeNS(null, "y", y0);
+      rect.setAttributeNS(null, "width", x1 - x0);
+      rect.setAttributeNS(null, "height", y1 - y0);
+      rect.setAttributeNS(null, "fill", this._makeShadingPattern(args));
+
+      if (this.current.fillAlpha < 1) {
+        rect.setAttributeNS(null, "fill-opacity", this.current.fillAlpha);
+      }
+
+      this._ensureTransformGroup().appendChild(rect);
+    }
+
+    _makeColorN_Pattern(args) {
+      if (args[0] === "TilingPattern") {
+        return this._makeTilingPattern(args);
+      }
+
+      return this._makeShadingPattern(args);
+    }
+
+    _makeTilingPattern(args) {
+      const color = args[1];
+      const operatorList = args[2];
+      const matrix = args[3] || _util.IDENTITY_MATRIX;
+      const [x0, y0, x1, y1] = args[4];
+      const xstep = args[5];
+      const ystep = args[6];
+      const paintType = args[7];
+      const tilingId = `shading${shadingCount++}`;
+
+      const [tx0, ty0, tx1, ty1] = _util.Util.normalizeRect([..._util.Util.applyTransform([x0, y0], matrix), ..._util.Util.applyTransform([x1, y1], matrix)]);
+
+      const [xscale, yscale] = _util.Util.singularValueDecompose2dScale(matrix);
+
+      const txstep = xstep * xscale;
+      const tystep = ystep * yscale;
+      const tiling = this.svgFactory.createElement("svg:pattern");
+      tiling.setAttributeNS(null, "id", tilingId);
+      tiling.setAttributeNS(null, "patternUnits", "userSpaceOnUse");
+      tiling.setAttributeNS(null, "width", txstep);
+      tiling.setAttributeNS(null, "height", tystep);
+      tiling.setAttributeNS(null, "x", `${tx0}`);
+      tiling.setAttributeNS(null, "y", `${ty0}`);
+      const svg = this.svg;
+      const transformMatrix = this.transformMatrix;
+      const fillColor = this.current.fillColor;
+      const strokeColor = this.current.strokeColor;
+      const bbox = this.svgFactory.create(tx1 - tx0, ty1 - ty0);
+      this.svg = bbox;
+      this.transformMatrix = matrix;
+
+      if (paintType === 2) {
+        const cssColor = _util.Util.makeHexColor(...color);
+
+        this.current.fillColor = cssColor;
+        this.current.strokeColor = cssColor;
+      }
+
+      this.executeOpTree(this.convertOpList(operatorList));
+      this.svg = svg;
+      this.transformMatrix = transformMatrix;
+      this.current.fillColor = fillColor;
+      this.current.strokeColor = strokeColor;
+      tiling.appendChild(bbox.childNodes[0]);
+      this.defs.appendChild(tiling);
+      return `url(#${tilingId})`;
+    }
+
+    _makeShadingPattern(args) {
+      if (typeof args === "string") {
+        args = this.objs.get(args);
+      }
+
+      switch (args[0]) {
+        case "RadialAxial":
+          const shadingId = `shading${shadingCount++}`;
+          const colorStops = args[3];
+          let gradient;
+
+          switch (args[1]) {
+            case "axial":
+              const point0 = args[4];
+              const point1 = args[5];
+              gradient = this.svgFactory.createElement("svg:linearGradient");
+              gradient.setAttributeNS(null, "id", shadingId);
+              gradient.setAttributeNS(null, "gradientUnits", "userSpaceOnUse");
+              gradient.setAttributeNS(null, "x1", point0[0]);
+              gradient.setAttributeNS(null, "y1", point0[1]);
+              gradient.setAttributeNS(null, "x2", point1[0]);
+              gradient.setAttributeNS(null, "y2", point1[1]);
+              break;
+
+            case "radial":
+              const focalPoint = args[4];
+              const circlePoint = args[5];
+              const focalRadius = args[6];
+              const circleRadius = args[7];
+              gradient = this.svgFactory.createElement("svg:radialGradient");
+              gradient.setAttributeNS(null, "id", shadingId);
+              gradient.setAttributeNS(null, "gradientUnits", "userSpaceOnUse");
+              gradient.setAttributeNS(null, "cx", circlePoint[0]);
+              gradient.setAttributeNS(null, "cy", circlePoint[1]);
+              gradient.setAttributeNS(null, "r", circleRadius);
+              gradient.setAttributeNS(null, "fx", focalPoint[0]);
+              gradient.setAttributeNS(null, "fy", focalPoint[1]);
+              gradient.setAttributeNS(null, "fr", focalRadius);
+              break;
+
+            default:
+              throw new Error(`Unknown RadialAxial type: ${args[1]}`);
+          }
+
+          for (const colorStop of colorStops) {
+            const stop = this.svgFactory.createElement("svg:stop");
+            stop.setAttributeNS(null, "offset", colorStop[0]);
+            stop.setAttributeNS(null, "stop-color", colorStop[1]);
+            gradient.appendChild(stop);
+          }
+
+          this.defs.appendChild(gradient);
+          return `url(#${shadingId})`;
+
+        case "Mesh":
+          (0, _util.warn)("Unimplemented pattern Mesh");
+          return null;
+
+        case "Dummy":
+          return "hotpink";
+
+        default:
+          throw new Error(`Unknown IR type: ${args[0]}`);
+      }
+    }
+
+    setDash(dashArray, dashPhase) {
+      this.current.dashArray = dashArray;
+      this.current.dashPhase = dashPhase;
+    }
+
+    constructPath(ops, args) {
+      const current = this.current;
+      let x = current.x,
+          y = current.y;
+      let d = [];
+      let j = 0;
+
+      for (const op of ops) {
+        switch (op | 0) {
+          case _util.OPS.rectangle:
+            x = args[j++];
+            y = args[j++];
+            const width = args[j++];
+            const height = args[j++];
+            const xw = x + width;
+            const yh = y + height;
+            d.push("M", pf(x), pf(y), "L", pf(xw), pf(y), "L", pf(xw), pf(yh), "L", pf(x), pf(yh), "Z");
+            break;
+
+          case _util.OPS.moveTo:
+            x = args[j++];
+            y = args[j++];
+            d.push("M", pf(x), pf(y));
+            break;
+
+          case _util.OPS.lineTo:
+            x = args[j++];
+            y = args[j++];
+            d.push("L", pf(x), pf(y));
+            break;
+
+          case _util.OPS.curveTo:
+            x = args[j + 4];
+            y = args[j + 5];
+            d.push("C", pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), pf(args[j + 3]), pf(x), pf(y));
+            j += 6;
+            break;
+
+          case _util.OPS.curveTo2:
+            d.push("C", pf(x), pf(y), pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), pf(args[j + 3]));
+            x = args[j + 2];
+            y = args[j + 3];
+            j += 4;
+            break;
+
+          case _util.OPS.curveTo3:
+            x = args[j + 2];
+            y = args[j + 3];
+            d.push("C", pf(args[j]), pf(args[j + 1]), pf(x), pf(y), pf(x), pf(y));
+            j += 4;
+            break;
+
+          case _util.OPS.closePath:
+            d.push("Z");
+            break;
+        }
+      }
+
+      d = d.join(" ");
+
+      if (current.path && ops.length > 0 && ops[0] !== _util.OPS.rectangle && ops[0] !== _util.OPS.moveTo) {
+        d = current.path.getAttributeNS(null, "d") + d;
+      } else {
+        current.path = this.svgFactory.createElement("svg:path");
+
+        this._ensureTransformGroup().appendChild(current.path);
+      }
+
+      current.path.setAttributeNS(null, "d", d);
+      current.path.setAttributeNS(null, "fill", "none");
+      current.element = current.path;
+      current.setCurrentPoint(x, y);
+    }
+
+    endPath() {
+      const current = this.current;
+      current.path = null;
+
+      if (!this.pendingClip) {
+        return;
+      }
+
+      if (!current.element) {
+        this.pendingClip = null;
+        return;
+      }
+
+      const clipId = `clippath${clipCount++}`;
+      const clipPath = this.svgFactory.createElement("svg:clipPath");
+      clipPath.setAttributeNS(null, "id", clipId);
+      clipPath.setAttributeNS(null, "transform", pm(this.transformMatrix));
+      const clipElement = current.element.cloneNode(true);
+
+      if (this.pendingClip === "evenodd") {
+        clipElement.setAttributeNS(null, "clip-rule", "evenodd");
+      } else {
+        clipElement.setAttributeNS(null, "clip-rule", "nonzero");
+      }
+
+      this.pendingClip = null;
+      clipPath.appendChild(clipElement);
+      this.defs.appendChild(clipPath);
+
+      if (current.activeClipUrl) {
+        current.clipGroup = null;
+
+        for (const prev of this.extraStack) {
+          prev.clipGroup = null;
+        }
+
+        clipPath.setAttributeNS(null, "clip-path", current.activeClipUrl);
+      }
+
+      current.activeClipUrl = `url(#${clipId})`;
+      this.tgrp = null;
+    }
+
+    clip(type) {
+      this.pendingClip = type;
+    }
+
+    closePath() {
+      const current = this.current;
+
+      if (current.path) {
+        const d = `${current.path.getAttributeNS(null, "d")}Z`;
+        current.path.setAttributeNS(null, "d", d);
+      }
+    }
+
+    setLeading(leading) {
+      this.current.leading = -leading;
+    }
+
+    setTextRise(textRise) {
+      this.current.textRise = textRise;
+    }
+
+    setTextRenderingMode(textRenderingMode) {
+      this.current.textRenderingMode = textRenderingMode;
+    }
+
+    setHScale(scale) {
+      this.current.textHScale = scale / 100;
+    }
+
+    setRenderingIntent(intent) {}
+
+    setFlatness(flatness) {}
+
+    setGState(states) {
+      for (const [key, value] of states) {
+        switch (key) {
+          case "LW":
+            this.setLineWidth(value);
+            break;
+
+          case "LC":
+            this.setLineCap(value);
+            break;
+
+          case "LJ":
+            this.setLineJoin(value);
+            break;
+
+          case "ML":
+            this.setMiterLimit(value);
+            break;
+
+          case "D":
+            this.setDash(value[0], value[1]);
+            break;
+
+          case "RI":
+            this.setRenderingIntent(value);
+            break;
+
+          case "FL":
+            this.setFlatness(value);
+            break;
+
+          case "Font":
+            this.setFont(value);
+            break;
+
+          case "CA":
+            this.setStrokeAlpha(value);
+            break;
+
+          case "ca":
+            this.setFillAlpha(value);
+            break;
+
+          default:
+            (0, _util.warn)(`Unimplemented graphic state operator ${key}`);
+            break;
+        }
+      }
+    }
+
+    fill() {
+      const current = this.current;
+
+      if (current.element) {
+        current.element.setAttributeNS(null, "fill", current.fillColor);
+        current.element.setAttributeNS(null, "fill-opacity", current.fillAlpha);
+        this.endPath();
+      }
+    }
+
+    stroke() {
+      const current = this.current;
+
+      if (current.element) {
+        this._setStrokeAttributes(current.element);
+
+        current.element.setAttributeNS(null, "fill", "none");
+        this.endPath();
+      }
+    }
+
+    _setStrokeAttributes(element, lineWidthScale = 1) {
+      const current = this.current;
+      let dashArray = current.dashArray;
+
+      if (lineWidthScale !== 1 && dashArray.length > 0) {
+        dashArray = dashArray.map(function (value) {
+          return lineWidthScale * value;
+        });
+      }
+
+      element.setAttributeNS(null, "stroke", current.strokeColor);
+      element.setAttributeNS(null, "stroke-opacity", current.strokeAlpha);
+      element.setAttributeNS(null, "stroke-miterlimit", pf(current.miterLimit));
+      element.setAttributeNS(null, "stroke-linecap", current.lineCap);
+      element.setAttributeNS(null, "stroke-linejoin", current.lineJoin);
+      element.setAttributeNS(null, "stroke-width", pf(lineWidthScale * current.lineWidth) + "px");
+      element.setAttributeNS(null, "stroke-dasharray", dashArray.map(pf).join(" "));
+      element.setAttributeNS(null, "stroke-dashoffset", pf(lineWidthScale * current.dashPhase) + "px");
+    }
+
+    eoFill() {
+      if (this.current.element) {
+        this.current.element.setAttributeNS(null, "fill-rule", "evenodd");
+      }
+
+      this.fill();
+    }
+
+    fillStroke() {
+      this.stroke();
+      this.fill();
+    }
+
+    eoFillStroke() {
+      if (this.current.element) {
+        this.current.element.setAttributeNS(null, "fill-rule", "evenodd");
+      }
+
+      this.fillStroke();
+    }
+
+    closeStroke() {
+      this.closePath();
+      this.stroke();
+    }
+
+    closeFillStroke() {
+      this.closePath();
+      this.fillStroke();
+    }
+
+    closeEOFillStroke() {
+      this.closePath();
+      this.eoFillStroke();
+    }
+
+    paintSolidColorImageMask() {
+      const rect = this.svgFactory.createElement("svg:rect");
+      rect.setAttributeNS(null, "x", "0");
+      rect.setAttributeNS(null, "y", "0");
+      rect.setAttributeNS(null, "width", "1px");
+      rect.setAttributeNS(null, "height", "1px");
+      rect.setAttributeNS(null, "fill", this.current.fillColor);
+
+      this._ensureTransformGroup().appendChild(rect);
+    }
+
+    paintImageXObject(objId) {
+      const imgData = objId.startsWith("g_") ? this.commonObjs.get(objId) : this.objs.get(objId);
+
+      if (!imgData) {
+        (0, _util.warn)(`Dependent image with object ID ${objId} is not ready yet`);
+        return;
+      }
+
+      this.paintInlineImageXObject(imgData);
+    }
+
+    paintInlineImageXObject(imgData, mask) {
+      const width = imgData.width;
+      const height = imgData.height;
+      const imgSrc = convertImgDataToPng(imgData, this.forceDataSchema, !!mask);
+      const cliprect = this.svgFactory.createElement("svg:rect");
+      cliprect.setAttributeNS(null, "x", "0");
+      cliprect.setAttributeNS(null, "y", "0");
+      cliprect.setAttributeNS(null, "width", pf(width));
+      cliprect.setAttributeNS(null, "height", pf(height));
+      this.current.element = cliprect;
+      this.clip("nonzero");
+      const imgEl = this.svgFactory.createElement("svg:image");
+      imgEl.setAttributeNS(XLINK_NS, "xlink:href", imgSrc);
+      imgEl.setAttributeNS(null, "x", "0");
+      imgEl.setAttributeNS(null, "y", pf(-height));
+      imgEl.setAttributeNS(null, "width", pf(width) + "px");
+      imgEl.setAttributeNS(null, "height", pf(height) + "px");
+      imgEl.setAttributeNS(null, "transform", `scale(${pf(1 / width)} ${pf(-1 / height)})`);
+
+      if (mask) {
+        mask.appendChild(imgEl);
+      } else {
+        this._ensureTransformGroup().appendChild(imgEl);
+      }
+    }
+
+    paintImageMaskXObject(imgData) {
+      const current = this.current;
+      const width = imgData.width;
+      const height = imgData.height;
+      const fillColor = current.fillColor;
+      current.maskId = `mask${maskCount++}`;
+      const mask = this.svgFactory.createElement("svg:mask");
+      mask.setAttributeNS(null, "id", current.maskId);
+      const rect = this.svgFactory.createElement("svg:rect");
+      rect.setAttributeNS(null, "x", "0");
+      rect.setAttributeNS(null, "y", "0");
+      rect.setAttributeNS(null, "width", pf(width));
+      rect.setAttributeNS(null, "height", pf(height));
+      rect.setAttributeNS(null, "fill", fillColor);
+      rect.setAttributeNS(null, "mask", `url(#${current.maskId})`);
+      this.defs.appendChild(mask);
+
+      this._ensureTransformGroup().appendChild(rect);
+
+      this.paintInlineImageXObject(imgData, mask);
+    }
+
+    paintFormXObjectBegin(matrix, bbox) {
+      if (Array.isArray(matrix) && matrix.length === 6) {
+        this.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+      }
+
+      if (bbox) {
+        const width = bbox[2] - bbox[0];
+        const height = bbox[3] - bbox[1];
+        const cliprect = this.svgFactory.createElement("svg:rect");
+        cliprect.setAttributeNS(null, "x", bbox[0]);
+        cliprect.setAttributeNS(null, "y", bbox[1]);
+        cliprect.setAttributeNS(null, "width", pf(width));
+        cliprect.setAttributeNS(null, "height", pf(height));
+        this.current.element = cliprect;
+        this.clip("nonzero");
+        this.endPath();
+      }
+    }
+
+    paintFormXObjectEnd() {}
+
+    _initialize(viewport) {
+      const svg = this.svgFactory.create(viewport.width, viewport.height);
+      const definitions = this.svgFactory.createElement("svg:defs");
+      svg.appendChild(definitions);
+      this.defs = definitions;
+      const rootGroup = this.svgFactory.createElement("svg:g");
+      rootGroup.setAttributeNS(null, "transform", pm(viewport.transform));
+      svg.appendChild(rootGroup);
+      this.svg = rootGroup;
+      return svg;
+    }
+
+    _ensureClipGroup() {
+      if (!this.current.clipGroup) {
+        const clipGroup = this.svgFactory.createElement("svg:g");
+        clipGroup.setAttributeNS(null, "clip-path", this.current.activeClipUrl);
+        this.svg.appendChild(clipGroup);
+        this.current.clipGroup = clipGroup;
+      }
+
+      return this.current.clipGroup;
+    }
+
+    _ensureTransformGroup() {
+      if (!this.tgrp) {
+        this.tgrp = this.svgFactory.createElement("svg:g");
+        this.tgrp.setAttributeNS(null, "transform", pm(this.transformMatrix));
+
+        if (this.current.activeClipUrl) {
+          this._ensureClipGroup().appendChild(this.tgrp);
+        } else {
+          this.svg.appendChild(this.tgrp);
+        }
+      }
+
+      return this.tgrp;
+    }
+
+  };
+}
+
+/***/ }),
+/* 23 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.PDFNodeStream = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+var _network_utils = __w_pdfjs_require__(24);
+
+;
+
+const fs = require("fs");
+
+const http = require("http");
+
+const https = require("https");
+
+const url = require("url");
+
+const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
+
+function parseUrl(sourceUrl) {
+  const parsedUrl = url.parse(sourceUrl);
+
+  if (parsedUrl.protocol === "file:" || parsedUrl.host) {
+    return parsedUrl;
+  }
+
+  if (/^[a-z]:[/\\]/i.test(sourceUrl)) {
+    return url.parse(`file:///${sourceUrl}`);
+  }
+
+  if (!parsedUrl.host) {
+    parsedUrl.protocol = "file:";
+  }
+
+  return parsedUrl;
+}
+
+class PDFNodeStream {
+  constructor(source) {
+    this.source = source;
+    this.url = parseUrl(source.url);
+    this.isHttp = this.url.protocol === "http:" || this.url.protocol === "https:";
+    this.isFsUrl = this.url.protocol === "file:";
+    this.httpHeaders = this.isHttp && source.httpHeaders || {};
+    this._fullRequestReader = null;
+    this._rangeRequestReaders = [];
+  }
+
+  get _progressiveDataLength() {
+    return this._fullRequestReader?._loaded ?? 0;
+  }
+
+  getFullReader() {
+    (0, _util.assert)(!this._fullRequestReader, "PDFNodeStream.getFullReader can only be called once.");
+    this._fullRequestReader = this.isFsUrl ? new PDFNodeStreamFsFullReader(this) : new PDFNodeStreamFullReader(this);
+    return this._fullRequestReader;
+  }
+
+  getRangeReader(start, end) {
+    if (end <= this._progressiveDataLength) {
+      return null;
+    }
+
+    const rangeReader = this.isFsUrl ? new PDFNodeStreamFsRangeReader(this, start, end) : new PDFNodeStreamRangeReader(this, start, end);
+
+    this._rangeRequestReaders.push(rangeReader);
+
+    return rangeReader;
+  }
+
+  cancelAllRequests(reason) {
+    if (this._fullRequestReader) {
+      this._fullRequestReader.cancel(reason);
+    }
+
+    for (const reader of this._rangeRequestReaders.slice(0)) {
+      reader.cancel(reason);
+    }
+  }
+
+}
+
+exports.PDFNodeStream = PDFNodeStream;
+
+class BaseFullReader {
+  constructor(stream) {
+    this._url = stream.url;
+    this._done = false;
+    this._storedError = null;
+    this.onProgress = null;
+    const source = stream.source;
+    this._contentLength = source.length;
+    this._loaded = 0;
+    this._filename = null;
+    this._disableRange = source.disableRange || false;
+    this._rangeChunkSize = source.rangeChunkSize;
+
+    if (!this._rangeChunkSize && !this._disableRange) {
+      this._disableRange = true;
+    }
+
+    this._isStreamingSupported = !source.disableStream;
+    this._isRangeSupported = !source.disableRange;
+    this._readableStream = null;
+    this._readCapability = (0, _util.createPromiseCapability)();
+    this._headersCapability = (0, _util.createPromiseCapability)();
+  }
+
+  get headersReady() {
+    return this._headersCapability.promise;
+  }
+
+  get filename() {
+    return this._filename;
+  }
+
+  get contentLength() {
+    return this._contentLength;
+  }
+
+  get isRangeSupported() {
+    return this._isRangeSupported;
+  }
+
+  get isStreamingSupported() {
+    return this._isStreamingSupported;
+  }
+
+  async read() {
+    await this._readCapability.promise;
+
+    if (this._done) {
+      return {
+        value: undefined,
+        done: true
+      };
+    }
+
+    if (this._storedError) {
+      throw this._storedError;
+    }
+
+    const chunk = this._readableStream.read();
+
+    if (chunk === null) {
+      this._readCapability = (0, _util.createPromiseCapability)();
+      return this.read();
+    }
+
+    this._loaded += chunk.length;
+
+    if (this.onProgress) {
+      this.onProgress({
+        loaded: this._loaded,
+        total: this._contentLength
+      });
+    }
+
+    const buffer = new Uint8Array(chunk).buffer;
+    return {
+      value: buffer,
+      done: false
+    };
+  }
+
+  cancel(reason) {
+    if (!this._readableStream) {
+      this._error(reason);
+
+      return;
+    }
+
+    this._readableStream.destroy(reason);
+  }
+
+  _error(reason) {
+    this._storedError = reason;
+
+    this._readCapability.resolve();
+  }
+
+  _setReadableStream(readableStream) {
+    this._readableStream = readableStream;
+    readableStream.on("readable", () => {
+      this._readCapability.resolve();
+    });
+    readableStream.on("end", () => {
+      readableStream.destroy();
+      this._done = true;
+
+      this._readCapability.resolve();
+    });
+    readableStream.on("error", reason => {
+      this._error(reason);
+    });
+
+    if (!this._isStreamingSupported && this._isRangeSupported) {
+      this._error(new _util.AbortException("streaming is disabled"));
+    }
+
+    if (this._storedError) {
+      this._readableStream.destroy(this._storedError);
+    }
+  }
+
+}
+
+class BaseRangeReader {
+  constructor(stream) {
+    this._url = stream.url;
+    this._done = false;
+    this._storedError = null;
+    this.onProgress = null;
+    this._loaded = 0;
+    this._readableStream = null;
+    this._readCapability = (0, _util.createPromiseCapability)();
+    const source = stream.source;
+    this._isStreamingSupported = !source.disableStream;
+  }
+
+  get isStreamingSupported() {
+    return this._isStreamingSupported;
+  }
+
+  async read() {
+    await this._readCapability.promise;
+
+    if (this._done) {
+      return {
+        value: undefined,
+        done: true
+      };
+    }
+
+    if (this._storedError) {
+      throw this._storedError;
+    }
+
+    const chunk = this._readableStream.read();
+
+    if (chunk === null) {
+      this._readCapability = (0, _util.createPromiseCapability)();
+      return this.read();
+    }
+
+    this._loaded += chunk.length;
+
+    if (this.onProgress) {
+      this.onProgress({
+        loaded: this._loaded
+      });
+    }
+
+    const buffer = new Uint8Array(chunk).buffer;
+    return {
+      value: buffer,
+      done: false
+    };
+  }
+
+  cancel(reason) {
+    if (!this._readableStream) {
+      this._error(reason);
+
+      return;
+    }
+
+    this._readableStream.destroy(reason);
+  }
+
+  _error(reason) {
+    this._storedError = reason;
+
+    this._readCapability.resolve();
+  }
+
+  _setReadableStream(readableStream) {
+    this._readableStream = readableStream;
+    readableStream.on("readable", () => {
+      this._readCapability.resolve();
+    });
+    readableStream.on("end", () => {
+      readableStream.destroy();
+      this._done = true;
+
+      this._readCapability.resolve();
+    });
+    readableStream.on("error", reason => {
+      this._error(reason);
+    });
+
+    if (this._storedError) {
+      this._readableStream.destroy(this._storedError);
+    }
+  }
+
+}
+
+function createRequestOptions(parsedUrl, headers) {
+  return {
+    protocol: parsedUrl.protocol,
+    auth: parsedUrl.auth,
+    host: parsedUrl.hostname,
+    port: parsedUrl.port,
+    path: parsedUrl.path,
+    method: "GET",
+    headers
+  };
+}
+
+class PDFNodeStreamFullReader extends BaseFullReader {
+  constructor(stream) {
+    super(stream);
+
+    const handleResponse = response => {
+      if (response.statusCode === 404) {
+        const error = new _util.MissingPDFException(`Missing PDF "${this._url}".`);
+        this._storedError = error;
+
+        this._headersCapability.reject(error);
+
+        return;
+      }
+
+      this._headersCapability.resolve();
+
+      this._setReadableStream(response);
+
+      const getResponseHeader = name => {
+        return this._readableStream.headers[name.toLowerCase()];
+      };
+
+      const {
+        allowRangeRequests,
+        suggestedLength
+      } = (0, _network_utils.validateRangeRequestCapabilities)({
+        getResponseHeader,
+        isHttp: stream.isHttp,
+        rangeChunkSize: this._rangeChunkSize,
+        disableRange: this._disableRange
+      });
+      this._isRangeSupported = allowRangeRequests;
+      this._contentLength = suggestedLength || this._contentLength;
+      this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
+    };
+
+    this._request = null;
+
+    if (this._url.protocol === "http:") {
+      this._request = http.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse);
+    } else {
+      this._request = https.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse);
+    }
+
+    this._request.on("error", reason => {
+      this._storedError = reason;
+
+      this._headersCapability.reject(reason);
+    });
+
+    this._request.end();
+  }
+
+}
+
+class PDFNodeStreamRangeReader extends BaseRangeReader {
+  constructor(stream, start, end) {
+    super(stream);
+    this._httpHeaders = {};
+
+    for (const property in stream.httpHeaders) {
+      const value = stream.httpHeaders[property];
+
+      if (typeof value === "undefined") {
+        continue;
+      }
+
+      this._httpHeaders[property] = value;
+    }
+
+    this._httpHeaders.Range = `bytes=${start}-${end - 1}`;
+
+    const handleResponse = response => {
+      if (response.statusCode === 404) {
+        const error = new _util.MissingPDFException(`Missing PDF "${this._url}".`);
+        this._storedError = error;
+        return;
+      }
+
+      this._setReadableStream(response);
+    };
+
+    this._request = null;
+
+    if (this._url.protocol === "http:") {
+      this._request = http.request(createRequestOptions(this._url, this._httpHeaders), handleResponse);
+    } else {
+      this._request = https.request(createRequestOptions(this._url, this._httpHeaders), handleResponse);
+    }
+
+    this._request.on("error", reason => {
+      this._storedError = reason;
+    });
+
+    this._request.end();
+  }
+
+}
+
+class PDFNodeStreamFsFullReader extends BaseFullReader {
+  constructor(stream) {
+    super(stream);
+    let path = decodeURIComponent(this._url.path);
+
+    if (fileUriRegex.test(this._url.href)) {
+      path = path.replace(/^\//, "");
+    }
+
+    fs.lstat(path, (error, stat) => {
+      if (error) {
+        if (error.code === "ENOENT") {
+          error = new _util.MissingPDFException(`Missing PDF "${path}".`);
+        }
+
+        this._storedError = error;
+
+        this._headersCapability.reject(error);
+
+        return;
+      }
+
+      this._contentLength = stat.size;
+
+      this._setReadableStream(fs.createReadStream(path));
+
+      this._headersCapability.resolve();
+    });
+  }
+
+}
+
+class PDFNodeStreamFsRangeReader extends BaseRangeReader {
+  constructor(stream, start, end) {
+    super(stream);
+    let path = decodeURIComponent(this._url.path);
+
+    if (fileUriRegex.test(this._url.href)) {
+      path = path.replace(/^\//, "");
+    }
+
+    this._setReadableStream(fs.createReadStream(path, {
+      start,
+      end: end - 1
+    }));
+  }
+
+}
+
+/***/ }),
+/* 24 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.createResponseStatusError = createResponseStatusError;
+exports.extractFilenameFromHeader = extractFilenameFromHeader;
+exports.validateRangeRequestCapabilities = validateRangeRequestCapabilities;
+exports.validateResponseStatus = validateResponseStatus;
+
+var _util = __w_pdfjs_require__(2);
+
+var _content_disposition = __w_pdfjs_require__(25);
+
+var _display_utils = __w_pdfjs_require__(1);
+
+function validateRangeRequestCapabilities({
+  getResponseHeader,
+  isHttp,
+  rangeChunkSize,
+  disableRange
+}) {
+  (0, _util.assert)(rangeChunkSize > 0, "Range chunk size must be larger than zero");
+  const returnValues = {
+    allowRangeRequests: false,
+    suggestedLength: undefined
+  };
+  const length = parseInt(getResponseHeader("Content-Length"), 10);
+
+  if (!Number.isInteger(length)) {
+    return returnValues;
+  }
+
+  returnValues.suggestedLength = length;
+
+  if (length <= 2 * rangeChunkSize) {
+    return returnValues;
+  }
+
+  if (disableRange || !isHttp) {
+    return returnValues;
+  }
+
+  if (getResponseHeader("Accept-Ranges") !== "bytes") {
+    return returnValues;
+  }
+
+  const contentEncoding = getResponseHeader("Content-Encoding") || "identity";
+
+  if (contentEncoding !== "identity") {
+    return returnValues;
+  }
+
+  returnValues.allowRangeRequests = true;
+  return returnValues;
+}
+
+function extractFilenameFromHeader(getResponseHeader) {
+  const contentDisposition = getResponseHeader("Content-Disposition");
+
+  if (contentDisposition) {
+    let filename = (0, _content_disposition.getFilenameFromContentDispositionHeader)(contentDisposition);
+
+    if (filename.includes("%")) {
+      try {
+        filename = decodeURIComponent(filename);
+      } catch (ex) {}
+    }
+
+    if ((0, _display_utils.isPdfFile)(filename)) {
+      return filename;
+    }
+  }
+
+  return null;
+}
+
+function createResponseStatusError(status, url) {
+  if (status === 404 || status === 0 && url.startsWith("file:")) {
+    return new _util.MissingPDFException('Missing PDF "' + url + '".');
+  }
+
+  return new _util.UnexpectedResponseException(`Unexpected server response (${status}) while retrieving PDF "${url}".`, status);
+}
+
+function validateResponseStatus(status) {
+  return status === 200 || status === 206;
+}
+
+/***/ }),
+/* 25 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.getFilenameFromContentDispositionHeader = getFilenameFromContentDispositionHeader;
+
+var _util = __w_pdfjs_require__(2);
+
+function getFilenameFromContentDispositionHeader(contentDisposition) {
+  let needsEncodingFixup = true;
+  let tmp = toParamRegExp("filename\\*", "i").exec(contentDisposition);
+
+  if (tmp) {
+    tmp = tmp[1];
+    let filename = rfc2616unquote(tmp);
+    filename = unescape(filename);
+    filename = rfc5987decode(filename);
+    filename = rfc2047decode(filename);
+    return fixupEncoding(filename);
+  }
+
+  tmp = rfc2231getparam(contentDisposition);
+
+  if (tmp) {
+    const filename = rfc2047decode(tmp);
+    return fixupEncoding(filename);
+  }
+
+  tmp = toParamRegExp("filename", "i").exec(contentDisposition);
+
+  if (tmp) {
+    tmp = tmp[1];
+    let filename = rfc2616unquote(tmp);
+    filename = rfc2047decode(filename);
+    return fixupEncoding(filename);
+  }
+
+  function toParamRegExp(attributePattern, flags) {
+    return new RegExp("(?:^|;)\\s*" + attributePattern + "\\s*=\\s*" + "(" + '[^";\\s][^;\\s]*' + "|" + '"(?:[^"\\\\]|\\\\"?)+"?' + ")", flags);
+  }
+
+  function textdecode(encoding, value) {
+    if (encoding) {
+      if (!/^[\x00-\xFF]+$/.test(value)) {
+        return value;
+      }
+
+      try {
+        const decoder = new TextDecoder(encoding, {
+          fatal: true
+        });
+        const buffer = (0, _util.stringToBytes)(value);
+        value = decoder.decode(buffer);
+        needsEncodingFixup = false;
+      } catch (e) {
+        if (/^utf-?8$/i.test(encoding)) {
+          try {
+            value = decodeURIComponent(escape(value));
+            needsEncodingFixup = false;
+          } catch (err) {}
+        }
+      }
+    }
+
+    return value;
+  }
+
+  function fixupEncoding(value) {
+    if (needsEncodingFixup && /[\x80-\xff]/.test(value)) {
+      value = textdecode("utf-8", value);
+
+      if (needsEncodingFixup) {
+        value = textdecode("iso-8859-1", value);
+      }
+    }
+
+    return value;
+  }
+
+  function rfc2231getparam(contentDispositionStr) {
+    const matches = [];
+    let match;
+    const iter = toParamRegExp("filename\\*((?!0\\d)\\d+)(\\*?)", "ig");
+
+    while ((match = iter.exec(contentDispositionStr)) !== null) {
+      let [, n, quot, part] = match;
+      n = parseInt(n, 10);
+
+      if (n in matches) {
+        if (n === 0) {
+          break;
+        }
+
+        continue;
+      }
+
+      matches[n] = [quot, part];
+    }
+
+    const parts = [];
+
+    for (let n = 0; n < matches.length; ++n) {
+      if (!(n in matches)) {
+        break;
+      }
+
+      let [quot, part] = matches[n];
+      part = rfc2616unquote(part);
+
+      if (quot) {
+        part = unescape(part);
+
+        if (n === 0) {
+          part = rfc5987decode(part);
+        }
+      }
+
+      parts.push(part);
+    }
+
+    return parts.join("");
+  }
+
+  function rfc2616unquote(value) {
+    if (value.startsWith('"')) {
+      const parts = value.slice(1).split('\\"');
+
+      for (let i = 0; i < parts.length; ++i) {
+        const quotindex = parts[i].indexOf('"');
+
+        if (quotindex !== -1) {
+          parts[i] = parts[i].slice(0, quotindex);
+          parts.length = i + 1;
+        }
+
+        parts[i] = parts[i].replace(/\\(.)/g, "$1");
+      }
+
+      value = parts.join('"');
+    }
+
+    return value;
+  }
+
+  function rfc5987decode(extvalue) {
+    const encodingend = extvalue.indexOf("'");
+
+    if (encodingend === -1) {
+      return extvalue;
+    }
+
+    const encoding = extvalue.slice(0, encodingend);
+    const langvalue = extvalue.slice(encodingend + 1);
+    const value = langvalue.replace(/^[^']*'/, "");
+    return textdecode(encoding, value);
+  }
+
+  function rfc2047decode(value) {
+    if (!value.startsWith("=?") || /[\x00-\x19\x80-\xff]/.test(value)) {
+      return value;
+    }
+
+    return value.replace(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g, function (matches, charset, encoding, text) {
+      if (encoding === "q" || encoding === "Q") {
+        text = text.replace(/_/g, " ");
+        text = text.replace(/=([0-9a-fA-F]{2})/g, function (match, hex) {
+          return String.fromCharCode(parseInt(hex, 16));
+        });
+        return textdecode(charset, text);
+      }
+
+      try {
+        text = atob(text);
+      } catch (e) {}
+
+      return textdecode(charset, text);
+    });
+  }
+
+  return "";
+}
+
+/***/ }),
+/* 26 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.PDFNetworkStream = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+var _network_utils = __w_pdfjs_require__(24);
+
+;
+const OK_RESPONSE = 200;
+const PARTIAL_CONTENT_RESPONSE = 206;
+
+function getArrayBuffer(xhr) {
+  const data = xhr.response;
+
+  if (typeof data !== "string") {
+    return data;
+  }
+
+  const array = (0, _util.stringToBytes)(data);
+  return array.buffer;
+}
+
+class NetworkManager {
+  constructor(url, args = {}) {
+    this.url = url;
+    this.isHttp = /^https?:/i.test(url);
+    this.httpHeaders = this.isHttp && args.httpHeaders || Object.create(null);
+    this.withCredentials = args.withCredentials || false;
+
+    this.getXhr = args.getXhr || function NetworkManager_getXhr() {
+      return new XMLHttpRequest();
+    };
+
+    this.currXhrId = 0;
+    this.pendingRequests = Object.create(null);
+  }
+
+  requestRange(begin, end, listeners) {
+    const args = {
+      begin,
+      end
+    };
+
+    for (const prop in listeners) {
+      args[prop] = listeners[prop];
+    }
+
+    return this.request(args);
+  }
+
+  requestFull(listeners) {
+    return this.request(listeners);
+  }
+
+  request(args) {
+    const xhr = this.getXhr();
+    const xhrId = this.currXhrId++;
+    const pendingRequest = this.pendingRequests[xhrId] = {
+      xhr
+    };
+    xhr.open("GET", this.url);
+    xhr.withCredentials = this.withCredentials;
+
+    for (const property in this.httpHeaders) {
+      const value = this.httpHeaders[property];
+
+      if (typeof value === "undefined") {
+        continue;
+      }
+
+      xhr.setRequestHeader(property, value);
+    }
+
+    if (this.isHttp && "begin" in args && "end" in args) {
+      xhr.setRequestHeader("Range", `bytes=${args.begin}-${args.end - 1}`);
+      pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE;
+    } else {
+      pendingRequest.expectedStatus = OK_RESPONSE;
+    }
+
+    xhr.responseType = "arraybuffer";
+
+    if (args.onError) {
+      xhr.onerror = function (evt) {
+        args.onError(xhr.status);
+      };
+    }
+
+    xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
+    xhr.onprogress = this.onProgress.bind(this, xhrId);
+    pendingRequest.onHeadersReceived = args.onHeadersReceived;
+    pendingRequest.onDone = args.onDone;
+    pendingRequest.onError = args.onError;
+    pendingRequest.onProgress = args.onProgress;
+    xhr.send(null);
+    return xhrId;
+  }
+
+  onProgress(xhrId, evt) {
+    const pendingRequest = this.pendingRequests[xhrId];
+
+    if (!pendingRequest) {
+      return;
+    }
+
+    pendingRequest.onProgress?.(evt);
+  }
+
+  onStateChange(xhrId, evt) {
+    const pendingRequest = this.pendingRequests[xhrId];
+
+    if (!pendingRequest) {
+      return;
+    }
+
+    const xhr = pendingRequest.xhr;
+
+    if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
+      pendingRequest.onHeadersReceived();
+      delete pendingRequest.onHeadersReceived;
+    }
+
+    if (xhr.readyState !== 4) {
+      return;
+    }
+
+    if (!(xhrId in this.pendingRequests)) {
+      return;
+    }
+
+    delete this.pendingRequests[xhrId];
+
+    if (xhr.status === 0 && this.isHttp) {
+      pendingRequest.onError?.(xhr.status);
+      return;
+    }
+
+    const xhrStatus = xhr.status || OK_RESPONSE;
+    const ok_response_on_range_request = xhrStatus === OK_RESPONSE && pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
+
+    if (!ok_response_on_range_request && xhrStatus !== pendingRequest.expectedStatus) {
+      pendingRequest.onError?.(xhr.status);
+      return;
+    }
+
+    const chunk = getArrayBuffer(xhr);
+
+    if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
+      const rangeHeader = xhr.getResponseHeader("Content-Range");
+      const matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
+      pendingRequest.onDone({
+        begin: parseInt(matches[1], 10),
+        chunk
+      });
+    } else if (chunk) {
+      pendingRequest.onDone({
+        begin: 0,
+        chunk
+      });
+    } else {
+      pendingRequest.onError?.(xhr.status);
+    }
+  }
+
+  getRequestXhr(xhrId) {
+    return this.pendingRequests[xhrId].xhr;
+  }
+
+  isPendingRequest(xhrId) {
+    return xhrId in this.pendingRequests;
+  }
+
+  abortRequest(xhrId) {
+    const xhr = this.pendingRequests[xhrId].xhr;
+    delete this.pendingRequests[xhrId];
+    xhr.abort();
+  }
+
+}
+
+class PDFNetworkStream {
+  constructor(source) {
+    this._source = source;
+    this._manager = new NetworkManager(source.url, {
+      httpHeaders: source.httpHeaders,
+      withCredentials: source.withCredentials
+    });
+    this._rangeChunkSize = source.rangeChunkSize;
+    this._fullRequestReader = null;
+    this._rangeRequestReaders = [];
+  }
+
+  _onRangeRequestReaderClosed(reader) {
+    const i = this._rangeRequestReaders.indexOf(reader);
+
+    if (i >= 0) {
+      this._rangeRequestReaders.splice(i, 1);
+    }
+  }
+
+  getFullReader() {
+    (0, _util.assert)(!this._fullRequestReader, "PDFNetworkStream.getFullReader can only be called once.");
+    this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this._manager, this._source);
+    return this._fullRequestReader;
+  }
+
+  getRangeReader(begin, end) {
+    const reader = new PDFNetworkStreamRangeRequestReader(this._manager, begin, end);
+    reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
+
+    this._rangeRequestReaders.push(reader);
+
+    return reader;
+  }
+
+  cancelAllRequests(reason) {
+    this._fullRequestReader?.cancel(reason);
+
+    for (const reader of this._rangeRequestReaders.slice(0)) {
+      reader.cancel(reason);
+    }
+  }
+
+}
+
+exports.PDFNetworkStream = PDFNetworkStream;
+
+class PDFNetworkStreamFullRequestReader {
+  constructor(manager, source) {
+    this._manager = manager;
+    const args = {
+      onHeadersReceived: this._onHeadersReceived.bind(this),
+      onDone: this._onDone.bind(this),
+      onError: this._onError.bind(this),
+      onProgress: this._onProgress.bind(this)
+    };
+    this._url = source.url;
+    this._fullRequestId = manager.requestFull(args);
+    this._headersReceivedCapability = (0, _util.createPromiseCapability)();
+    this._disableRange = source.disableRange || false;
+    this._contentLength = source.length;
+    this._rangeChunkSize = source.rangeChunkSize;
+
+    if (!this._rangeChunkSize && !this._disableRange) {
+      this._disableRange = true;
+    }
+
+    this._isStreamingSupported = false;
+    this._isRangeSupported = false;
+    this._cachedChunks = [];
+    this._requests = [];
+    this._done = false;
+    this._storedError = undefined;
+    this._filename = null;
+    this.onProgress = null;
+  }
+
+  _onHeadersReceived() {
+    const fullRequestXhrId = this._fullRequestId;
+
+    const fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId);
+
+    const getResponseHeader = name => {
+      return fullRequestXhr.getResponseHeader(name);
+    };
+
+    const {
+      allowRangeRequests,
+      suggestedLength
+    } = (0, _network_utils.validateRangeRequestCapabilities)({
+      getResponseHeader,
+      isHttp: this._manager.isHttp,
+      rangeChunkSize: this._rangeChunkSize,
+      disableRange: this._disableRange
+    });
+
+    if (allowRangeRequests) {
+      this._isRangeSupported = true;
+    }
+
+    this._contentLength = suggestedLength || this._contentLength;
+    this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
+
+    if (this._isRangeSupported) {
+      this._manager.abortRequest(fullRequestXhrId);
+    }
+
+    this._headersReceivedCapability.resolve();
+  }
+
+  _onDone(data) {
+    if (data) {
+      if (this._requests.length > 0) {
+        const requestCapability = this._requests.shift();
+
+        requestCapability.resolve({
+          value: data.chunk,
+          done: false
+        });
+      } else {
+        this._cachedChunks.push(data.chunk);
+      }
+    }
+
+    this._done = true;
+
+    if (this._cachedChunks.length > 0) {
+      return;
+    }
+
+    for (const requestCapability of this._requests) {
+      requestCapability.resolve({
+        value: undefined,
+        done: true
+      });
+    }
+
+    this._requests.length = 0;
+  }
+
+  _onError(status) {
+    this._storedError = (0, _network_utils.createResponseStatusError)(status, this._url);
+
+    this._headersReceivedCapability.reject(this._storedError);
+
+    for (const requestCapability of this._requests) {
+      requestCapability.reject(this._storedError);
+    }
+
+    this._requests.length = 0;
+    this._cachedChunks.length = 0;
+  }
+
+  _onProgress(evt) {
+    this.onProgress?.({
+      loaded: evt.loaded,
+      total: evt.lengthComputable ? evt.total : this._contentLength
+    });
+  }
+
+  get filename() {
+    return this._filename;
+  }
+
+  get isRangeSupported() {
+    return this._isRangeSupported;
+  }
+
+  get isStreamingSupported() {
+    return this._isStreamingSupported;
+  }
+
+  get contentLength() {
+    return this._contentLength;
+  }
+
+  get headersReady() {
+    return this._headersReceivedCapability.promise;
+  }
+
+  async read() {
+    if (this._storedError) {
+      throw this._storedError;
+    }
+
+    if (this._cachedChunks.length > 0) {
+      const chunk = this._cachedChunks.shift();
+
+      return {
+        value: chunk,
+        done: false
+      };
+    }
+
+    if (this._done) {
+      return {
+        value: undefined,
+        done: true
+      };
+    }
+
+    const requestCapability = (0, _util.createPromiseCapability)();
+
+    this._requests.push(requestCapability);
+
+    return requestCapability.promise;
+  }
+
+  cancel(reason) {
+    this._done = true;
+
+    this._headersReceivedCapability.reject(reason);
+
+    for (const requestCapability of this._requests) {
+      requestCapability.resolve({
+        value: undefined,
+        done: true
+      });
+    }
+
+    this._requests.length = 0;
+
+    if (this._manager.isPendingRequest(this._fullRequestId)) {
+      this._manager.abortRequest(this._fullRequestId);
+    }
+
+    this._fullRequestReader = null;
+  }
+
+}
+
+class PDFNetworkStreamRangeRequestReader {
+  constructor(manager, begin, end) {
+    this._manager = manager;
+    const args = {
+      onDone: this._onDone.bind(this),
+      onError: this._onError.bind(this),
+      onProgress: this._onProgress.bind(this)
+    };
+    this._url = manager.url;
+    this._requestId = manager.requestRange(begin, end, args);
+    this._requests = [];
+    this._queuedChunk = null;
+    this._done = false;
+    this._storedError = undefined;
+    this.onProgress = null;
+    this.onClosed = null;
+  }
+
+  _close() {
+    this.onClosed?.(this);
+  }
+
+  _onDone(data) {
+    const chunk = data.chunk;
+
+    if (this._requests.length > 0) {
+      const requestCapability = this._requests.shift();
+
+      requestCapability.resolve({
+        value: chunk,
+        done: false
+      });
+    } else {
+      this._queuedChunk = chunk;
+    }
+
+    this._done = true;
+
+    for (const requestCapability of this._requests) {
+      requestCapability.resolve({
+        value: undefined,
+        done: true
+      });
+    }
+
+    this._requests.length = 0;
+
+    this._close();
+  }
+
+  _onError(status) {
+    this._storedError = (0, _network_utils.createResponseStatusError)(status, this._url);
+
+    for (const requestCapability of this._requests) {
+      requestCapability.reject(this._storedError);
+    }
+
+    this._requests.length = 0;
+    this._queuedChunk = null;
+  }
+
+  _onProgress(evt) {
+    if (!this.isStreamingSupported) {
+      this.onProgress?.({
+        loaded: evt.loaded
+      });
+    }
+  }
+
+  get isStreamingSupported() {
+    return false;
+  }
+
+  async read() {
+    if (this._storedError) {
+      throw this._storedError;
+    }
+
+    if (this._queuedChunk !== null) {
+      const chunk = this._queuedChunk;
+      this._queuedChunk = null;
+      return {
+        value: chunk,
+        done: false
+      };
+    }
+
+    if (this._done) {
+      return {
+        value: undefined,
+        done: true
+      };
+    }
+
+    const requestCapability = (0, _util.createPromiseCapability)();
+
+    this._requests.push(requestCapability);
+
+    return requestCapability.promise;
+  }
+
+  cancel(reason) {
+    this._done = true;
+
+    for (const requestCapability of this._requests) {
+      requestCapability.resolve({
+        value: undefined,
+        done: true
+      });
+    }
+
+    this._requests.length = 0;
+
+    if (this._manager.isPendingRequest(this._requestId)) {
+      this._manager.abortRequest(this._requestId);
+    }
+
+    this._close();
+  }
+
+}
+
+/***/ }),
+/* 27 */
+/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+exports.PDFFetchStream = void 0;
+
+var _util = __w_pdfjs_require__(2);
+
+var _network_utils = __w_pdfjs_require__(24);
+
+;
+
+function createFetchOptions(headers, withCredentials, abortController) {
+  return {
+    method: "GET",
+    headers,
+    signal: abortController?.signal,
+    mode: "cors",
+    credentials: withCredentials ? "include" : "same-origin",
+    redirect: "follow"
+  };
+}
+
+function createHeaders(httpHeaders) {
+  const headers = new Headers();
+
+  for (const property in httpHeaders) {
+    const value = httpHeaders[property];
+
+    if (typeof value === "undefined") {
+      continue;
+    }
+
+    headers.append(property, value);
+  }
+
+  return headers;
+}
+
+class PDFFetchStream {
+  constructor(source) {
+    this.source = source;
+    this.isHttp = /^https?:/i.test(source.url);
+    this.httpHeaders = this.isHttp && source.httpHeaders || {};
+    this._fullRequestReader = null;
+    this._rangeRequestReaders = [];
+  }
+
+  get _progressiveDataLength() {
+    return this._fullRequestReader?._loaded ?? 0;
+  }
+
+  getFullReader() {
+    (0, _util.assert)(!this._fullRequestReader, "PDFFetchStream.getFullReader can only be called once.");
+    this._fullRequestReader = new PDFFetchStreamReader(this);
+    return this._fullRequestReader;
+  }
+
+  getRangeReader(begin, end) {
+    if (end <= this._progressiveDataLength) {
+      return null;
+    }
+
+    const reader = new PDFFetchStreamRangeReader(this, begin, end);
+
+    this._rangeRequestReaders.push(reader);
+
+    return reader;
+  }
+
+  cancelAllRequests(reason) {
+    if (this._fullRequestReader) {
+      this._fullRequestReader.cancel(reason);
+    }
+
+    for (const reader of this._rangeRequestReaders.slice(0)) {
+      reader.cancel(reason);
+    }
+  }
+
+}
+
+exports.PDFFetchStream = PDFFetchStream;
+
+class PDFFetchStreamReader {
+  constructor(stream) {
+    this._stream = stream;
+    this._reader = null;
+    this._loaded = 0;
+    this._filename = null;
+    const source = stream.source;
+    this._withCredentials = source.withCredentials || false;
+    this._contentLength = source.length;
+    this._headersCapability = (0, _util.createPromiseCapability)();
+    this._disableRange = source.disableRange || false;
+    this._rangeChunkSize = source.rangeChunkSize;
+
+    if (!this._rangeChunkSize && !this._disableRange) {
+      this._disableRange = true;
+    }
+
+    if (typeof AbortController !== "undefined") {
+      this._abortController = new AbortController();
+    }
+
+    this._isStreamingSupported = !source.disableStream;
+    this._isRangeSupported = !source.disableRange;
+    this._headers = createHeaders(this._stream.httpHeaders);
+    const url = source.url;
+    fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(response => {
+      if (!(0, _network_utils.validateResponseStatus)(response.status)) {
+        throw (0, _network_utils.createResponseStatusError)(response.status, url);
+      }
+
+      this._reader = response.body.getReader();
+
+      this._headersCapability.resolve();
+
+      const getResponseHeader = name => {
+        return response.headers.get(name);
+      };
+
+      const {
+        allowRangeRequests,
+        suggestedLength
+      } = (0, _network_utils.validateRangeRequestCapabilities)({
+        getResponseHeader,
+        isHttp: this._stream.isHttp,
+        rangeChunkSize: this._rangeChunkSize,
+        disableRange: this._disableRange
+      });
+      this._isRangeSupported = allowRangeRequests;
+      this._contentLength = suggestedLength || this._contentLength;
+      this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
+
+      if (!this._isStreamingSupported && this._isRangeSupported) {
+        this.cancel(new _util.AbortException("Streaming is disabled."));
+      }
+    }).catch(this._headersCapability.reject);
+    this.onProgress = null;
+  }
+
+  get headersReady() {
+    return this._headersCapability.promise;
+  }
+
+  get filename() {
+    return this._filename;
+  }
+
+  get contentLength() {
+    return this._contentLength;
+  }
+
+  get isRangeSupported() {
+    return this._isRangeSupported;
+  }
+
+  get isStreamingSupported() {
+    return this._isStreamingSupported;
+  }
+
+  async read() {
+    await this._headersCapability.promise;
+    const {
+      value,
+      done
+    } = await this._reader.read();
+
+    if (done) {
+      return {
+        value,
+        done
+      };
+    }
+
+    this._loaded += value.byteLength;
+
+    if (this.onProgress) {
+      this.onProgress({
+        loaded: this._loaded,
+        total: this._contentLength
+      });
+    }
+
+    const buffer = new Uint8Array(value).buffer;
+    return {
+      value: buffer,
+      done: false
+    };
+  }
+
+  cancel(reason) {
+    if (this._reader) {
+      this._reader.cancel(reason);
+    }
+
+    if (this._abortController) {
+      this._abortController.abort();
+    }
+  }
+
+}
+
+class PDFFetchStreamRangeReader {
+  constructor(stream, begin, end) {
+    this._stream = stream;
+    this._reader = null;
+    this._loaded = 0;
+    const source = stream.source;
+    this._withCredentials = source.withCredentials || false;
+    this._readCapability = (0, _util.createPromiseCapability)();
+    this._isStreamingSupported = !source.disableStream;
+
+    if (typeof AbortController !== "undefined") {
+      this._abortController = new AbortController();
+    }
+
+    this._headers = createHeaders(this._stream.httpHeaders);
+
+    this._headers.append("Range", `bytes=${begin}-${end - 1}`);
+
+    const url = source.url;
+    fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(response => {
+      if (!(0, _network_utils.validateResponseStatus)(response.status)) {
+        throw (0, _network_utils.createResponseStatusError)(response.status, url);
+      }
+
+      this._readCapability.resolve();
+
+      this._reader = response.body.getReader();
+    }).catch(this._readCapability.reject);
+    this.onProgress = null;
+  }
+
+  get isStreamingSupported() {
+    return this._isStreamingSupported;
+  }
+
+  async read() {
+    await this._readCapability.promise;
+    const {
+      value,
+      done
+    } = await this._reader.read();
+
+    if (done) {
+      return {
+        value,
+        done
+      };
+    }
+
+    this._loaded += value.byteLength;
+
+    if (this.onProgress) {
+      this.onProgress({
+        loaded: this._loaded
+      });
+    }
+
+    const buffer = new Uint8Array(value).buffer;
+    return {
+      value: buffer,
+      done: false
+    };
+  }
+
+  cancel(reason) {
+    if (this._reader) {
+      this._reader.cancel(reason);
+    }
+
+    if (this._abortController) {
+      this._abortController.abort();
+    }
+  }
+
+}
+
+/***/ })
+/******/ 	]);
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __w_pdfjs_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __w_pdfjs_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/************************************************************************/
+var __webpack_exports__ = {};
+// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
+(() => {
+var exports = __webpack_exports__;
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+Object.defineProperty(exports, "AnnotationLayer", ({
+  enumerable: true,
+  get: function () {
+    return _annotation_layer.AnnotationLayer;
+  }
+}));
+Object.defineProperty(exports, "AnnotationMode", ({
+  enumerable: true,
+  get: function () {
+    return _util.AnnotationMode;
+  }
+}));
+Object.defineProperty(exports, "CMapCompressionType", ({
+  enumerable: true,
+  get: function () {
+    return _util.CMapCompressionType;
+  }
+}));
+Object.defineProperty(exports, "GlobalWorkerOptions", ({
+  enumerable: true,
+  get: function () {
+    return _worker_options.GlobalWorkerOptions;
+  }
+}));
+Object.defineProperty(exports, "InvalidPDFException", ({
+  enumerable: true,
+  get: function () {
+    return _util.InvalidPDFException;
+  }
+}));
+Object.defineProperty(exports, "LinkTarget", ({
+  enumerable: true,
+  get: function () {
+    return _display_utils.LinkTarget;
+  }
+}));
+Object.defineProperty(exports, "LoopbackPort", ({
+  enumerable: true,
+  get: function () {
+    return _api.LoopbackPort;
+  }
+}));
+Object.defineProperty(exports, "MissingPDFException", ({
+  enumerable: true,
+  get: function () {
+    return _util.MissingPDFException;
+  }
+}));
+Object.defineProperty(exports, "OPS", ({
+  enumerable: true,
+  get: function () {
+    return _util.OPS;
+  }
+}));
+Object.defineProperty(exports, "PDFDataRangeTransport", ({
+  enumerable: true,
+  get: function () {
+    return _api.PDFDataRangeTransport;
+  }
+}));
+Object.defineProperty(exports, "PDFDateString", ({
+  enumerable: true,
+  get: function () {
+    return _display_utils.PDFDateString;
+  }
+}));
+Object.defineProperty(exports, "PDFWorker", ({
+  enumerable: true,
+  get: function () {
+    return _api.PDFWorker;
+  }
+}));
+Object.defineProperty(exports, "PasswordResponses", ({
+  enumerable: true,
+  get: function () {
+    return _util.PasswordResponses;
+  }
+}));
+Object.defineProperty(exports, "PermissionFlag", ({
+  enumerable: true,
+  get: function () {
+    return _util.PermissionFlag;
+  }
+}));
+Object.defineProperty(exports, "PixelsPerInch", ({
+  enumerable: true,
+  get: function () {
+    return _display_utils.PixelsPerInch;
+  }
+}));
+Object.defineProperty(exports, "RenderingCancelledException", ({
+  enumerable: true,
+  get: function () {
+    return _display_utils.RenderingCancelledException;
+  }
+}));
+Object.defineProperty(exports, "SVGGraphics", ({
+  enumerable: true,
+  get: function () {
+    return _svg.SVGGraphics;
+  }
+}));
+Object.defineProperty(exports, "UNSUPPORTED_FEATURES", ({
+  enumerable: true,
+  get: function () {
+    return _util.UNSUPPORTED_FEATURES;
+  }
+}));
+Object.defineProperty(exports, "UnexpectedResponseException", ({
+  enumerable: true,
+  get: function () {
+    return _util.UnexpectedResponseException;
+  }
+}));
+Object.defineProperty(exports, "Util", ({
+  enumerable: true,
+  get: function () {
+    return _util.Util;
+  }
+}));
+Object.defineProperty(exports, "VerbosityLevel", ({
+  enumerable: true,
+  get: function () {
+    return _util.VerbosityLevel;
+  }
+}));
+Object.defineProperty(exports, "XfaLayer", ({
+  enumerable: true,
+  get: function () {
+    return _xfa_layer.XfaLayer;
+  }
+}));
+Object.defineProperty(exports, "addLinkAttributes", ({
+  enumerable: true,
+  get: function () {
+    return _display_utils.addLinkAttributes;
+  }
+}));
+Object.defineProperty(exports, "build", ({
+  enumerable: true,
+  get: function () {
+    return _api.build;
+  }
+}));
+Object.defineProperty(exports, "createObjectURL", ({
+  enumerable: true,
+  get: function () {
+    return _util.createObjectURL;
+  }
+}));
+Object.defineProperty(exports, "createPromiseCapability", ({
+  enumerable: true,
+  get: function () {
+    return _util.createPromiseCapability;
+  }
+}));
+Object.defineProperty(exports, "createValidAbsoluteUrl", ({
+  enumerable: true,
+  get: function () {
+    return _util.createValidAbsoluteUrl;
+  }
+}));
+Object.defineProperty(exports, "getDocument", ({
+  enumerable: true,
+  get: function () {
+    return _api.getDocument;
+  }
+}));
+Object.defineProperty(exports, "getFilenameFromUrl", ({
+  enumerable: true,
+  get: function () {
+    return _display_utils.getFilenameFromUrl;
+  }
+}));
+Object.defineProperty(exports, "getPdfFilenameFromUrl", ({
+  enumerable: true,
+  get: function () {
+    return _display_utils.getPdfFilenameFromUrl;
+  }
+}));
+Object.defineProperty(exports, "getXfaPageViewport", ({
+  enumerable: true,
+  get: function () {
+    return _display_utils.getXfaPageViewport;
+  }
+}));
+Object.defineProperty(exports, "isPdfFile", ({
+  enumerable: true,
+  get: function () {
+    return _display_utils.isPdfFile;
+  }
+}));
+Object.defineProperty(exports, "loadScript", ({
+  enumerable: true,
+  get: function () {
+    return _display_utils.loadScript;
+  }
+}));
+Object.defineProperty(exports, "removeNullCharacters", ({
+  enumerable: true,
+  get: function () {
+    return _util.removeNullCharacters;
+  }
+}));
+Object.defineProperty(exports, "renderTextLayer", ({
+  enumerable: true,
+  get: function () {
+    return _text_layer.renderTextLayer;
+  }
+}));
+Object.defineProperty(exports, "shadow", ({
+  enumerable: true,
+  get: function () {
+    return _util.shadow;
+  }
+}));
+Object.defineProperty(exports, "version", ({
+  enumerable: true,
+  get: function () {
+    return _api.version;
+  }
+}));
+
+var _display_utils = __w_pdfjs_require__(1);
+
+var _util = __w_pdfjs_require__(2);
+
+var _api = __w_pdfjs_require__(6);
+
+var _annotation_layer = __w_pdfjs_require__(18);
+
+var _worker_options = __w_pdfjs_require__(12);
+
+var _is_node = __w_pdfjs_require__(4);
+
+var _text_layer = __w_pdfjs_require__(21);
+
+var _svg = __w_pdfjs_require__(22);
+
+var _xfa_layer = __w_pdfjs_require__(20);
+
+const pdfjsVersion = '2.12.313';
+const pdfjsBuild = 'a2ae56f39';
+{
+  if (_is_node.isNodeJS) {
+    const {
+      PDFNodeStream
+    } = __w_pdfjs_require__(23);
+
+    (0, _api.setPDFNetworkStreamFactory)(params => {
+      return new PDFNodeStream(params);
+    });
+  } else {
+    const {
+      PDFNetworkStream
+    } = __w_pdfjs_require__(26);
+
+    const {
+      PDFFetchStream
+    } = __w_pdfjs_require__(27);
+
+    (0, _api.setPDFNetworkStreamFactory)(params => {
+      if ((0, _display_utils.isValidFetchUrl)(params.url)) {
+        return new PDFFetchStream(params);
+      }
+
+      return new PDFNetworkStream(params);
+    });
+  }
+}
+})();
+
+/******/ 	return __webpack_exports__;
+/******/ })()
+;
+});
+//# sourceMappingURL=pdf.js.map

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
public/js/pdfjs-2.12.313/build/pdf.js.map


Diff do ficheiro suprimidas por serem muito extensas
+ 39 - 0
public/js/pdfjs-2.12.313/build/pdf.sandbox.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
public/js/pdfjs-2.12.313/build/pdf.sandbox.js.map


Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff