: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if (this.layersButton.disabled) {
console.error(`PDFSidebar.switchView: "${view}" is not a valid view.`);
toggleCheckedBtn(this.thumbnailButton, view === SidebarView.THUMBS, this.thumbnailView);
toggleCheckedBtn(this.outlineButton, view === SidebarView.OUTLINE, this.outlineView);
toggleCheckedBtn(this.attachmentsButton, view === SidebarView.ATTACHMENTS, this.attachmentsView);
toggleCheckedBtn(this.layersButton, view === SidebarView.LAYERS, this.layersView);
if (forceOpen && !this.isOpen) {
this.onUpdateThumbnails();
toggleExpandedBtn(this.toggleButton, true);
this.outerContainer.classList.add("sidebarMoving", "sidebarOpen");
if (this.active === SidebarView.THUMBS) {
this.onUpdateThumbnails();
this.#hideUINotification();
toggleExpandedBtn(this.toggleButton, false);
this.outerContainer.classList.add("sidebarMoving");
this.outerContainer.classList.remove("sidebarOpen");
this.toggleButton.blur();
if (this.isInitialViewSet) {
this.isInitialEventDispatched ||= true;
this.eventBus.dispatch("sidebarviewchanged", {
this.toggleButton.setAttribute("data-l10n-id", "pdfjs-toggle-sidebar-notification-button");
this.toggleButton.classList.add(UI_NOTIFICATION_CLASS);
#hideUINotification(reset = false) {
if (this.isOpen || reset) {
this.toggleButton.classList.remove(UI_NOTIFICATION_CLASS);
this.toggleButton.setAttribute("data-l10n-id", "pdfjs-toggle-sidebar-button");
this.sidebarContainer.addEventListener("transitionend", evt => {
if (evt.target === this.sidebarContainer) {
this.outerContainer.classList.remove("sidebarMoving");
this.eventBus.dispatch("resize", {
this.toggleButton.addEventListener("click", evt => {
this.thumbnailButton.addEventListener("click", () => {
this.switchView(SidebarView.THUMBS);
this.outlineButton.addEventListener("click", () => {
this.switchView(SidebarView.OUTLINE);
this.outlineButton.addEventListener("dblclick", () => {
this.eventBus.dispatch("toggleoutlinetree", {
this.attachmentsButton.addEventListener("click", () => {
this.switchView(SidebarView.ATTACHMENTS);
this.layersButton.addEventListener("click", () => {
this.switchView(SidebarView.LAYERS);
this.layersButton.addEventListener("dblclick", () => {
this.eventBus.dispatch("resetlayers", {
this._currentOutlineItemButton.addEventListener("click", () => {
this.eventBus.dispatch("currentoutlineitem", {
const onTreeLoaded = (count, button, view) => {
button.disabled = !count;
this.#showUINotification();
} else if (this.active === view) {
this.switchView(SidebarView.THUMBS);
this.eventBus._on("outlineloaded", evt => {
onTreeLoaded(evt.outlineCount, this.outlineButton, SidebarView.OUTLINE);
evt.currentOutlineItemPromise.then(enabled => {
if (!this.isInitialViewSet) {
this._currentOutlineItemButton.disabled = !enabled;
this.eventBus._on("attachmentsloaded", evt => {
onTreeLoaded(evt.attachmentsCount, this.attachmentsButton, SidebarView.ATTACHMENTS);
this.eventBus._on("layersloaded", evt => {
onTreeLoaded(evt.layersCount, this.layersButton, SidebarView.LAYERS);
this.eventBus._on("presentationmodechanged", evt => {
if (evt.state === PresentationModeState.NORMAL && this.visibleView === SidebarView.THUMBS) {
this.onUpdateThumbnails();
this.resizer.addEventListener("mousedown", evt => {
this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);
window.addEventListener("mousemove", this.#mouseMoveBound);
window.addEventListener("mouseup", this.#mouseUpBound);
this.eventBus._on("resize", evt => {
if (evt.source !== window) {
this.#outerContainerWidth = null;
this.#updateWidth(this.#width);
this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);
const updated = this.#updateWidth(this.#width);
Promise.resolve().then(() => {
this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS);
this.eventBus.dispatch("resize", {
get outerContainerWidth() {
return this.#outerContainerWidth ||= this.outerContainer.clientWidth;
#updateWidth(width = 0) {
const maxWidth = Math.floor(this.outerContainerWidth / 2);
if (width < SIDEBAR_MIN_WIDTH) {
width = SIDEBAR_MIN_WIDTH;
if (width === this.#width) {
docStyle.setProperty(SIDEBAR_WIDTH_VAR, `${width}px`);
width = this.outerContainerWidth - width;
this.#updateWidth(width);
this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS);
this.eventBus.dispatch("resize", {
window.removeEventListener("mousemove", this.#mouseMoveBound);
window.removeEventListener("mouseup", this.#mouseUpBound);
;// CONCATENATED MODULE: ./web/pdf_thumbnail_view.js
const DRAW_UPSCALE_FACTOR = 2;
const MAX_NUM_SCALING_STEPS = 3;
const THUMBNAIL_WIDTH = 98;
static #tempCanvas = null;
static getCanvas(width, height) {
const tempCanvas = this.#tempCanvas ||= document.createElement("canvas");
tempCanvas.width = width;
tempCanvas.height = height;
const ctx = tempCanvas.getContext("2d", {
ctx.fillStyle = "rgb(255, 255, 255)";
ctx.fillRect(0, 0, width, height);
return [tempCanvas, tempCanvas.getContext("2d")];
const tempCanvas = this.#tempCanvas;
optionalContentConfigPromise,
this.renderingId = "thumbnail" + id;
this.viewport = defaultViewport;
this.pdfPageRotate = defaultViewport.rotation;
this._optionalContentConfigPromise = optionalContentConfigPromise || null;
this.pageColors = pageColors || null;
this.eventBus = eventBus;
this.linkService = linkService;
this.renderingQueue = renderingQueue;
this.renderingState = RenderingStates.INITIAL;
const anchor = document.createElement("a");
anchor.href = linkService.getAnchorUrl("#page=" + id);
anchor.setAttribute("data-l10n-id", "pdfjs-thumb-page-title");
anchor.setAttribute("data-l10n-args", this.#pageL10nArgs);
anchor.onclick = function () {
linkService.goToPage(id);
const div = document.createElement("div");
div.className = "thumbnail";
div.setAttribute("data-page-number", this.id);
const img = document.createElement("div");
img.className = "thumbnailImage";
this._placeholderImg = img;
container.append(anchor);
const ratio = width / height;
this.canvasWidth = THUMBNAIL_WIDTH;
this.canvasHeight = this.canvasWidth / ratio | 0;
this.scale = this.canvasWidth / width;
style.setProperty("--thumbnail-width", `${this.canvasWidth}px`);
style.setProperty("--thumbnail-height", `${this.canvasHeight}px`);
this.pdfPageRotate = pdfPage.rotate;
const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
this.viewport = pdfPage.getViewport({
this.renderingState = RenderingStates.INITIAL;
this.div.removeAttribute("data-loaded");
this.image?.replaceWith(this._placeholderImg);
this.image.removeAttribute("src");
if (typeof rotation === "number") {
this.rotation = rotation;
const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
this.viewport = this.viewport.clone({
this.renderTask.cancel();
#getPageDrawContext(upscaleFactor = 1) {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d", {
const outputScale = new OutputScale();
canvas.width = upscaleFactor * this.canvasWidth * outputScale.sx | 0;
canvas.height = upscaleFactor * this.canvasHeight * outputScale.sy | 0;
const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null;
#convertCanvasToImage(canvas) {
if (this.renderingState !== RenderingStates.FINISHED) {
throw new Error("#convertCanvasToImage: Rendering has not finished.");
const reducedCanvas = this.#reduceImage(canvas);
const image = document.createElement("img");
image.className = "thumbnailImage";
image.setAttribute("data-l10n-id", "pdfjs-thumb-page-canvas");
image.setAttribute("data-l10n-args", this.#pageL10nArgs);
image.src = reducedCanvas.toDataURL();
this.div.setAttribute("data-loaded", true);
this._placeholderImg.replaceWith(image);
reducedCanvas.height = 0;
async #finishRenderTask(renderTask, canvas, error = null) {
if (renderTask === this.renderTask) {
if (error instanceof RenderingCancelledException) {
this.renderingState = RenderingStates.FINISHED;
this.#convertCanvasToImage(canvas);
if (this.renderingState !== RenderingStates.INITIAL) {
console.error("Must be in new state before drawing");
this.renderingState = RenderingStates.FINISHED;
throw new Error("pdfPage is not loaded");
this.renderingState = RenderingStates.RUNNING;
} = this.#getPageDrawContext(DRAW_UPSCALE_FACTOR);
const drawViewport = this.viewport.clone({
scale: DRAW_UPSCALE_FACTOR * this.scale
const renderContinueCallback = cont => {
if (!this.renderingQueue.isHighestPriority(this)) {
this.renderingState = RenderingStates.PAUSED;
this.renderingState = RenderingStates.RUNNING;
optionalContentConfigPromise: this._optionalContentConfigPromise,
pageColors: this.pageColors
const renderTask = this.renderTask = pdfPage.render(renderContext);
renderTask.onContinue = renderContinueCallback;
const resultPromise = renderTask.promise.then(() => this.#finishRenderTask(renderTask, canvas), error => this.#finishRenderTask(renderTask, canvas, error));
resultPromise.finally(() => {
this.eventBus.dispatch("thumbnailrendered", {
if (this.renderingState !== RenderingStates.INITIAL) {
this.setPdfPage(pdfPage);
if (scale < this.scale) {
this.renderingState = RenderingStates.FINISHED;
this.#convertCanvasToImage(canvas);
} = this.#getPageDrawContext();
if (img.width <= 2 * canvas.width) {
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
let reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS;
let reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS;
const [reducedImage, reducedImageCtx] = TempImageFactory.getCanvas(reducedWidth, reducedHeight);
while (reducedWidth > img.width || reducedHeight > img.height) {
reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight);
while (reducedWidth > 2 * canvas.width) {
reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1);
ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height);
page: this.pageLabel ?? this.id