From 43caa89de88aee44a720fcb3601bffc5bd20bd9a Mon Sep 17 00:00:00 2001 From: Noel Chou Date: Wed, 19 Nov 2025 13:35:15 -0500 Subject: [PATCH] BL-15441 add canvas origami element, use css for placeHolders --- DistFiles/localization/en/Bloom.xlf | 10 ++ artwork/placeholder.svg | 64 --------- src/BloomBrowserUI/bookEdit/css/editMode.less | 55 ++++---- .../js/CanvasElementContextControls.tsx | 14 +- .../bookEdit/js/CanvasElementManager.ts | 91 +++++++++---- .../bookEdit/js/bloomEditing.ts | 4 - src/BloomBrowserUI/bookEdit/js/bloomImages.ts | 31 +++-- src/BloomBrowserUI/bookEdit/js/origami.ts | 128 +++++++++++------- .../bookEdit/toolbox/games/GameTool.tsx | 3 +- .../impairmentVisualizer.tsx | 4 +- .../bookEdit/toolbox/motion/motionTool.tsx | 7 +- .../toolbox/talkingBook/audioRecording.ts | 2 +- .../collectionsTabBookPane/previewMode.less | 7 +- src/BloomBrowserUI/images/placeHolder.png | Bin 0 -> 3748 bytes src/BloomBrowserUI/placeHolderImages.less | 66 +++++++++ src/BloomExe/Book/Book.cs | 19 ++- src/BloomExe/Book/BookCompressor.cs | 2 +- src/BloomExe/Book/BookStorage.cs | 26 +--- .../Book/RuntimeInformationInjector.cs | 1 - src/BloomExe/BookThumbNailer.cs | 12 +- src/BloomExe/Edit/EditingModel.cs | 2 +- src/BloomExe/Edit/EditingView.cs | 23 ---- src/BloomExe/ImageProcessing/ImageUtils.cs | 26 ++-- .../Publish/BloomPub/BloomPubMaker.cs | 11 +- src/BloomExe/Publish/Epub/EpubMaker.cs | 44 +++--- src/BloomExe/Publish/PublishHelper.cs | 7 +- .../Spreadsheet/SpreadsheetExporter.cs | 4 +- src/BloomExe/Spreadsheet/SpreadsheetIO.cs | 6 +- .../Spreadsheet/SpreadsheetImporter.cs | 21 ++- src/BloomExe/web/BloomServer.cs | 7 + .../web/controllers/BookMetadataApi.cs | 9 +- .../web/controllers/EditingViewApi.cs | 12 -- src/BloomTests/Book/BookStorageTests.cs | 18 ++- .../Publish/ExportEpubTestsBaseClass.cs | 3 - .../Spreadsheet/SpreadsheetAudioTests.cs | 10 -- .../Spreadsheet/SpreadsheetImagesTests.cs | 10 -- .../Spreadsheet/SpreadsheetImporterTests.cs | 1 - .../basic/16x9 Landscape/placeHolder.png | Bin 6734 -> 0 bytes .../basic/A5 Portrait/placeHolder.png | Bin 6734 -> 0 bytes .../templates/bloom-foundation-mixins.pug | 2 +- .../template books/Activity/Activity.pug | 2 +- .../template books/Activity/placeHolder.png | Bin 6734 -> 0 bytes .../Arithmetic Template/placeHolder.png | Bin 6734 -> 0 bytes .../template books/Basic Book/placeHolder.png | Bin 6734 -> 0 bytes .../template books/Big Book/placeHolder.png | Bin 6734 -> 0 bytes .../Decodable Reader/placeHolder.png | Bin 6734 -> 0 bytes .../Digital Comic Book/placeHolder.png | Bin 6734 -> 0 bytes .../template books/Games/placeHolder.png | Bin 6734 -> 0 bytes .../Leveled Reader/placeHolder.png | Bin 6734 -> 0 bytes .../Paper Comic Book/placeHolder.png | Bin 6734 -> 0 bytes .../Picture Dictionary/placeHolder.png | Bin 6734 -> 0 bytes .../template books/Playground/placeHolder.png | Bin 6734 -> 0 bytes .../Sign Language/placeHolder.png | Bin 6734 -> 0 bytes .../Template Starter/placeHolder.png | Bin 6734 -> 0 bytes .../Template Maker/placeHolder.png | Bin 6734 -> 0 bytes .../Wall Calendar/Wall Calendar.pug | 2 +- .../Wall Calendar/placeHolder.png | Bin 6734 -> 0 bytes .../template books/eBook/placeHolder.png | Bin 6734 -> 0 bytes .../templates/template books/placeHolder.png | Bin 6734 -> 0 bytes 59 files changed, 416 insertions(+), 350 deletions(-) delete mode 100644 artwork/placeholder.svg create mode 100644 src/BloomBrowserUI/images/placeHolder.png create mode 100644 src/BloomBrowserUI/placeHolderImages.less delete mode 100644 src/BloomVisualRegressionTests/collections/basic/16x9 Landscape/placeHolder.png delete mode 100644 src/BloomVisualRegressionTests/collections/basic/A5 Portrait/placeHolder.png delete mode 100644 src/content/templates/template books/Activity/placeHolder.png delete mode 100644 src/content/templates/template books/Arithmetic Template/placeHolder.png delete mode 100644 src/content/templates/template books/Basic Book/placeHolder.png delete mode 100644 src/content/templates/template books/Big Book/placeHolder.png delete mode 100644 src/content/templates/template books/Decodable Reader/placeHolder.png delete mode 100644 src/content/templates/template books/Digital Comic Book/placeHolder.png delete mode 100644 src/content/templates/template books/Games/placeHolder.png delete mode 100644 src/content/templates/template books/Leveled Reader/placeHolder.png delete mode 100644 src/content/templates/template books/Paper Comic Book/placeHolder.png delete mode 100644 src/content/templates/template books/Picture Dictionary/placeHolder.png delete mode 100644 src/content/templates/template books/Playground/placeHolder.png delete mode 100644 src/content/templates/template books/Sign Language/placeHolder.png delete mode 100644 src/content/templates/template books/Template Starter/placeHolder.png delete mode 100644 src/content/templates/template books/UnusedTemplates/Template Maker/placeHolder.png delete mode 100644 src/content/templates/template books/Wall Calendar/placeHolder.png delete mode 100644 src/content/templates/template books/eBook/placeHolder.png delete mode 100644 src/content/templates/template books/placeHolder.png diff --git a/DistFiles/localization/en/Bloom.xlf b/DistFiles/localization/en/Bloom.xlf index 9ce3692f8818..7a4587e5aeca 100644 --- a/DistFiles/localization/en/Bloom.xlf +++ b/DistFiles/localization/en/Bloom.xlf @@ -1355,6 +1355,15 @@ Picture ID: EditTab.CustomPage.Picture + Obsolete as of 6.3 + + + Image + ID: EditTab.CustomPage.Image + + + Canvas + ID: EditTab.CustomPage.Canvas Text @@ -1871,6 +1880,7 @@ Cut image ID: EditTab.Image.CutImage + Obsolete as of Bloom 6.3 Edit image credits, copyright, & license diff --git a/artwork/placeholder.svg b/artwork/placeholder.svg deleted file mode 100644 index dcd3ba56fba1..000000000000 --- a/artwork/placeholder.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/src/BloomBrowserUI/bookEdit/css/editMode.less b/src/BloomBrowserUI/bookEdit/css/editMode.less index 37c983044691..31d9b91173b3 100644 --- a/src/BloomBrowserUI/bookEdit/css/editMode.less +++ b/src/BloomBrowserUI/bookEdit/css/editMode.less @@ -1,6 +1,7 @@ /*This stylesheet applied when a book is being edited. It does things like show that images can be changed by click on them.*/ @import "../../bloomUI.less"; @import "../sourceBubbles/sourceBubbles.less"; +@import "../../placeHolderImages.less"; @bleed: 3mm; // Duplicated from basePage.less to remove circular dependency between BloomBrowserUI and content @@ -491,7 +492,8 @@ body:not(.origami-drag) .bloom-canvas:hover { // In an active background canvas element, don't show the edit metadata icon if the image failed // to load. Clicking on it would just show an error message anyway, and the button would // obscure part of the alt attribute error message. -.bloom-canavas:has(.bloom-backgroundImage:has(img.bloom-imageLoadError)) { +.bloom-canvas:has(.bloom-backgroundImage:has(img.bloom-imageLoadError)), +.bloom-canvas:has(.bloom-backgroundImage:has(img[src*="placeHolder.png"])) { .editMetadataButton.imgMetadataProblem { display: none !important; } @@ -590,9 +592,11 @@ body.bloom-fullBleed { // on each parent. We could conceivably compute a different transform for each child, but this is more // straightforward and less error-prone. .bloom-describedImage { - // for a reason I haven't tracked down, the rule that usually does this doesn't work here. - img[src="placeHolder.png"] { - display: none; + // Repeated class name so we override even the rules for data-tool-id="canvas" in placeHolderImages.less + .bloom-backgroundImage.bloom-canvas-element.bloom-canvas-element:has( + img[src*="placeHolder.png"] + ) { + background-image: none; } height: 100%; width: 100%; @@ -664,16 +668,6 @@ body.bloom-fullBleed { } } -// In a bloom-canvas that has canvas elements other than the background image, we want to -// hide the placeholder except when the background image is active. -.bloom-canvas:has(.bloom-canvas-element:not(.bloom-backgroundImage)) { - .bloom-backgroundImage:not([data-bloom-active="true"]) { - img[src^="placeHolder.png"] { - display: none; - } - } -} - button.deleteButton { position: absolute; left: 0; @@ -1439,6 +1433,17 @@ canvas.moving { display: block; } + // We want the crop handles to look disabled on an empty/placeholder image. Disabling them is actually done in + // typescript code + &.bloom-image-control-frame-no-image { + .bloom-ui-canvas-element-side-handle, + .bloom-ui-canvas-element-move-crop-handle { + pointer-events: none; + cursor: unset; + opacity: 30%; + } + } + // The resize handles are the small circles in the four corners. // The move crop handle is the small circle in the center, used to change how an // image is cropped by (apparently) moving the image within the frame. @@ -1668,23 +1673,15 @@ svg.bloom-videoControl { } // If the background image hasn't been set in a game, we don't want to show the placeholder image. -.bloom-page[data-tool-id="game"]:not([data-activity="simple-dom-choice"]) - .bloom-backgroundImage - img[src="placeHolder.png"] { - visibility: hidden; -} -// We also want the crop handles to look disabled. Disabling them is actually done in -// typescript code. The pointer-events: none; seems not to work on the handle divs but -// is left as a reminder that we don't want to allow cropping in this case. (BL-14703) -.bloom-page[data-tool-id="game"]:not([data-activity="simple-dom-choice"]) - #canvas-element-control-frame.bloom-backgroundImage-control-frame-no-image { - .bloom-ui-canvas-element-side-handle, - .bloom-ui-canvas-element-move-crop-handle { - pointer-events: none; - cursor: unset; - opacity: 30%; +.bloom-page[data-tool-id="game"]:not([data-activity="simple-dom-choice"]) { + .bloom-canvas + .bloom-backgroundImage.bloom-canvas-element:has( + img[src="placeHolder.png"] + ) { + background-image: none; } } + .bloom-passive-element[data-bloom-active="true"] ~ .bloom-ui-canvas-element-resize-handle, .bloom-passive-element[data-bloom-active="true"] diff --git a/src/BloomBrowserUI/bookEdit/js/CanvasElementContextControls.tsx b/src/BloomBrowserUI/bookEdit/js/CanvasElementContextControls.tsx index 420bd4ee8ac2..b85bd803bc57 100644 --- a/src/BloomBrowserUI/bookEdit/js/CanvasElementContextControls.tsx +++ b/src/BloomBrowserUI/bookEdit/js/CanvasElementContextControls.tsx @@ -22,6 +22,7 @@ import { doImageCommand, getImageUrlFromImageContainer, kImageContainerClass, + isPlaceHolderImage, } from "./bloomImages"; import { doVideoCommand, @@ -122,7 +123,7 @@ const CanvasElementContextControls: React.FunctionComponent<{ const videoSource = video?.getElementsByTagName("source")[0]; const videoAlreadyChosen = !!videoSource?.getAttribute("src"); const isPlaceHolder = - hasImage && img?.getAttribute("src")?.startsWith("placeHolder.png"); + hasImage && isPlaceHolderImage(img?.getAttribute("src")); const missingMetadata = hasImage && !isPlaceHolder && @@ -374,9 +375,7 @@ const CanvasElementContextControls: React.FunctionComponent<{ menuOptions.splice(index, 0, fillItem); // we can't delete the placeholder (or if there isn't an img, somehow) - deleteEnabled = !!( - img && !img.getAttribute("src")?.startsWith("placeHolder.png") - ); + deleteEnabled = hasRealImage(img); } else if (isSpecialGameElementSelected || isLinkGrid) { deleteEnabled = false; // don't allow deleting the single drag item in a sentence drag game or link grids } @@ -1073,6 +1072,10 @@ function addVideoMenuItems( ); } +function hasRealImage(img) { + return img && !isPlaceHolderImage(img.getAttribute("src")); +} + function addImageMenuOptions( menuOptions: IMenuItemWithSubmenu[], canvasElement: HTMLElement, @@ -1093,6 +1096,7 @@ function addImageMenuOptions( ); }; + const realImagePresent = hasRealImage(img); const imageMenuOptions: IMenuItemWithSubmenu[] = [ { l10nId: "EditTab.Image.ChooseImage", @@ -1114,6 +1118,7 @@ function addImageMenuOptions( english: "Copy image", onClick: () => doImageCommand(img, "copy"), icon: , + disabled: !realImagePresent, }, { l10nId: "EditTab.Image.EditMetadataOverlay", @@ -1121,6 +1126,7 @@ function addImageMenuOptions( subLabelL10nId: "EditTab.Image.EditMetadataOverlayMore", onClick: runMetadataDialog, icon: , + disabled: !realImagePresent, }, { l10nId: "EditTab.Image.Reset", diff --git a/src/BloomBrowserUI/bookEdit/js/CanvasElementManager.ts b/src/BloomBrowserUI/bookEdit/js/CanvasElementManager.ts index 8aac0d87058a..2d9ccef7955d 100644 --- a/src/BloomBrowserUI/bookEdit/js/CanvasElementManager.ts +++ b/src/BloomBrowserUI/bookEdit/js/CanvasElementManager.ts @@ -38,6 +38,7 @@ import { SetupMetadataButton, UpdateImageTooltipVisibility, HandleImageError, + isPlaceHolderImage, } from "./bloomImages"; import { adjustTarget, @@ -71,13 +72,18 @@ import { CanvasGuideProvider } from "./CanvasGuideProvider"; import { CanvasElementKeyboardProvider } from "./CanvasElementKeyboardProvider"; import { CanvasSnapProvider } from "./CanvasSnapProvider"; import { get, postData, postJson } from "../../utils/bloomApi"; -import AudioRecording from "../toolbox/talkingBook/audioRecording"; +import AudioRecording, { + kTalkingBookToolId, +} from "../toolbox/talkingBook/audioRecording"; import PlaceholderProvider from "./PlaceholderProvider"; import { getExactClientSize } from "../../utils/elementUtils"; import { copyContentToTarget, getTarget } from "bloom-player"; import { showRequiresSubscriptionDialogInEditView } from "../../react_components/requiresSubscription"; import { FeatureStatus } from "../../react_components/featureStatus"; import $ from "jquery"; +import { kCanvasToolId } from "../toolbox/toolIds"; +import { getToolboxBundleExports } from "./bloomFrames"; +import { ImageDescriptionAdapter } from "../toolbox/imageDescription/imageDescription"; export interface ITextColorInfo { color: string; @@ -547,6 +553,9 @@ export class CanvasElementManager { bloomCanvas.scrollLeft = 0; bloomCanvas.scrollTop = 0; }); + if (bloomCanvas.getAttribute("data-tool-id") === kCanvasToolId) { + SetupClickToShowCanvasTool(bloomCanvas); + } }); // todo: select the right one...in particular, currently we just select the last one. @@ -1309,12 +1318,8 @@ export class CanvasElementManager { return; } const target = event.currentTarget as HTMLElement; - if ( - target.closest( - `.${kBackgroundImageClass}-control-frame-no-image`, - ) - ) { - return; // don't crop empty background image container + if (target.closest(`.bloom-image-control-frame-no-image`)) { + return; // don't crop empty image container } this.startSideControlDrag(event, side); }); @@ -2683,11 +2688,12 @@ export class CanvasElementManager { imgWidth = imgOrVideo.naturalWidth; imgHeight = imgOrVideo.naturalHeight; if ( - imgOrVideo.naturalHeight === 0 && // not loaded successfully (yet) - !useSizeOfNewImage && // not waiting for new dimensions - imgOrVideo.classList.contains("bloom-imageLoadError") // error occurred while trying to load + isPlaceHolderImage(imgOrVideo.getAttribute("src")) || + (imgOrVideo.naturalHeight === 0 && // not loaded successfully (yet) + !useSizeOfNewImage && // not waiting for new dimensions + imgOrVideo.classList.contains("bloom-imageLoadError")) // error occurred while trying to load ) { - // Image is in an error state; we probably won't ever get useful dimensions. Just leave + // Image is in an error state or is just a placeholder; we probably won't ever get useful dimensions. Just leave // the canvas element the shape it is. return; } @@ -2827,6 +2833,7 @@ export class CanvasElementManager { canvasElement, true, ); + SetupMetadataButton(canvasElement); } else { this.adjustContainerAspectRatio(canvasElement, true); } @@ -2883,20 +2890,16 @@ export class CanvasElementManager { kBackgroundImageClass + "-control-frame", this.activeElement.classList.contains(kBackgroundImageClass), ); - let backgroundImageExists = true; - if (this.activeElement.classList.contains(kBackgroundImageClass)) { - const img = getImageFromCanvasElement(this.activeElement); - if (img && img.getAttribute("src") === "placeHolder.png") { - backgroundImageExists = false; - } + + // mark empty image control frames with a special class + let imageIsPlaceHolder = false; + const img = getImageFromCanvasElement(this.activeElement); + if (img && isPlaceHolderImage(img.getAttribute("src"))) { + imageIsPlaceHolder = true; } - // mark empty background images in games with a special class (BL-14703) controlFrame.classList.toggle( - kBackgroundImageClass + "-control-frame-no-image", - !backgroundImageExists && - !!this.activeElement.closest( - ".bloom-page[data-tool-id='game']", - ), + "bloom-image-control-frame-no-image", + imageIsPlaceHolder, ); const hasText = controlFrame.classList.contains("has-text"); @@ -5009,7 +5012,7 @@ export class CanvasElementManager { canvasElements[0].classList.contains(kBackgroundImageClass) ) { const bgimg = canvasElements[0].getElementsByTagName("img")[0]; - if (bgimg.getAttribute("src")?.startsWith("placeHolder.png")) { + if (isPlaceHolderImage(bgimg.getAttribute("src"))) { changeImageInfo(bgimg, imageInfo); this.adjustBackgroundImageSize( bloomCanvas, @@ -5030,7 +5033,7 @@ export class CanvasElementManager { const img = activeElement .getElementsByClassName(kImageContainerClass)[0] ?.getElementsByTagName("img")[0]; - if (img && img.getAttribute("src")?.startsWith("placeHolder.png")) { + if (img && isPlaceHolderImage(img.getAttribute("src"))) { changeImageInfo(img, imageInfo); this.adjustContainerAspectRatio( activeElement as HTMLElement, @@ -6833,9 +6836,12 @@ export class CanvasElementManager { // image has the special class indicating that it failed to load. (The class is supposed // to be removed when we change the src attribute, which leads to a new load attempt.) failedImage = - img.naturalHeight === 0 && // not loaded successfully (yet) - !useSizeOfNewImage && // not waiting for new dimensions - img.classList.contains("bloom-imageLoadError"); // error occurred while trying to load + // As of BL-15441, we use css instead of real placeHolder.png files but still set src="placeHolder.png" + // to indicate placeholders. Treat this case as a failed image for dimensions purposes + isPlaceHolderImage(img.getAttribute("src")) || + (img.naturalHeight === 0 && // not loaded successfully (yet) + !useSizeOfNewImage && // not waiting for new dimensions + img.classList.contains("bloom-imageLoadError")); // error occurred while trying to load if (failedImage) { // If the image failed to load, just use the container aspect ratio to fill up // the container with the error message (alt attribute string). @@ -6992,7 +6998,7 @@ export class CanvasElementManager { // for greater accuracy in scaling. (BL-15464) const newCeWidth = CanvasElementManager.pxToNumber( bgCanvasElement.style.width, - bgCanvasElement.clientWidth + bgCanvasElement.clientWidth, ); const scale = newCeWidth / oldCeWidth; img.style.width = @@ -7106,7 +7112,7 @@ export class CanvasElementManager { const img = getImageFromCanvasElement(child); if ( !img || - img.getAttribute("src") === "placeHolder.png" || + isPlaceHolderImage(img.getAttribute("src")) || children.length === 1 ) { // If there's no image or it's a placeholder, and there are other overlays, it won't be visible, @@ -7534,3 +7540,28 @@ async function copyAudioFileAsync( // `DEBUG copyAudioFileAsync: finished copying ${sourcePath} to ${targetPath}` // ); } + +function SetupClickToShowCanvasTool(canvasElement: Element) { + // if the user clicks on a canvas element, bring up the canvas tool + $(canvasElement).click((ev) => { + const toolbox = getToolboxBundleExports()?.getTheOneToolbox(); + const currentToolId = toolbox?.getCurrentTool()?.id(); + + if ( + toolbox?.toolboxIsShowing() && + (currentToolId === ImageDescriptionAdapter.kToolID || + currentToolId === kTalkingBookToolId) + ) { + // Image description tool or talking book tool is already open; we don't want to interfere with its functioning + return; + } + + showCanvasTool(); + }); +} + +export function showCanvasTool() { + getToolboxBundleExports() + ?.getTheOneToolbox() + .activateToolFromId(kCanvasToolId); +} diff --git a/src/BloomBrowserUI/bookEdit/js/bloomEditing.ts b/src/BloomBrowserUI/bookEdit/js/bloomEditing.ts index 45a2f90ff191..e5d6cb54aba0 100644 --- a/src/BloomBrowserUI/bookEdit/js/bloomEditing.ts +++ b/src/BloomBrowserUI/bookEdit/js/bloomEditing.ts @@ -430,10 +430,6 @@ export function changeImage(imageInfo: IImageInfo) { ); } changeImageInfo(imgOrImageContainer, imageInfo); - const ancestor = imgOrImageContainer.parentElement?.parentElement; - if (ancestor) { - SetupMetadataButton(ancestor); - } // id is just a temporary expedient to find the right image easily in this method. imgOrImageContainer.removeAttribute("id"); theOneCanvasElementManager.updateCanvasElementForChangedImage( diff --git a/src/BloomBrowserUI/bookEdit/js/bloomImages.ts b/src/BloomBrowserUI/bookEdit/js/bloomImages.ts index ad9feb5fe615..a3e2bbde20ed 100644 --- a/src/BloomBrowserUI/bookEdit/js/bloomImages.ts +++ b/src/BloomBrowserUI/bookEdit/js/bloomImages.ts @@ -33,6 +33,15 @@ const kBrowserDpi = 96; export const kImageContainerClass = "bloom-imageContainer"; export const kImageContainerSelector = `.${kImageContainerClass}`; +// We don't use actual placeHolder.png files anymore, but we do continue to use +// src="placeHolder.png" to mark placeholders +export function isPlaceHolderImage(url: string | null | undefined): boolean { + if (!url) { + return false; + } + return url.toLowerCase().includes("placeholder.png"); +} + export function cleanupImages() { $(".bloom-imageContainer").css("opacity", ""); //comes in on img containers from an old version of myimgscale, and is a major problem if the image is missing $(".bloom-imageContainer").css("overflow", ""); //review: also comes form myimgscale; is it a problem? @@ -162,7 +171,7 @@ export function HandleImageError(event: Event) { export function doImageCommand( img: HTMLElement | undefined, - command: "cut" | "copy" | "paste" | "change", + command: "copy" | "paste" | "change", ) { if (!img) { return; @@ -493,7 +502,7 @@ async function DetermineImageTooltipAsync( const targetDpiHeight = Math.ceil( (300 * containerJQ.height()) / kBrowserDpi, ); - const isPlaceHolder = url.indexOf("placeHolder.png") > -1; + const isPlaceHolder = isPlaceHolderImage(url); const result = await getWithConfigAsync("image/info", { params: { image: url }, @@ -645,13 +654,6 @@ function getFileLengthString(bytes): string { return ""; } -// IsImageReal returns true if the img tag refers to a non-placeholder image -// If the image is a placeholder: -// - we don't want to offer to edit placeholder credits -function IsImageReal(img) { - return GetRawImageUrl(img).toLowerCase().indexOf("placeholder") == -1; //don't offer to edit placeholder credits -} - // Gets the src attribute out of images, and the background-image:url() of everything else function GetRawImageUrl(imgOrDivWithBackgroundImage): string { if ($(imgOrDivWithBackgroundImage).hasAttr("src")) { @@ -707,7 +709,7 @@ export function SetupMetadataButton(parent: HTMLElement) { continue; // pathological } const img = getImageFromContainer(container); - if (!img || !IsImageReal(img)) continue; // placeholder, doesn't get one of these buttons. + if (!img || !!isPlaceHolderImage(GetRawImageUrl(img))) continue; // placeholder, doesn't get one of these buttons. //review: should we also require copyright, illustrator, etc? In many contexts the id of the work-for-hire illustrator isn't available const copyright = img.getAttribute("data-copyright"); @@ -746,7 +748,14 @@ export function SetupMetadataButton(parent: HTMLElement) { // Instead of "missing", we want to show it in the right ui language. We also want the text // to indicate that it might not be missing, just didn't load (this happens on slow machines) function SetAlternateTextOnImages(element) { - if (GetRawImageUrl(element).length > 0) { + const rawImageUrl = GetRawImageUrl(element); + if (rawImageUrl.length > 0) { + if (isPlaceHolderImage(rawImageUrl)) { + // We now use css to display the placeholder image instead of an actual placeHolder.png file, + // but we are continuing to set and use src=placeHolder.png to trigger place holder behavior. So we + // don't expect to find a placeHolder.png file, and we don't want to display alt text. + return; + } //don't show this on the empty license image when we don't know the license yet const englishText = "This picture, {0}, is missing or was loading too slowly."; // Also update HtmlDom.cs::IsPlaceholderImageAltText diff --git a/src/BloomBrowserUI/bookEdit/js/origami.ts b/src/BloomBrowserUI/bookEdit/js/origami.ts index 5a1c76b7c1f3..e5bb91a50156 100644 --- a/src/BloomBrowserUI/bookEdit/js/origami.ts +++ b/src/BloomBrowserUI/bookEdit/js/origami.ts @@ -10,45 +10,58 @@ import { theOneCanvasElementManager } from "./CanvasElementManager"; import { getFeatureStatusAsync } from "../../react_components/featureStatus"; import $ from "jquery"; import { splitPane } from "../../lib/split-pane/split-pane"; +import { kCanvasToolId } from "../toolbox/toolIds"; $(() => { splitPane($("div.split-pane")); }); export function setupOrigami() { - getFeatureStatusAsync("widget").then((featureStatus) => { - const isWidgetFeatureEnabled: boolean = featureStatus?.enabled || false; - const customPages = document.getElementsByClassName("customPage"); - if (customPages.length > 0) { - const width = customPages[0].clientWidth; - const origamiControl = getAbovePageControlContainer() - .append(createTypeSelectors(isWidgetFeatureEnabled)) - .append(createTextBoxIdentifier()); - // The order of this is not important in most ways, since it is positioned absolutely. - // However, we position the page label, also absolutely, in the same screen area, and - // we want it on top of origami control, so that in template pages the user can edit it. - // The page label is part of the page, so we want the page to come after the origami control. - // (Could also do this with z-order, but I prefer to do what I can by ordering elements, - // and save z-order for when it is really needed.) - $("#page-scaling-container").prepend(origamiControl); - // The container width is set to 100% in the CSS, but we need to - // limit it to no more than the actual width of the page. - const toggleContainer = $(".above-page-control-container").get(0); - toggleContainer.style.maxWidth = width + "px"; - } - // I'm not clear why the rest of this needs to wait until we have - // the two results, but none of the controls shows up if we leave it all - // outside the bloomApi functions. - $(".origami-toggle .onoffswitch").change(layoutToggleClickHandler); - - if ($(".customPage .marginBox.origami-layout-mode").length) { - setupLayoutMode(); - $("#myonoffswitch").prop("checked", true); - } - - $(".customPage, .above-page-control-container") - .find("*[data-i18n]") - .localize(); + getFeatureStatusAsync("widget").then((widgetFeatureStatus) => { + getFeatureStatusAsync("canvas").then((canvasFeatureStatus) => { + const isWidgetFeatureEnabled: boolean = + widgetFeatureStatus?.enabled || false; + const isCanvasFeatureEnabled: boolean = + canvasFeatureStatus?.enabled || false; + const customPages = document.getElementsByClassName("customPage"); + if (customPages.length > 0) { + const width = customPages[0].clientWidth; + const origamiControl = getAbovePageControlContainer() + .append( + createTypeSelectors( + isWidgetFeatureEnabled, + isCanvasFeatureEnabled, + ), + ) + .append(createTextBoxIdentifier()); + // The order of this is not important in most ways, since it is positioned absolutely. + // However, we position the page label, also absolutely, in the same screen area, and + // we want it on top of origami control, so that in template pages the user can edit it. + // The page label is part of the page, so we want the page to come after the origami control. + // (Could also do this with z-order, but I prefer to do what I can by ordering elements, + // and save z-order for when it is really needed.) + $("#page-scaling-container").prepend(origamiControl); + // The container width is set to 100% in the CSS, but we need to + // limit it to no more than the actual width of the page. + const toggleContainer = $(".above-page-control-container").get( + 0, + ); + toggleContainer.style.maxWidth = width + "px"; + } + // I'm not clear why the rest of this needs to wait until we have + // the two results, but none of the controls shows up if we leave it all + // outside the bloomApi functions. + $(".origami-toggle .onoffswitch").change(layoutToggleClickHandler); + + if ($(".customPage .marginBox.origami-layout-mode").length) { + setupLayoutMode(); + $("#myonoffswitch").prop("checked", true); + } + + $(".customPage, .above-page-control-container") + .find("*[data-i18n]") + .localize(); + }); }); } @@ -412,13 +425,17 @@ function getCloseButton() { } // N.B. If we ever add a new type, make sure you also modify 'bloomContainerClasses'. -function createTypeSelectors(includeWidget: boolean) { +function createTypeSelectors(includeWidget: boolean, includeCanvas: boolean) { const space = " "; const links = $(""); - const pictureLink = $( - "Picture", + const imageLink = $( + "Image", ); - pictureLink.click(makePictureFieldClickHandler); + imageLink.click(makeImageFieldClickHandler); + const canvasLink = $( + "Canvas", + ); + canvasLink.click(makeCanvasFieldClickHandler); const textLink = $( "Text", ); @@ -432,13 +449,9 @@ function createTypeSelectors(includeWidget: boolean) { "HTML Widget", ); htmlWidgetLink.click(makeHtmlWidgetFieldClickHandler); - links - .append(pictureLink) - .append(",") - .append(space) - .append(videoLink) - .append(",") - .append(space); + links.append(imageLink).append(",").append(space); + if (includeCanvas) links.append(canvasLink).append(","); + links.append(space).append(videoLink).append(",").append(space); if (includeWidget) { links .append(textLink) @@ -487,20 +500,31 @@ function makeTextFieldClickHandler(e) { dialog.AttachToBox(this); }); } -function makePictureFieldClickHandler(e) { - e.preventDefault(); - const container = $(this).closest(".split-pane-component-inner"); +function makeImageOrCanvasFieldClickHandler( + clickedElement: JQuery, + isCanvasClick: boolean, +) { + const container = clickedElement.closest(".split-pane-component-inner"); addUndoPoint(); const bloomCanvas = $( - "
", - ); - const image = $( - "Could not load the picture", + `
`, ); + const image = $(""); bloomCanvas.append(image); SetupImage(image); // Must attach it first so event handler gets added to parent container.append(bloomCanvas); - $(this).closest(".selector-links").remove(); + clickedElement.closest(".selector-links").remove(); +} +function makeImageFieldClickHandler(e) { + e.preventDefault(); + makeImageOrCanvasFieldClickHandler($(this), false); +} + +function makeCanvasFieldClickHandler(e) { + e.preventDefault(); + makeImageOrCanvasFieldClickHandler($(this), true); } function makeVideoFieldClickHandler(e) { diff --git a/src/BloomBrowserUI/bookEdit/toolbox/games/GameTool.tsx b/src/BloomBrowserUI/bookEdit/toolbox/games/GameTool.tsx index a29f6a57fe79..ee964b5a0d8a 100644 --- a/src/BloomBrowserUI/bookEdit/toolbox/games/GameTool.tsx +++ b/src/BloomBrowserUI/bookEdit/toolbox/games/GameTool.tsx @@ -68,6 +68,7 @@ import { getGameType, isPageBloomGame } from "./GameInfo"; import { getImageFromCanvasElement, kImageContainerSelector, + isPlaceHolderImage, } from "../../js/bloomImages"; import { doesContainingPageHaveSameSizeMode } from "./gameUtilities"; import { CanvasSnapProvider } from "../../js/CanvasSnapProvider"; @@ -245,7 +246,7 @@ export const adjustTarget = ( const img = getImageFromCanvasElement(x); // I don't think we want to increase the minimum size of targets to account // for images that are still placeholders. - if (img && img.getAttribute("src") !== "placeholder.png") { + if (img && !isPlaceHolderImage(img.getAttribute("src"))) { draggableImages.push(x as HTMLElement); } else if (x !== draggable) { otherDraggables.push(x as HTMLElement); diff --git a/src/BloomBrowserUI/bookEdit/toolbox/impairmentVisualizer/impairmentVisualizer.tsx b/src/BloomBrowserUI/bookEdit/toolbox/impairmentVisualizer/impairmentVisualizer.tsx index bd877b1aebb2..ffa48cbaf556 100644 --- a/src/BloomBrowserUI/bookEdit/toolbox/impairmentVisualizer/impairmentVisualizer.tsx +++ b/src/BloomBrowserUI/bookEdit/toolbox/impairmentVisualizer/impairmentVisualizer.tsx @@ -8,7 +8,7 @@ import "./impairmentVisualizer.less"; import { RadioGroup } from "../../../react_components/RadioGroup"; import { deuteranopia, tritanopia, achromatopsia } from "color-blind"; import { ToolBottomHelpLink } from "../../../react_components/helpLink"; -import { kImageContainerClass } from "../../js/bloomImages"; +import { kImageContainerClass, isPlaceHolderImage } from "../../js/bloomImages"; import { CanvasElementManager } from "../../js/CanvasElementManager"; import { ThemeProvider } from "@mui/material"; import { ApiCheckbox } from "../../../react_components/ApiCheckbox"; @@ -232,7 +232,7 @@ export class ImpairmentVisualizerControls extends React.Component< window.setTimeout(() => this.makeColorBlindnessOverlay(img), 100); return; } - if (img.getAttribute("src") === "placeHolder.png") { + if (isPlaceHolderImage(img.getAttribute("src"))) { // I don't think any purpose is served by visualizing what color blindness does to // a greyscale image that won't show in the real book, and it makes for more // updates to correctly handle when it shows and hides. diff --git a/src/BloomBrowserUI/bookEdit/toolbox/motion/motionTool.tsx b/src/BloomBrowserUI/bookEdit/toolbox/motion/motionTool.tsx index 59d2b9801cd0..c318ff242441 100644 --- a/src/BloomBrowserUI/bookEdit/toolbox/motion/motionTool.tsx +++ b/src/BloomBrowserUI/bookEdit/toolbox/motion/motionTool.tsx @@ -16,6 +16,7 @@ import { DisableImageEditing, EnableImageEditing, getBackgroundImageFromBloomCanvas, + isPlaceHolderImage, } from "../../js/bloomImages"; import { kMotionToolId } from "../toolIds"; import { RequiresSubscriptionOverlayWrapper } from "../../../react_components/requiresSubscription"; @@ -497,7 +498,7 @@ export class MotionTool extends ToolboxToolReactAdaptor { const bgImage = this.getBackgroundImage(); if (bgImage) { const src = bgImage.getAttribute("src"); - haveBgImage = !!src && src.toLowerCase() !== "placeholder.png"; + haveBgImage = !!src && !isPlaceHolderImage(src); } const newState = this.getStateFromHtml(); if (haveBgImage) { @@ -569,7 +570,7 @@ export class MotionTool extends ToolboxToolReactAdaptor { const bgImage = this.getBackgroundImage(); if (bgImage) { const src = bgImage.getAttribute("src"); - if (!src || src.toLowerCase() === "placeholder.png") { + if (!src || isPlaceHolderImage(src)) { this.hideRectangles(); } this.observer.observe(bgImage, { @@ -938,7 +939,7 @@ export class MotionTool extends ToolboxToolReactAdaptor { src = bgImage?.getAttribute("src") || ""; } - const doNotHaveAPicture = !src || src.startsWith("placeHolder.png"); + const doNotHaveAPicture = !src || isPlaceHolderImage(src); let motionChecked = true; let motionPossible = !doNotHaveAPicture; diff --git a/src/BloomBrowserUI/bookEdit/toolbox/talkingBook/audioRecording.ts b/src/BloomBrowserUI/bookEdit/toolbox/talkingBook/audioRecording.ts index 01a2c45ee0e1..73dec3e7cdc3 100644 --- a/src/BloomBrowserUI/bookEdit/toolbox/talkingBook/audioRecording.ts +++ b/src/BloomBrowserUI/bookEdit/toolbox/talkingBook/audioRecording.ts @@ -122,7 +122,7 @@ const kBloomVisibleClass = "bloom-visibility-code-on"; const kAudioSplitId = "audio-split"; -const kTalkingBookToolId = "talkingBook"; +export const kTalkingBookToolId = "talkingBook"; export const kPlaybackOrderContainerClass: string = "bloom-playbackOrderControlsContainer"; diff --git a/src/BloomBrowserUI/collectionsTab/collectionsTabBookPane/previewMode.less b/src/BloomBrowserUI/collectionsTab/collectionsTabBookPane/previewMode.less index 4f9e85f509cc..d60753f81f71 100644 --- a/src/BloomBrowserUI/collectionsTab/collectionsTabBookPane/previewMode.less +++ b/src/BloomBrowserUI/collectionsTab/collectionsTabBookPane/previewMode.less @@ -1,4 +1,5 @@ @import (reference) "../../bloomUI.less"; +@import "../../placeHolderImages.less"; // This is wanted only for previewing templates, not real books. // Real books always have a data-l1 attribute added, and the standard basePage rules work for them. @@ -135,9 +136,11 @@ and as a result, the labels are shifted to this many pixels to the width. This s } // when making a PDF or a thumbnail, if no image is chosen, just don't show anything +// repeated class is necessary to override the data-tool-id="canvas" case in placeHolderImages.less // note that the *= here is needed in case there is a path, as happens in folio pdfs e.g. ../foo/placheholder.png -.hidePlaceHolders img[src*="placeHolder.png"] { - display: none; +.hidePlaceHolders.hidePlaceHolders.hidePlaceHolders.hidePlaceHolders + .bloom-canvas-element:has(img[src*="placeHolder.png"]) { + background-image: none; } @stripeGrey: #f0f0f0; diff --git a/src/BloomBrowserUI/images/placeHolder.png b/src/BloomBrowserUI/images/placeHolder.png new file mode 100644 index 0000000000000000000000000000000000000000..b76e98b72faa91e53528adcfbe324798fe7645e0 GIT binary patch literal 3748 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'); +@canvas-placeholder: url('data:image/svg+xml,'); + +.image-placeholder-background() { + background-image: @image-placeholder; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + + // Don't show the default "missing image" icon + img[src*="placeHolder.png"] { + display: none; + } +} + +.bloom-canvas .bloom-canvas-element:has(img[src*="placeHolder.png"]) { + .image-placeholder-background(); +} + +// When previewing templates in the Collection Tab, and also when in Change Layout mode in the Edit tab, +// img elements may not be wrapped in canvas-element divs (see BL-15514). Also below. +.preview:not([data-l1]), // Real books always have a data-l1 attribute added +.origami-layout-mode { + .bloom-canvas:not(:has(.bloom-canvas-element)):has( + img[src*="placeHolder.png"] + ) { + .image-placeholder-background(); + } +} + +// Use the easel placeholder instead of the usual flower placeholder for the background image whenever there is data-tool-id="canvas" +// (there are no legacy-style templates that should have the easel icon) +.bloom-canvas[data-tool-id="canvas"] + .bloom-backgroundImage.bloom-canvas-element:has( + img[src*="placeHolder.png"] + ), +.origami-layout-mode + .bloom-canvas[data-tool-id="canvas"]:not(:has(.bloom-canvas-element)):has( + img[src*="placeHolder.png"] + ) { + background-image: @canvas-placeholder; +} + +// In a bloom-canvas that has canvas elements other than the background image, we want to +// hide the placeholder except for when the background image is active/selected +.bloom-canvas.bloom-canvas:has( + .bloom-canvas-element:not(.bloom-backgroundImage) + ) { + .bloom-canvas-element.bloom-backgroundImage:not( + [data-bloom-active="true"] + ):has(img[src*="placeHolder.png"]) { + background-image: none; + } +} + +// For template books (made from the Template Starter), we do want to display the placeholder images in the bloompub. +// Hopefully we don't in any way put the string "placeHolder.png" in the inline style of canvases which should not get it! +// We need !important here to override the inline style attribute background-image which we normally use to put images in bloompubs +.bloomPlayer-page.template + .bloom-canvas[style*="background-image"][style*="placeHolder.png"] { + background-image: @image-placeholder !important; + + &[data-tool-id="canvas"] { + background-image: @canvas-placeholder !important; + } +} diff --git a/src/BloomExe/Book/Book.cs b/src/BloomExe/Book/Book.cs index ec638899be94..1ac1a2025e8f 100644 --- a/src/BloomExe/Book/Book.cs +++ b/src/BloomExe/Book/Book.cs @@ -16,6 +16,7 @@ using Bloom.Collection; using Bloom.FontProcessing; using Bloom.History; +using Bloom.ImageProcessing; using Bloom.Publish; using Bloom.SafeXml; using Bloom.SubscriptionAndFeatures; @@ -3185,7 +3186,7 @@ private bool NonTrivialImageFileExists(SafeXmlElement image) var file = imageUrl.PathOnly.NotEncoded; if (string.IsNullOrEmpty(file)) return false; - if (file == "placeHolder.png" && !image.HasAttribute("data-license")) + if (ImageUtils.IsPlaceholderImageFilename(file) && !image.HasAttribute("data-license")) return false; return RobustFile.Exists(Path.Combine(Storage.FolderPath, file)); } @@ -3427,7 +3428,11 @@ private static void RemoveImageResolutionMessageAndAddMissingImageMessage(HtmlDo { var src = img.GetAttribute("src"); var alt = img.GetAttribute("alt"); - if (!String.IsNullOrEmpty(src) && String.IsNullOrEmpty(alt)) + if ( + !String.IsNullOrEmpty(src) + && String.IsNullOrEmpty(alt) + && !ImageUtils.IsPlaceholderImageFilename(src) + ) { var localizedFormatString = LocalizationManager.GetString( "EditTab.Image.AltMsg", @@ -5183,6 +5188,12 @@ public string GetCoverImagePathAndElt(out SafeXmlElement coverImgElt) StoragePageFolder, ref coverImageFileName ); + // We no longer put placeHolder.png files in books (BL-15441) but we still need to detect when the placeholder + // is called for, so here we return placeHolder.png instead of null. Callers of this method should handle this special case. + if (ImageUtils.IsPlaceholderImageFilename(coverImagePath)) + { + return coverImagePath; + } if (!RobustFile.Exists(coverImagePath)) { // And the filename might be multiply-HTML encoded. @@ -5332,7 +5343,7 @@ private bool PageHasImages(SafeXmlElement page) { foreach (var img in page.SafeSelectNodes(".//img")) { - if (img.GetAttribute("src") != "placeHolder.png") + if (!ImageUtils.IsPlaceholderImageFilename(img.GetAttribute("src"))) return true; } foreach ( @@ -5343,7 +5354,7 @@ SafeXmlElement div in page.SafeSelectNodes( { var imgUrl = HtmlDom.GetImageElementUrl(div).PathOnly.NotEncoded; // Actually getting a background img url is a good indication that it's one we want. - if (!string.IsNullOrEmpty(imgUrl) && imgUrl != "placeHolder.png") + if (!string.IsNullOrEmpty(imgUrl) && !ImageUtils.IsPlaceholderImageFilename(imgUrl)) return true; } return false; diff --git a/src/BloomExe/Book/BookCompressor.cs b/src/BloomExe/Book/BookCompressor.cs index b41cc8f2f080..6fb3f84e3a51 100644 --- a/src/BloomExe/Book/BookCompressor.cs +++ b/src/BloomExe/Book/BookCompressor.cs @@ -46,7 +46,7 @@ int heightAndWidth BookThumbNailer.GenerateImageForWeb(book); var coverImagePath = book.GetCoverImagePath(); - if (coverImagePath == null) + if (coverImagePath == null || ImageUtils.IsPlaceholderImageFilename(coverImagePath)) { var blankImage = Path.Combine( FileLocationUtilities.DirectoryOfApplicationOrSolution, diff --git a/src/BloomExe/Book/BookStorage.cs b/src/BloomExe/Book/BookStorage.cs index 5984f55545fc..5b0244453d4e 100644 --- a/src/BloomExe/Book/BookStorage.cs +++ b/src/BloomExe/Book/BookStorage.cs @@ -321,7 +321,7 @@ public static void RemoveLocalOnlyFiles(string folderPath) /// code for those tasks has no business knowing about that status file. OTOH, /// some of those functions don't need some of the audio files; but a generic /// cleanup function like this doesn't know which ones. For now, it just deals - /// with TC cleanup and with any unused copies of the placeHolder.png image file. + /// with TC cleanup and any copies of the placeHolder.png image file left from older versions of Bloom. /// public static List LocalOnlyFiles(string folderPath) { @@ -332,30 +332,17 @@ public static List LocalOnlyFiles(string folderPath) } /// - /// Add unused copies of placeHolder.png in bookFolderPath to accumulator. + /// Add any copies of the placeHolder.png image file left from older versions of Bloom to accumulator. We don't use them anymore. /// private static void AddUnusedPlaceholderImages( string bookFolderPath, List accumulator ) { - // See https://issues.bloomlibrary.org/youtrack/issue/BL-7616 and also - // https://issues.bloomlibrary.org/youtrack/issue/BL-9479 for what has - // happened in the past that still can use cleanup in new work. + // We now no longer use placeHolder.png file in books (BL-15441) + // They may be there from older version of Bloom, remove them. var placeholders = Directory.GetFiles(bookFolderPath, "placeHolder*.png"); - if (placeholders.Length == 0) - return; - var htmlPath = FindBookHtmlInFolder(bookFolderPath); - if (String.IsNullOrEmpty(htmlPath)) - return; // shouldn't happen, but if it does we'll surely flag it elsewhere - var htmlContent = RobustFile.ReadAllText(htmlPath); - foreach (var filepath in placeholders) - { - var filename = Path.GetFileName(filepath); - if (htmlContent.Contains($" src=\"{filename}\"")) - continue; // file is used - accumulator.Add(filepath); - } + accumulator.AddRange(placeholders); } public string PathToExistingHtml @@ -1276,8 +1263,6 @@ var path in RobustIO ) ) continue; - if (filename.ToLowerInvariant() == "placeholder.png") - continue; // delete unused copies, but keep base placeholder image file even if unused at the moment imageFiles.Add(Path.GetFileName(GetNormalizedPathForOS(path))); } //Remove from that list each image actually in use @@ -2718,7 +2703,6 @@ public void UpdateSupportFiles() var supportFilesToUpdate = new List( new[] { - "placeHolder.png", BookInfo.AppearanceSettings.BasePageCssName, "previewMode.css", "origami.css", diff --git a/src/BloomExe/Book/RuntimeInformationInjector.cs b/src/BloomExe/Book/RuntimeInformationInjector.cs index fbff3871496f..dd8c9e0d22e2 100644 --- a/src/BloomExe/Book/RuntimeInformationInjector.cs +++ b/src/BloomExe/Book/RuntimeInformationInjector.cs @@ -326,7 +326,6 @@ private static void AddHtmlUiStrings(Dictionary d) "Edit image credits, copyright, & license" ); AddTranslationToDictionaryUsingKey(d, "EditTab.Image.CopyImage", "Copy image"); - AddTranslationToDictionaryUsingKey(d, "EditTab.Image.CutImage", "Cut image"); // tool tips for style editor AddTranslationToDictionaryUsingKey( diff --git a/src/BloomExe/BookThumbNailer.cs b/src/BloomExe/BookThumbNailer.cs index 8a628b81f685..9df6aa20645a 100644 --- a/src/BloomExe/BookThumbNailer.cs +++ b/src/BloomExe/BookThumbNailer.cs @@ -193,7 +193,7 @@ HtmlThumbNailer.ThumbnailOptions options { if (string.IsNullOrEmpty(imageSrc)) return false; - else if (Path.GetFileName(imageSrc) == "placeHolder.png") + else if (ImageUtils.IsPlaceholderImageFilename(imageSrc)) { // Valid examples: // thumbnail.png @@ -235,6 +235,16 @@ internal static bool CreateThumbnailOfCoverImage( if (!Directory.Exists(book.FolderPath)) return false; var imageSrc = book.GetCoverImagePathAndElt(out SafeXmlElement coverImgElt); + // We still use src="placeHolder.png" to indicate no image has been chosen, but we use css rather than a file to display it. + // Detect this case and use a placeHolder file to make the thumbnail. + // Enhance: skip unnecessary checking and processing below in the case where this is a placeholder image + if (!String.IsNullOrEmpty(imageSrc) && ImageUtils.IsPlaceholderImageFilename(imageSrc)) + { + var bloomRoot = FileLocationUtilities.GetDirectoryDistributedWithApplication( + BloomFileLocator.BrowserRoot + ); + imageSrc = Path.Combine(bloomRoot, "images", "placeHolder.png"); + } if (!IsCoverImageSrcValid(imageSrc, options)) { Debug.WriteLine(book.StoragePageFolder + " does not have a cover image."); diff --git a/src/BloomExe/Edit/EditingModel.cs b/src/BloomExe/Edit/EditingModel.cs index 7bbe2284fb3a..171d419eaafc 100644 --- a/src/BloomExe/Edit/EditingModel.cs +++ b/src/BloomExe/Edit/EditingModel.cs @@ -1977,7 +1977,7 @@ public void AdjustPageZoom(int delta) /// /// Make sure the book folder contains a current version of the video placeholder. - /// We don't copy this to every book like placeHolder.png, since relatively few books need it, + /// We don't copy this to every book, since relatively few books need it, /// but if it's used it needs to be there so things look right when opened in a browser. /// I don't think our image deletion code is smart enough to detect that something a CSS /// file says is needed as a background should not be deleted, so I've just made this diff --git a/src/BloomExe/Edit/EditingView.cs b/src/BloomExe/Edit/EditingView.cs index 51faded5c954..7d3f0221051f 100644 --- a/src/BloomExe/Edit/EditingView.cs +++ b/src/BloomExe/Edit/EditingView.cs @@ -738,29 +738,6 @@ public void CopyImageMetadataToAllImages(Metadata metadata) } } - public void OnCutImage(string imageId, UrlPathString imageSrc, bool imageIsGif) - { - var bookFolderPath = _model.CurrentBook.FolderPath; - - if (CopyImageToClipboard(imageSrc, bookFolderPath, imageIsGif)) // returns 'true' if successful - { - // Replace current image with placeHolder.png - // N.B. It is unnecessary to check for the existence of this file, since selecting a book in - // collection view triggers an automatic book update process that ensures that the file - // is put there if not already present. - var path = Path.Combine(bookFolderPath, "placeHolder.png"); - using (var palasoImage = PalasoImage.FromFileRobustly(path)) - { - _model.ChangePicture(imageId, imageSrc, palasoImage); - } - } - else - { - // remove imageId from the element since it's no longer needed - RemoveUnneededImageId(imageId); - } - } - public void OnCopyImage(UrlPathString imageSrc, bool imageIsGif) { // NB: bloomImages.js contains code that prevents us arriving here diff --git a/src/BloomExe/ImageProcessing/ImageUtils.cs b/src/BloomExe/ImageProcessing/ImageUtils.cs index f945fda33ff5..8fff704ba87f 100644 --- a/src/BloomExe/ImageProcessing/ImageUtils.cs +++ b/src/BloomExe/ImageProcessing/ImageUtils.cs @@ -257,6 +257,14 @@ public static bool HasJpegExtension(string filename) ); } + /// + /// Check whether the given path represents a placeholder image. + /// + public static bool IsPlaceholderImageFilename(string filename) + { + return Path.GetFileName(filename)?.ToLowerInvariant() == "placeholder.png"; + } + public static bool AppearsToBePng(PalasoImage imageInfo) { if (imageInfo == null || imageInfo.Image == null) @@ -331,13 +339,11 @@ bool isSameFile { //LogMemoryUsage(); - // If we go through all the processing and saving machinations for the placeholder image, - // we just get more and more placeholders when we cut images (BL-9011). - // And the normal update process that a book goes through when selecting it (in the Collection tab) - // for editing ensures that the placeHolder.png file is present in the book. + // As of BL-15441, we aren't using real placeHolder image files anymore. But if one is there, + // don't go through all the processing and saving machinations for it. if ( !string.IsNullOrEmpty(imageInfo.OriginalFilePath) - && imageInfo.OriginalFilePath.ToLowerInvariant().EndsWith("placeholder.png") + && IsPlaceholderImageFilename(imageInfo.OriginalFilePath) ) { return Path.GetFileName(imageInfo.OriginalFilePath); @@ -776,7 +782,7 @@ public static bool NeedToShrinkImages(string folderPath) .ToArray(); foreach (string path in pngFiles) { - if (Path.GetFileName(path)?.ToLowerInvariant() == "placeholder.png") + if (IsPlaceholderImageFilename(path)) continue; // Very large PNG files can cause "out of memory" errors here, while making thumbnails, // and when creating ePUBs or BloomPub books. So, we check for sizes bigger than our @@ -906,7 +912,7 @@ IProgress progress progress.ProgressIndicator.PercentCompleted = (int)( 100.0 * (float)completed / (float)totalFileCount ); - if (Path.GetFileName(path)?.ToLowerInvariant() == "placeholder.png") + if (IsPlaceholderImageFilename(path)) { ++completed; continue; @@ -963,7 +969,7 @@ IProgress progress !AppearsToBeJpeg(pi) && !IsIndexedAndOpaque(pi.Image) && Path.GetFileName(path).ToLowerInvariant() != "thumbnail.png" - && Path.GetFileName(path).ToLowerInvariant() != "placeholder.png" + && !IsPlaceholderImageFilename(path) ) { RemoveTransparency(pi, path, progress); @@ -2049,7 +2055,7 @@ string imageDestFolder { var src = img.GetAttribute("src"); // We don't want to crop placeHolder.png, just not display it. (BL-15201) - if (src == "placeHolder.png") + if (IsPlaceholderImageFilename(src)) continue; var style = img.GetAttribute("style"); if (!SignifiesCropping(style)) @@ -2061,7 +2067,7 @@ string imageDestFolder foreach (var img in images) { var src = img.GetAttribute("src"); - if (src == "placeHolder.png") + if (IsPlaceholderImageFilename(src)) continue; // we still don't want to crop placeHolder.png (BL-15229) var style = img.GetAttribute("style"); var imgContainer = img.ParentNode as SafeXmlElement; diff --git a/src/BloomExe/Publish/BloomPub/BloomPubMaker.cs b/src/BloomExe/Publish/BloomPub/BloomPubMaker.cs index 6abebc7afe95..657a7525b355 100644 --- a/src/BloomExe/Publish/BloomPub/BloomPubMaker.cs +++ b/src/BloomExe/Publish/BloomPub/BloomPubMaker.cs @@ -8,6 +8,7 @@ using System.Xml; using Bloom.Book; using Bloom.FontProcessing; +using Bloom.ImageProcessing; using Bloom.Publish.Epub; using Bloom.SafeXml; using Bloom.SubscriptionAndFeatures; @@ -726,9 +727,13 @@ private static void StripImgIfWeCannotFindFile(SafeXmlDocument dom, string bookF var imgElt in dom.SafeSelectNodes("//img[@src]").Cast().ToArray() ) { - var file = UrlPathString - .CreateFromUrlEncodedString(imgElt.GetAttribute("src")) - .PathOnly.NotEncoded; + // As of BL-15441, we use css rather than real files to display placeholders, but we still mark the img elements with src="placeHolder.png". + // Don't strip such img elements here - we want them to persist in template books. For other books we + // are already removing them in PublishHelper.RemoveUnwantedContent. + string src = imgElt.GetAttribute("src"); + if (ImageUtils.IsPlaceholderImageFilename(src)) + continue; + var file = UrlPathString.CreateFromUrlEncodedString(src).PathOnly.NotEncoded; if (!RobustFile.Exists(Path.Combine(folderPath, file))) { imgElt.ParentNode.RemoveChild(imgElt); diff --git a/src/BloomExe/Publish/Epub/EpubMaker.cs b/src/BloomExe/Publish/Epub/EpubMaker.cs index f45bc140b02d..10f208177f63 100644 --- a/src/BloomExe/Publish/Epub/EpubMaker.cs +++ b/src/BloomExe/Publish/Epub/EpubMaker.cs @@ -13,6 +13,7 @@ using Bloom.Api; using Bloom.Book; using Bloom.FontProcessing; +using Bloom.ImageProcessing; using Bloom.SafeXml; using Bloom.SubscriptionAndFeatures; using Bloom.ToPalaso; @@ -478,7 +479,8 @@ out double height // If we don't have an epub thumbnail, create a nice large thumbnail of the cover image // with the desired name. This is a temporary file stored only in the staged book folder // before being added to the epub. - if (!RobustFile.Exists(epubThumbnailImagePath)) + var thumbnailFileExists = RobustFile.Exists(epubThumbnailImagePath); + if (!thumbnailFileExists) { string coverPageImageFile = "thumbnail-256.png"; // name created by _thumbNailer ApplicationException thumbNailException = null; @@ -497,7 +499,7 @@ out double height return; // especially to avoid reporting problems making thumbnail, e.g., because aborted. var coverPageImagePath = Path.Combine(Book.FolderPath, coverPageImageFile); - if (thumbNailException != null || !RobustFile.Exists(coverPageImagePath)) + if (thumbNailException != null) { NonFatalProblem.Report( ModalIf.All, @@ -506,25 +508,23 @@ out double height "We will try to make the book anyway, but you may want to try again.", thumbNailException ); - - coverPageImageFile = "thumbnail.png"; // Try a low-res image, which should always exist + } + if (thumbNailException != null || !RobustFile.Exists(coverPageImagePath)) + { + coverPageImageFile = "thumbnail.png"; // Try a low-res image coverPageImagePath = Path.Combine(Book.FolderPath, coverPageImageFile); - if (!RobustFile.Exists(coverPageImagePath)) - { - // I don't think we can make an epub without a cover page so at this point we've had it. - // I suppose we could recover without actually crashing but it doesn't seem worth it unless this - // actually happens to real users. - throw new FileNotFoundException( - "Could not find or create thumbnail for cover page (BL-3209)", - coverPageImageFile - ); - } } - RobustFile.Move(coverPageImagePath, epubThumbnailImagePath); + if (RobustFile.Exists(coverPageImagePath)) + { + RobustFile.Move(coverPageImagePath, epubThumbnailImagePath); + thumbnailFileExists = true; + } + } + // Cover image file and therefore thumbnail file may be non-existent simply because no cover image was chosen/it was still the placeHolder, not a problem + if (thumbnailFileExists) + { + CopyFileToEpub(epubThumbnailImagePath, true, true, kImagesFolder, imageSettings); } - - CopyFileToEpub(epubThumbnailImagePath, true, true, kImagesFolder, imageSettings); - var warnings = EmbedFonts(progress); // must call after copying stylesheets if (warnings.Any()) PublishHelper.SendBatchedWarningMessagesToProgress(warnings, progress); @@ -552,7 +552,11 @@ out double height " ); - MakeManifest(kImagesFolder + "/" + Path.GetFileName(epubThumbnailImagePath)); + MakeManifest( + thumbnailFileExists + ? kImagesFolder + "/" + Path.GetFileName(epubThumbnailImagePath) + : null + ); foreach ( var filename in Directory.EnumerateFiles( @@ -2133,7 +2137,7 @@ SafeXmlElement img in HtmlDom.SelectChildImgAndBackgroundImageElements(pageEleme { bool isBrandingFile; // not used here, but part of method signature var path = FindRealImageFileIfPossible(img, out isBrandingFile); - if (!String.IsNullOrEmpty(path) && Path.GetFileName(path) != "placeHolder.png") // consider blank if only placeholder image + if (!String.IsNullOrEmpty(path) && !ImageUtils.IsPlaceholderImageFilename(path)) // consider blank if only placeholder image return false; } foreach ( diff --git a/src/BloomExe/Publish/PublishHelper.cs b/src/BloomExe/Publish/PublishHelper.cs index b09afd026a4d..113df979b62a 100644 --- a/src/BloomExe/Publish/PublishHelper.cs +++ b/src/BloomExe/Publish/PublishHelper.cs @@ -381,7 +381,7 @@ var div in dom.Body.SafeSelectNodes("//div[@role='textbox']").Cast c is SafeXmlElement ce && ce.LocalName == "img" ) as SafeXmlElement; - if (bcImg != null && bcImg.GetAttribute("src") != "placeHolder.png") + if ( + bcImg != null + && !ImageUtils.IsPlaceholderImageFilename(bcImg.GetAttribute("src")) + ) continue; // paranoia if (bcImg != null) { diff --git a/src/BloomExe/Spreadsheet/SpreadsheetExporter.cs b/src/BloomExe/Spreadsheet/SpreadsheetExporter.cs index 801cf544dfef..40a3903ab180 100644 --- a/src/BloomExe/Spreadsheet/SpreadsheetExporter.cs +++ b/src/BloomExe/Spreadsheet/SpreadsheetExporter.cs @@ -239,7 +239,7 @@ Color colorForPage ); var fileName = Path.GetFileName(imagePath); var outputPath = Path.Combine("images", fileName); - if (fileName == "placeHolder.png") + if (ImageUtils.IsPlaceholderImageFilename(fileName)) outputPath = InternalSpreadsheet.BlankContentIndicator; row.SetCell(InternalSpreadsheet.ImageSourceColumnLabel, outputPath); CopyImageFileToSpreadsheetFolder(imagePath); @@ -830,7 +830,7 @@ private void CopyImageFileToSpreadsheetFolder(string imageSourcePath) { if (_outputImageFolder != null) { - if (Path.GetFileName(imageSourcePath) == "placeHolder.png") + if (ImageUtils.IsPlaceholderImageFilename(imageSourcePath)) return; // don't need to copy this around. if (!RobustFile.Exists(imageSourcePath)) { diff --git a/src/BloomExe/Spreadsheet/SpreadsheetIO.cs b/src/BloomExe/Spreadsheet/SpreadsheetIO.cs index ad0697a686f6..b9ef488fc178 100644 --- a/src/BloomExe/Spreadsheet/SpreadsheetIO.cs +++ b/src/BloomExe/Spreadsheet/SpreadsheetIO.cs @@ -142,7 +142,11 @@ public static void WriteSpreadsheet( var imageSrc = sourceCell.Content; // if this row has an image source value that is not a header - if (imageSrc != "" && !row.IsHeader) + if ( + imageSrc != "" + && !ImageUtils.IsPlaceholderImageFilename(imageSrc) + && !row.IsHeader + ) { var sheetFolder = Path.GetDirectoryName(outputPath); var imagePath = Path.Combine(sheetFolder, imageSrc); diff --git a/src/BloomExe/Spreadsheet/SpreadsheetImporter.cs b/src/BloomExe/Spreadsheet/SpreadsheetImporter.cs index 9c6614d7e06c..520714aaa6ba 100644 --- a/src/BloomExe/Spreadsheet/SpreadsheetImporter.cs +++ b/src/BloomExe/Spreadsheet/SpreadsheetImporter.cs @@ -852,19 +852,11 @@ SafeXmlElement currentBloomCanvas // notes about its resolution, etc. We think it will be regenerated as needed, but certainly // the one from a previous background image is no use. currentBloomCanvas.RemoveAttribute("title"); - if (_pathToSpreadsheetFolder != null) //currently will only be null in tests + if ( + _pathToSpreadsheetFolder != null //currently will only be null in tests + && !ImageUtils.IsPlaceholderImageFilename(spreadsheetImgPath) + ) { - if (spreadsheetImgPath == "placeHolder.png") - { - // Don't assume the source has it, let's get a copy from files shipped with Bloom - fullSpreadsheetPath = Path.Combine( - BloomFileLocator.FactoryCollectionsDirectory, - "template books", - "Basic Book", - "placeHolder.png" - ); - } - CopyImageFileToDestination(destFileName, fullSpreadsheetPath, imgElement); } @@ -1025,7 +1017,10 @@ private async Task UpdateDataDivFromRowAsync(ContentRow currentRow, string dataB if (templateNodeIsNew) AddDataBookNode(templateNode); - if (_pathToSpreadsheetFolder != null) + if ( + _pathToSpreadsheetFolder != null + && !ImageUtils.IsPlaceholderImageFilename(imageFileName) + ) { // Make sure the image gets copied over too. var fullSpreadsheetPath = Path.Combine(_pathToSpreadsheetFolder, imageSrc); diff --git a/src/BloomExe/web/BloomServer.cs b/src/BloomExe/web/BloomServer.cs index 8b674a7b6441..7d7dc780f881 100644 --- a/src/BloomExe/web/BloomServer.cs +++ b/src/BloomExe/web/BloomServer.cs @@ -746,6 +746,13 @@ private bool ProcessImageFileRequest(IRequestInfo info) { imageFile = imageFile.Replace("flat", "icy_orange"); } + else if (ImageUtils.IsPlaceholderImageFilename(imageFile)) + { + // We now use css to put in the placeholder images, but still use "placeHolder.png" to mark them + // So we actually don't want to provide an image file for placeHolder.png. + info.WriteCompleteOutput(""); + return true; + } // If the user does add a video or widget, these placeholder .svgs will get copied to the // book folder and used from there. But we don't copy to the book folder while the user // is still in origami in case the user doesn't actually add the video or widget. diff --git a/src/BloomExe/web/controllers/BookMetadataApi.cs b/src/BloomExe/web/controllers/BookMetadataApi.cs index b105484df1d8..ef39dc6fdea8 100644 --- a/src/BloomExe/web/controllers/BookMetadataApi.cs +++ b/src/BloomExe/web/controllers/BookMetadataApi.cs @@ -1,7 +1,9 @@ -using System; +using System; +using System.IO; using Bloom.Api; using Bloom.Book; using Bloom.CollectionTab; +using Bloom.ImageProcessing; using L10NSharp; namespace Bloom.web.controllers @@ -51,12 +53,15 @@ private void HandleBookMetadata(ApiRequest request) var licenseUrl = book.GetLicenseMetadata().License.Url; if (string.IsNullOrEmpty(licenseUrl)) licenseUrl = null; // allows us to use ?? below. + string coverImagePath = book.GetCoverImagePath(); var metadata = new { metapicture = new { type = "image", - value = "/bloom/" + book.GetCoverImagePath(), + value = ImageUtils.IsPlaceholderImageFilename(coverImagePath) + ? "" + : "/bloom/" + coverImagePath, translatedLabel = LocalizationManager.GetString( "BookMetadata.metapicture", "Picture" diff --git a/src/BloomExe/web/controllers/EditingViewApi.cs b/src/BloomExe/web/controllers/EditingViewApi.cs index a0430fc21b79..b1a5994cec05 100644 --- a/src/BloomExe/web/controllers/EditingViewApi.cs +++ b/src/BloomExe/web/controllers/EditingViewApi.cs @@ -75,7 +75,6 @@ public void RegisterWithApiHandler(BloomApiHandler apiHandler) ); apiHandler.RegisterEndpointHandler("editView/topics", HandleTopics, false); apiHandler.RegisterEndpointHandler("editView/changeImage", HandleChangeImage, true); - apiHandler.RegisterEndpointHandler("editView/cutImage", HandleCutImage, true); apiHandler.RegisterEndpointHandler("editView/copyImage", HandleCopyImage, true); apiHandler.RegisterEndpointHandler("editView/pasteImage", HandlePasteImage, true); apiHandler.RegisterEndpointHandler("editView/paste", HandlePaste, true); @@ -282,17 +281,6 @@ private void HandleCopyImage(ApiRequest request) request.PostSucceeded(); } - private void HandleCutImage(ApiRequest request) - { - dynamic data = DynamicJson.Parse(request.RequiredPostJson()); - View.OnCutImage( - data.imageId, - UrlPathString.CreateFromUrlEncodedString(data.imageSrc), - data.imageIsGif - ); - request.PostSucceeded(); - } - private void HandleChangeImage(ApiRequest request) { dynamic data = DynamicJson.Parse(request.RequiredPostJson()); diff --git a/src/BloomTests/Book/BookStorageTests.cs b/src/BloomTests/Book/BookStorageTests.cs index 970dc73b96aa..8148b8317e94 100644 --- a/src/BloomTests/Book/BookStorageTests.cs +++ b/src/BloomTests/Book/BookStorageTests.cs @@ -760,7 +760,7 @@ public void CleanupUnusedImageFiles_ImageOnlyReferencedInDataDiv_ImageNotRemoved } [Test] - public void CleanupUnusedImageFiles_ThumbnailsAndPlaceholdersNotRemoved() + public void CleanupUnusedImageFiles_ThumbnailsNotRemoved() { var storage = GetInitialStorageWithCustomHtml( XmlHtmlConverter.CreateHtmlString( @@ -769,15 +769,27 @@ public void CleanupUnusedImageFiles_ThumbnailsAndPlaceholdersNotRemoved() ); var p1 = MakeSamplePngImage(Path.Combine(_folder.Path, "thumbnail.png")); var p2 = MakeSamplePngImage(Path.Combine(_folder.Path, "thumbnail88.png")); - var p3 = MakeSamplePngImage(Path.Combine(_folder.Path, "placeholder.png")); var dropmeTemp = MakeSamplePngImage(Path.Combine(_folder.Path, "dropme.png")); storage.CleanupUnusedImageFiles(); Assert.IsTrue(File.Exists(p1.Path)); Assert.IsTrue(File.Exists(p2.Path)); - Assert.IsTrue(File.Exists(p3.Path)); Assert.IsFalse(File.Exists(dropmeTemp.Path)); } + [Test] + public void CleanupUnusedImageFiles_PlaceholderFilesRemoved() + { + // BL-15441 + var storage = GetInitialStorageWithCustomHtml( + XmlHtmlConverter.CreateHtmlString( + "
" + ) + ); + var placeholder = MakeSamplePngImage(Path.Combine(_folder.Path, "placeholder.png")); + storage.CleanupUnusedImageFiles(); + Assert.IsFalse(File.Exists(placeholder.Path)); + } + [Test] public void CleanupUnusedImageFiles_UnusedImageIsLocked_NotException() { diff --git a/src/BloomTests/Publish/ExportEpubTestsBaseClass.cs b/src/BloomTests/Publish/ExportEpubTestsBaseClass.cs index 09f422b7922b..6bce38ee79cf 100644 --- a/src/BloomTests/Publish/ExportEpubTestsBaseClass.cs +++ b/src/BloomTests/Publish/ExportEpubTestsBaseClass.cs @@ -641,9 +641,6 @@ protected void CheckBasicsInManifest(params string[] imageFiles) assertThatManifest.HasAtLeastOneMatchForXpath( "package/manifest/item[@properties='nav']" ); - assertThatManifest.HasAtLeastOneMatchForXpath( - "package/manifest/item[@properties='cover-image']" - ); assertThatManifest.HasAtLeastOneMatchForXpath( "package/manifest/item[@id='defaultLangStyles' and @href='" diff --git a/src/BloomTests/Spreadsheet/SpreadsheetAudioTests.cs b/src/BloomTests/Spreadsheet/SpreadsheetAudioTests.cs index 36a93ed8cf48..c1cb38b995ad 100644 --- a/src/BloomTests/Spreadsheet/SpreadsheetAudioTests.cs +++ b/src/BloomTests/Spreadsheet/SpreadsheetAudioTests.cs @@ -149,16 +149,6 @@ protected void Setup(string pagesContent, string titleOverride = null) ); _exporter = new SpreadsheetExporter(mockLangDisplayNameResolver.Object); - var placeHolderSource = Path.Combine( - BloomFileLocator.FactoryCollectionsDirectory, - "template books", - "Basic Book", - "placeHolder.png" - ); - RobustFile.Copy( - placeHolderSource, - Path.Combine(_bookFolder.FolderPath, "placeHolder.png") - ); _progressSpy = new ProgressSpy(); Sheet = _exporter.ExportToFolder( diff --git a/src/BloomTests/Spreadsheet/SpreadsheetImagesTests.cs b/src/BloomTests/Spreadsheet/SpreadsheetImagesTests.cs index 61fdd22babb8..5cceee9b4421 100644 --- a/src/BloomTests/Spreadsheet/SpreadsheetImagesTests.cs +++ b/src/BloomTests/Spreadsheet/SpreadsheetImagesTests.cs @@ -209,16 +209,6 @@ var name in new[] Path.Combine(path, name), Path.Combine(_bookFolder.FolderPath, name) ); - var placeHolderSource = Path.Combine( - BloomFileLocator.FactoryCollectionsDirectory, - "template books", - "Basic Book", - "placeHolder.png" - ); - RobustFile.Copy( - placeHolderSource, - Path.Combine(_bookFolder.FolderPath, "placeHolder.png") - ); _progressSpy = new ProgressSpy(); _sheetFromExport = _exporter.ExportToFolder( diff --git a/src/BloomTests/Spreadsheet/SpreadsheetImporterTests.cs b/src/BloomTests/Spreadsheet/SpreadsheetImporterTests.cs index b294ab63d312..6abed15dd9c0 100644 --- a/src/BloomTests/Spreadsheet/SpreadsheetImporterTests.cs +++ b/src/BloomTests/Spreadsheet/SpreadsheetImporterTests.cs @@ -1233,7 +1233,6 @@ public void XMatterUpdatesTitleCorrectlyOnImport() [TestCase("Othello 199.jpg")] [TestCase("Mars 3.png")] [TestCase("Mars 4.png")] - [TestCase("placeHolder.png")] public void ImageCopiedToOutput(string fileName) { Assert.That(RobustFile.Exists(Path.Combine(_bookFolder.FolderPath, fileName))); diff --git a/src/BloomVisualRegressionTests/collections/basic/16x9 Landscape/placeHolder.png b/src/BloomVisualRegressionTests/collections/basic/16x9 Landscape/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/BloomVisualRegressionTests/collections/basic/A5 Portrait/placeHolder.png b/src/BloomVisualRegressionTests/collections/basic/A5 Portrait/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/bloom-foundation-mixins.pug b/src/content/templates/bloom-foundation-mixins.pug index 6428b79c8e64..8553829f62b3 100644 --- a/src/content/templates/bloom-foundation-mixins.pug +++ b/src/content/templates/bloom-foundation-mixins.pug @@ -117,7 +117,7 @@ mixin field-version1(placeholder) mixin image - requireZeroArguments('image', arguments); .bloom-canvas&attributes(attributes) - img(src="placeHolder.png", width=attributes.initialImageWidth, alt='This picture, placeHolder.png, is missing or was loading too slowly.') + img(src="placeHolder.png", width=attributes.initialImageWidth) block mixin video diff --git a/src/content/templates/template books/Activity/Activity.pug b/src/content/templates/template books/Activity/Activity.pug index ea62facc6695..8ebdecf6da61 100644 --- a/src/content/templates/template books/Activity/Activity.pug +++ b/src/content/templates/template books/Activity/Activity.pug @@ -60,7 +60,7 @@ html //- div.bloom-canvas-element.ui-resizable.ui-draggable(data-img-txt="1" data-bubble="{`version`:`1.0`,`style`:`none`,`tails`:[],`level`:1,`backgroundColors`:[`transparent`]}" style="left: 60px; top: 80px; width: 100px; height: 100px; position: absolute;") //- //- tabindex 0 is necessary for canvas element image containers so they can properly be set as the active canvas element. //- .bloom-imageContainer(tabindex="0") - //- img(src="placeHolder.png", width="100px", alt='This picture, placeHolder.png, is missing or was loading too slowly.') + //- img(src="placeHolder.png", width="100px") //- //- a corresponding text box //- div.bloom-canvas-element.ui-resizable.ui-draggable.bloom-allowAutoShrink.bloom-wordChoice.bloom-activeTextBox(data-txt-img="1" data-bubble="{`version`:`1.0`,`style`:`none`,`tails`:[],`level`:1,`backgroundColors`:[`transparent`]}" style="left: 60px; top: 20px; width: 91px; height: 31px; position: absolute;") //- .bloom-translationGroup(data-default-languages='auto') diff --git a/src/content/templates/template books/Activity/placeHolder.png b/src/content/templates/template books/Activity/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Arithmetic Template/placeHolder.png b/src/content/templates/template books/Arithmetic Template/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Basic Book/placeHolder.png b/src/content/templates/template books/Basic Book/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Big Book/placeHolder.png b/src/content/templates/template books/Big Book/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 zcmeI0_fr#Eu*XA{s)zytf^?87O+chd?=1QL3euHY33 zAkw8=LsO&+^0@!R`{liz&wh8#&e@qWd*;mSoD>T)eP#wO1^@uSY-pfk1prWhuH2lC z>MAoJQqz;u zGTx-Wy&@$eGxcp|+S{zO%&hdx?2OEu^sN8L$jW(}otv4R_ckXlGbb-A7oL>|%g%#m z!{9ma{9IT;4!j^2UXYhx2+J?ZEBFssK@q&LIKQw2UR0W2R8mk}T3Gz9pro|0q^z*y zT~TRSaVetc9isRhqNJ?6w5*~8QC^C;(u#NGm1X5s?<%UxDyk5b)#X+HQBhTcsH!cm zs;Q{1sjR83szz4Spek$8l{Lt!T4Z%Cx(bP^L0&1Q8i}q!VQSHJHE3)t23L#5ATf1U zpfEUO9Tr_zkF2Xl)#1=s90pfkhiyP%8_+mBroIt_YpAPlz}7d`HQ;d#SK5TdH`e0` zSUdsO)Lh@#)X+%46Nrt3<_2O5p3vM#Y;J09ArM>f&25d%ZA~rhO)ag&mUcpGTXSm% zp{>28t&`Z^)!f$6+TPjL(b?YFbwx*4_Z6KzyqamAn(GYa43)%sVv9 zE!YcS;pQ6{Ds83<qy`AXGleW|06^QR-os0prY}{-rwdb!?ld%@s!9rXUy~ND<=EbEi z$$TZ3IfK0IDm*!T&&G+a*xwcyrkN!om*7K1%gsva3aX)>4JnUjP9}>Q)R_JPeTt{% zW&&ktC^9oe(`Whd0Xf8y=FFN@m2qwsY6EdxwF_K#X84deAMK3XJ^EBXI^fLD@*$PG z^l$tCz?%tEkn`@MI$}s=hcN*YhOV&iBmU(B6JJ^L+^Vt1 z1km?7s#!a+Cfj3}Plm~bkV7kRwzgvsM-R~M7Kvfw*1K_%42c4*I5!!7MCpuLZ0d76 zzi2iOIW&UOBory4%s0s}G>pl3xk1D4(D3j&W0Be~vuCzZR&2I_I=!s`vE^L!!dxq> z-($P252nP8QF}EjwNavu!5NQp9Z8TxWD)l-Oi*u#s2ZcC{op!8HJx7u*-28L=0(^? z>atB^o?D$6OLe(oh~sn9z0KJA(P# zSYG`|9PEwk1*<7fJ0sdZ$8FV3G;$yzLk=Q@G6~niZ5zQTjt5JOz?P>SvBq7RAf;uw z!2UL81bUYecSKFXj!7d#&mjl-a-a;%lg>s;Lg}96u1@mTg1o$VlpZB;vzh&&5$y|iz1OPMv2pwKW#s-v^tUe}hl9z8v0Or}+sn?l)6Q$&e zjP@LFT|1|ZCo}tTg5wGsA6YKBHNp!xH0vmPrIQuTD3n2KVM~rnBw<@p{MWu32It?h zg%Ww<@5{YU7iDJ{140SZ5^+FFH)t(mVLwuxgDIs%0h~@tU&?S4#Qo4d{8_gVA3E}% zIUC^zi<0uf_By`aEY?l~OH5@k%-6Nq9;>|0k)1O2iJ(a#EYf0i?WM!)-j7y`1AwP+d~ zwM>tlaSVYJ2g)*nT8C^$<-A~CviJ~mce+W*`w5xO*>ROYv9a37jq z?s{ADJSWJb|#iKTBv&bQ@zRRXf0DB0Hz_d7eQn|Pbq3d9@?{h6=U7(+lIYI z-*UxDP^)6WX3!QL6;iloz%Vo%^sQS?Fl*x0P&Kfn1LrAt$poI+00S#^F~TOKGc|an~ZdAg8@P9F->wmIMk^9 zY(AnTd-w5AQBo4JbK($aHVOoZ>|GaT!Wfx=UZ~(MsvlTFADzf3Xt%U)7BB;0oz!Hb z9|F16U@Fii)v%*!I~yG5uB7pMFiqMyL9&vJ3*0Ete`H$<^S_P@4i+fqoV6l={(fX; z^oiu&g7_OD&vQm8T2W7bM}iRI@*iTsO4)wH>f@_9an)C&=)}f%5wyT>w;<@Z_yB8d z(L~_~w&)X_rGD;EIIa`hKa~fE$hVID>9R@u%KU96pjK4h&eZ)aEa?a_u3IFXhQJ>0R;W?#n z->9Fg&^Ce--4|X9xjSwJT}*{3LZb0&TO~V}x%)H)cl{ttKP@T;Qsub7iXzx2A`Rr` z(A|x5xn}YjRXR$)Q;wfUEY}V_84hj%N9J+Wi*H+hWf?v`{ic%@V}2OZW&SHPRou!& zbafJFJsj&Oy|`hU9)^NIGsmXyWD!Y$motvZnfW+X7YWhkp;^oEa zz54PIuWn;Bm;Gl9J?NrXxSSzpo$I13{HpTEL>pG3KA&h=rJ$k6r#xGgs^+p5=XE*O zq7-1SM0u1m>=IP*xsYvsu8LtAX2*5^bR=@P`}DBqaC$HE!=^?VB@yu?G}1${1HsSY=trc2B=oZff;S(tg(Ey-CtErZr)FquBM z%aFHKWP$3A>Yg|0h&kQixi&ufDLBA{WbUe4y<6#`UGUIT`fPz+ZpQtI2`F4^IFNzr z-cqu5#(MXWa-ulugN_Nw+0-fJCg#bw+~viy_Oq|X-zGWK8jVp#b(cJDNYl@MI)H2h zj^-|z$xgEgoJ9af&2h`=Jx0F=L9H@%DWFTsx^j{I&4s}e3Q2yM;BpzUmPbF;m?2%! zrjPr}G@DA-v@C#sv=V^wCw>&nG^bPpLZJH*Btk;r&b5JXbE$C&!^vRU}9eME3xyBN2%uA)| zlUN@X;8LDEDPp0+CnF4-fH;d2BGp&TvnrN}fcDgCz#U?Shqz4!Qw7wS#!UrDdZP1^ ziK1L#=&xTj1>_17?{vq-+-h>TZo|!1_Wp^(mPTOAafjk;1w-^;oZDNF;kD`w(9Y0` zv-t-iW=pb=HZKk`Az|aYYM&NpV zHieBzDCYzIy#Uz;8e-&De2emt((*$(*nuvzPLuR4b=l7X9Hip%XXaBXu*(#`)&qVP zw~&c+J=R-2FfD(V6h5=8N0)bS`=#2_L(=vICYo?cF~T7E!exrGudv$r)94}ub9|<4 zG-K`RsM)vW%2E-JviTDnM)PO(&dD7*M#-ZlG0CUi^SjF1*Th%$s!QC5M{acufQ#3jNjQZZ7Hw~j4d2{OujX1} z8Z$VrSgE3ZLit^gBcimPUzz??*Q%O zS@PNNteiaPy))oT_*||Hbm9V_O8utf8dpJq?XSXG+G~mq#O;h5F9NaD4H6um?>N;u zc)tD$4@E8#?j^C)xBdlwq;=zDhKE`(qZ@=B;@)g+jinW|eU0J3hoF~jgp;B@4lk5{ zIj#Tg!5vty!pV0<-ufTJnADBcOKnSDs&`bSb~Sj!>w{E+79O00X|xmxo+yJQJN5%X z-)&*d*Z9=Ir}r1^Wzf9zlAM-pB{YxudW1=rDr{SWGp-)|oGA3-o;Q0?F7c^OD5Z<7 zB=qqkX`c@Z`fDE?V^3xnev_0qCq%{!db@2FX0Z-goI-?(DYgqTZS)OpUHzto*8|{t z24WwB92Q!OazrH|7`fwC=BUgNTu>_`gsFde%pYo!Z4QK1ex;7fAp0_Pr#Axw& zM}+@itrHGb+ha*btrf8ueqv3QZN10!Y5#T9LXGuM5c`s7^n1>K*?-}g?>Q{1&x~p@I9c3@~D_u@zMv#RFbLG&3_&Da&rj+c1De#n>z*=RXdxJKYDi zjU^X%U$&*Uu_E8m=QFr8Z3r@K--{!EXry!vq|Ek`qy%+qC6>NdX-2V{UE6Z;`{yaO zQnus9hSP_k)E1CTQnQ?u)X~k{ExGbD$9xEORY90qxrj^ys`O=JFS}zS-F%>|NG-lt zA7Mw8UTFqHO+(T(jUR&!=M)*znRR*`hyG#Pp*Zl%*U=3ZQ;PZ{gZv(r*Z|xMM>@R+ zMp$~vjCYckVnq%K-siR%E4G-^Q zNQNm6dMjJd>ZA#{131+?tttXWos|1D%6K!N#H7_1Zw4>~ZH?G-Jc$(by^+r(alzXw zDlQyf6%kv_E&SZU=I8j!Jne1YpkdsT+PQG~RYKQ>nXtuBYE{GtY9r~RD(qJyt{6<0 zz-9>QxcB0kq7vboybG_0JDuU-t@UNd4ocUPEbB=nlRx!3SvK zcADS%b^fPlP9oJ$!1%cHh>R!tt6~NplCs{Fu@G_;YR3YM8{(29`MU_ttM4NC`7Z9o z)OxLdcWETfmSE$)C>`|{y}y3TBLMXL{sWH6JweuTNL%d~1P^4p(Xc*seGQ&m%W^Na z8m;6yo}5J+JjS?2*4knXtsXMUvq01J17x#(0@N^@_a0t_~lMJnCbGyF>tt_pBHQAB-x< zb2NEjazyCJWKx_mpvWa-e)nSr%uo7aje8NzV-*!QLz^vdi!KlIde2T`JK|x{wV;k5 zkk|F@45I(Xd{UtS$;;nWgtb9)c8^p~YKP_tTV>pR_q4vd`ol^{1VHrg&Kfwy1tZo@ zWf3RlZh7|?K*BO^-xJXXsnZ~V7dSCe2h%(GjqUu1zG+W%%OG<(Y=wZ$^>q%+#|oWz z>&bz9h9C*(2BtWtcVbAB+OysaJY{#I&3vB!IGci90BenP2H1gwpwooUDOt#Q*J^bt zk0Hq3ioLr41-O8zDPU6a=BmZQaNu8e+J-L`>fW~IdC2w$)8PfXXZ-!h7Cn__vb#7S zflIeu^Km0pbE6(xB2pRkP8`VkzYoDy9pagzcdUs_WVm<%(%NRnR z=m`s)^7KRRLKBgCzy0g7JWSRV*%o>ERHxuca?Mtj`bs@!YS+gI%7sjMc&b*x0GlXYg!P&u^F&J1`eDEj^Cl_1rTX_0G+QDkPp_CT- zAS1%|MBr+&Qu}7&KVK^2N~2k&gVH0=MEsrMxA}66cl~48Vf6yn2oxMMQ{%(+J7;zd z&&>IixJ@$IMTjW8nLkMaB=PYkwkyzS+SZ?iwiDLj8BJonJe56|S-PBaq5T$UYcOMCzOWH;0`)4^%G G#{UlkhxEAs diff --git a/src/content/templates/template books/Decodable Reader/placeHolder.png b/src/content/templates/template books/Decodable Reader/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Digital Comic Book/placeHolder.png b/src/content/templates/template books/Digital Comic Book/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 zcmeI0_fr#Eu*XA{s)zytf^?87O+chd?=1QL3euHY33 zAkw8=LsO&+^0@!R`{liz&wh8#&e@qWd*;mSoD>T)eP#wO1^@uSY-pfk1prWhuH2lC z>MAoJQqz;u zGTx-Wy&@$eGxcp|+S{zO%&hdx?2OEu^sN8L$jW(}otv4R_ckXlGbb-A7oL>|%g%#m z!{9ma{9IT;4!j^2UXYhx2+J?ZEBFssK@q&LIKQw2UR0W2R8mk}T3Gz9pro|0q^z*y zT~TRSaVetc9isRhqNJ?6w5*~8QC^C;(u#NGm1X5s?<%UxDyk5b)#X+HQBhTcsH!cm zs;Q{1sjR83szz4Spek$8l{Lt!T4Z%Cx(bP^L0&1Q8i}q!VQSHJHE3)t23L#5ATf1U zpfEUO9Tr_zkF2Xl)#1=s90pfkhiyP%8_+mBroIt_YpAPlz}7d`HQ;d#SK5TdH`e0` zSUdsO)Lh@#)X+%46Nrt3<_2O5p3vM#Y;J09ArM>f&25d%ZA~rhO)ag&mUcpGTXSm% zp{>28t&`Z^)!f$6+TPjL(b?YFbwx*4_Z6KzyqamAn(GYa43)%sVv9 zE!YcS;pQ6{Ds83<qy`AXGleW|06^QR-os0prY}{-rwdb!?ld%@s!9rXUy~ND<=EbEi z$$TZ3IfK0IDm*!T&&G+a*xwcyrkN!om*7K1%gsva3aX)>4JnUjP9}>Q)R_JPeTt{% zW&&ktC^9oe(`Whd0Xf8y=FFN@m2qwsY6EdxwF_K#X84deAMK3XJ^EBXI^fLD@*$PG z^l$tCz?%tEkn`@MI$}s=hcN*YhOV&iBmU(B6JJ^L+^Vt1 z1km?7s#!a+Cfj3}Plm~bkV7kRwzgvsM-R~M7Kvfw*1K_%42c4*I5!!7MCpuLZ0d76 zzi2iOIW&UOBory4%s0s}G>pl3xk1D4(D3j&W0Be~vuCzZR&2I_I=!s`vE^L!!dxq> z-($P252nP8QF}EjwNavu!5NQp9Z8TxWD)l-Oi*u#s2ZcC{op!8HJx7u*-28L=0(^? z>atB^o?D$6OLe(oh~sn9z0KJA(P# zSYG`|9PEwk1*<7fJ0sdZ$8FV3G;$yzLk=Q@G6~niZ5zQTjt5JOz?P>SvBq7RAf;uw z!2UL81bUYecSKFXj!7d#&mjl-a-a;%lg>s;Lg}96u1@mTg1o$VlpZB;vzh&&5$y|iz1OPMv2pwKW#s-v^tUe}hl9z8v0Or}+sn?l)6Q$&e zjP@LFT|1|ZCo}tTg5wGsA6YKBHNp!xH0vmPrIQuTD3n2KVM~rnBw<@p{MWu32It?h zg%Ww<@5{YU7iDJ{140SZ5^+FFH)t(mVLwuxgDIs%0h~@tU&?S4#Qo4d{8_gVA3E}% zIUC^zi<0uf_By`aEY?l~OH5@k%-6Nq9;>|0k)1O2iJ(a#EYf0i?WM!)-j7y`1AwP+d~ zwM>tlaSVYJ2g)*nT8C^$<-A~CviJ~mce+W*`w5xO*>ROYv9a37jq z?s{ADJSWJb|#iKTBv&bQ@zRRXf0DB0Hz_d7eQn|Pbq3d9@?{h6=U7(+lIYI z-*UxDP^)6WX3!QL6;iloz%Vo%^sQS?Fl*x0P&Kfn1LrAt$poI+00S#^F~TOKGc|an~ZdAg8@P9F->wmIMk^9 zY(AnTd-w5AQBo4JbK($aHVOoZ>|GaT!Wfx=UZ~(MsvlTFADzf3Xt%U)7BB;0oz!Hb z9|F16U@Fii)v%*!I~yG5uB7pMFiqMyL9&vJ3*0Ete`H$<^S_P@4i+fqoV6l={(fX; z^oiu&g7_OD&vQm8T2W7bM}iRI@*iTsO4)wH>f@_9an)C&=)}f%5wyT>w;<@Z_yB8d z(L~_~w&)X_rGD;EIIa`hKa~fE$hVID>9R@u%KU96pjK4h&eZ)aEa?a_u3IFXhQJ>0R;W?#n z->9Fg&^Ce--4|X9xjSwJT}*{3LZb0&TO~V}x%)H)cl{ttKP@T;Qsub7iXzx2A`Rr` z(A|x5xn}YjRXR$)Q;wfUEY}V_84hj%N9J+Wi*H+hWf?v`{ic%@V}2OZW&SHPRou!& zbafJFJsj&Oy|`hU9)^NIGsmXyWD!Y$motvZnfW+X7YWhkp;^oEa zz54PIuWn;Bm;Gl9J?NrXxSSzpo$I13{HpTEL>pG3KA&h=rJ$k6r#xGgs^+p5=XE*O zq7-1SM0u1m>=IP*xsYvsu8LtAX2*5^bR=@P`}DBqaC$HE!=^?VB@yu?G}1${1HsSY=trc2B=oZff;S(tg(Ey-CtErZr)FquBM z%aFHKWP$3A>Yg|0h&kQixi&ufDLBA{WbUe4y<6#`UGUIT`fPz+ZpQtI2`F4^IFNzr z-cqu5#(MXWa-ulugN_Nw+0-fJCg#bw+~viy_Oq|X-zGWK8jVp#b(cJDNYl@MI)H2h zj^-|z$xgEgoJ9af&2h`=Jx0F=L9H@%DWFTsx^j{I&4s}e3Q2yM;BpzUmPbF;m?2%! zrjPr}G@DA-v@C#sv=V^wCw>&nG^bPpLZJH*Btk;r&b5JXbE$C&!^vRU}9eME3xyBN2%uA)| zlUN@X;8LDEDPp0+CnF4-fH;d2BGp&TvnrN}fcDgCz#U?Shqz4!Qw7wS#!UrDdZP1^ ziK1L#=&xTj1>_17?{vq-+-h>TZo|!1_Wp^(mPTOAafjk;1w-^;oZDNF;kD`w(9Y0` zv-t-iW=pb=HZKk`Az|aYYM&NpV zHieBzDCYzIy#Uz;8e-&De2emt((*$(*nuvzPLuR4b=l7X9Hip%XXaBXu*(#`)&qVP zw~&c+J=R-2FfD(V6h5=8N0)bS`=#2_L(=vICYo?cF~T7E!exrGudv$r)94}ub9|<4 zG-K`RsM)vW%2E-JviTDnM)PO(&dD7*M#-ZlG0CUi^SjF1*Th%$s!QC5M{acufQ#3jNjQZZ7Hw~j4d2{OujX1} z8Z$VrSgE3ZLit^gBcimPUzz??*Q%O zS@PNNteiaPy))oT_*||Hbm9V_O8utf8dpJq?XSXG+G~mq#O;h5F9NaD4H6um?>N;u zc)tD$4@E8#?j^C)xBdlwq;=zDhKE`(qZ@=B;@)g+jinW|eU0J3hoF~jgp;B@4lk5{ zIj#Tg!5vty!pV0<-ufTJnADBcOKnSDs&`bSb~Sj!>w{E+79O00X|xmxo+yJQJN5%X z-)&*d*Z9=Ir}r1^Wzf9zlAM-pB{YxudW1=rDr{SWGp-)|oGA3-o;Q0?F7c^OD5Z<7 zB=qqkX`c@Z`fDE?V^3xnev_0qCq%{!db@2FX0Z-goI-?(DYgqTZS)OpUHzto*8|{t z24WwB92Q!OazrH|7`fwC=BUgNTu>_`gsFde%pYo!Z4QK1ex;7fAp0_Pr#Axw& zM}+@itrHGb+ha*btrf8ueqv3QZN10!Y5#T9LXGuM5c`s7^n1>K*?-}g?>Q{1&x~p@I9c3@~D_u@zMv#RFbLG&3_&Da&rj+c1De#n>z*=RXdxJKYDi zjU^X%U$&*Uu_E8m=QFr8Z3r@K--{!EXry!vq|Ek`qy%+qC6>NdX-2V{UE6Z;`{yaO zQnus9hSP_k)E1CTQnQ?u)X~k{ExGbD$9xEORY90qxrj^ys`O=JFS}zS-F%>|NG-lt zA7Mw8UTFqHO+(T(jUR&!=M)*znRR*`hyG#Pp*Zl%*U=3ZQ;PZ{gZv(r*Z|xMM>@R+ zMp$~vjCYckVnq%K-siR%E4G-^Q zNQNm6dMjJd>ZA#{131+?tttXWos|1D%6K!N#H7_1Zw4>~ZH?G-Jc$(by^+r(alzXw zDlQyf6%kv_E&SZU=I8j!Jne1YpkdsT+PQG~RYKQ>nXtuBYE{GtY9r~RD(qJyt{6<0 zz-9>QxcB0kq7vboybG_0JDuU-t@UNd4ocUPEbB=nlRx!3SvK zcADS%b^fPlP9oJ$!1%cHh>R!tt6~NplCs{Fu@G_;YR3YM8{(29`MU_ttM4NC`7Z9o z)OxLdcWETfmSE$)C>`|{y}y3TBLMXL{sWH6JweuTNL%d~1P^4p(Xc*seGQ&m%W^Na z8m;6yo}5J+JjS?2*4knXtsXMUvq01J17x#(0@N^@_a0t_~lMJnCbGyF>tt_pBHQAB-x< zb2NEjazyCJWKx_mpvWa-e)nSr%uo7aje8NzV-*!QLz^vdi!KlIde2T`JK|x{wV;k5 zkk|F@45I(Xd{UtS$;;nWgtb9)c8^p~YKP_tTV>pR_q4vd`ol^{1VHrg&Kfwy1tZo@ zWf3RlZh7|?K*BO^-xJXXsnZ~V7dSCe2h%(GjqUu1zG+W%%OG<(Y=wZ$^>q%+#|oWz z>&bz9h9C*(2BtWtcVbAB+OysaJY{#I&3vB!IGci90BenP2H1gwpwooUDOt#Q*J^bt zk0Hq3ioLr41-O8zDPU6a=BmZQaNu8e+J-L`>fW~IdC2w$)8PfXXZ-!h7Cn__vb#7S zflIeu^Km0pbE6(xB2pRkP8`VkzYoDy9pagzcdUs_WVm<%(%NRnR z=m`s)^7KRRLKBgCzy0g7JWSRV*%o>ERHxuca?Mtj`bs@!YS+gI%7sjMc&b*x0GlXYg!P&u^F&J1`eDEj^Cl_1rTX_0G+QDkPp_CT- zAS1%|MBr+&Qu}7&KVK^2N~2k&gVH0=MEsrMxA}66cl~48Vf6yn2oxMMQ{%(+J7;zd z&&>IixJ@$IMTjW8nLkMaB=PYkwkyzS+SZ?iwiDLj8BJonJe56|S-PBaq5T$UYcOMCzOWH;0`)4^%G G#{UlkhxEAs diff --git a/src/content/templates/template books/Games/placeHolder.png b/src/content/templates/template books/Games/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Leveled Reader/placeHolder.png b/src/content/templates/template books/Leveled Reader/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Paper Comic Book/placeHolder.png b/src/content/templates/template books/Paper Comic Book/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Picture Dictionary/placeHolder.png b/src/content/templates/template books/Picture Dictionary/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Playground/placeHolder.png b/src/content/templates/template books/Playground/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Sign Language/placeHolder.png b/src/content/templates/template books/Sign Language/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Template Starter/placeHolder.png b/src/content/templates/template books/Template Starter/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 zcmeI0_fr#Eu*XA{s)zytf^?87O+chd?=1QL3euHY33 zAkw8=LsO&+^0@!R`{liz&wh8#&e@qWd*;mSoD>T)eP#wO1^@uSY-pfk1prWhuH2lC z>MAoJQqz;u zGTx-Wy&@$eGxcp|+S{zO%&hdx?2OEu^sN8L$jW(}otv4R_ckXlGbb-A7oL>|%g%#m z!{9ma{9IT;4!j^2UXYhx2+J?ZEBFssK@q&LIKQw2UR0W2R8mk}T3Gz9pro|0q^z*y zT~TRSaVetc9isRhqNJ?6w5*~8QC^C;(u#NGm1X5s?<%UxDyk5b)#X+HQBhTcsH!cm zs;Q{1sjR83szz4Spek$8l{Lt!T4Z%Cx(bP^L0&1Q8i}q!VQSHJHE3)t23L#5ATf1U zpfEUO9Tr_zkF2Xl)#1=s90pfkhiyP%8_+mBroIt_YpAPlz}7d`HQ;d#SK5TdH`e0` zSUdsO)Lh@#)X+%46Nrt3<_2O5p3vM#Y;J09ArM>f&25d%ZA~rhO)ag&mUcpGTXSm% zp{>28t&`Z^)!f$6+TPjL(b?YFbwx*4_Z6KzyqamAn(GYa43)%sVv9 zE!YcS;pQ6{Ds83<qy`AXGleW|06^QR-os0prY}{-rwdb!?ld%@s!9rXUy~ND<=EbEi z$$TZ3IfK0IDm*!T&&G+a*xwcyrkN!om*7K1%gsva3aX)>4JnUjP9}>Q)R_JPeTt{% zW&&ktC^9oe(`Whd0Xf8y=FFN@m2qwsY6EdxwF_K#X84deAMK3XJ^EBXI^fLD@*$PG z^l$tCz?%tEkn`@MI$}s=hcN*YhOV&iBmU(B6JJ^L+^Vt1 z1km?7s#!a+Cfj3}Plm~bkV7kRwzgvsM-R~M7Kvfw*1K_%42c4*I5!!7MCpuLZ0d76 zzi2iOIW&UOBory4%s0s}G>pl3xk1D4(D3j&W0Be~vuCzZR&2I_I=!s`vE^L!!dxq> z-($P252nP8QF}EjwNavu!5NQp9Z8TxWD)l-Oi*u#s2ZcC{op!8HJx7u*-28L=0(^? z>atB^o?D$6OLe(oh~sn9z0KJA(P# zSYG`|9PEwk1*<7fJ0sdZ$8FV3G;$yzLk=Q@G6~niZ5zQTjt5JOz?P>SvBq7RAf;uw z!2UL81bUYecSKFXj!7d#&mjl-a-a;%lg>s;Lg}96u1@mTg1o$VlpZB;vzh&&5$y|iz1OPMv2pwKW#s-v^tUe}hl9z8v0Or}+sn?l)6Q$&e zjP@LFT|1|ZCo}tTg5wGsA6YKBHNp!xH0vmPrIQuTD3n2KVM~rnBw<@p{MWu32It?h zg%Ww<@5{YU7iDJ{140SZ5^+FFH)t(mVLwuxgDIs%0h~@tU&?S4#Qo4d{8_gVA3E}% zIUC^zi<0uf_By`aEY?l~OH5@k%-6Nq9;>|0k)1O2iJ(a#EYf0i?WM!)-j7y`1AwP+d~ zwM>tlaSVYJ2g)*nT8C^$<-A~CviJ~mce+W*`w5xO*>ROYv9a37jq z?s{ADJSWJb|#iKTBv&bQ@zRRXf0DB0Hz_d7eQn|Pbq3d9@?{h6=U7(+lIYI z-*UxDP^)6WX3!QL6;iloz%Vo%^sQS?Fl*x0P&Kfn1LrAt$poI+00S#^F~TOKGc|an~ZdAg8@P9F->wmIMk^9 zY(AnTd-w5AQBo4JbK($aHVOoZ>|GaT!Wfx=UZ~(MsvlTFADzf3Xt%U)7BB;0oz!Hb z9|F16U@Fii)v%*!I~yG5uB7pMFiqMyL9&vJ3*0Ete`H$<^S_P@4i+fqoV6l={(fX; z^oiu&g7_OD&vQm8T2W7bM}iRI@*iTsO4)wH>f@_9an)C&=)}f%5wyT>w;<@Z_yB8d z(L~_~w&)X_rGD;EIIa`hKa~fE$hVID>9R@u%KU96pjK4h&eZ)aEa?a_u3IFXhQJ>0R;W?#n z->9Fg&^Ce--4|X9xjSwJT}*{3LZb0&TO~V}x%)H)cl{ttKP@T;Qsub7iXzx2A`Rr` z(A|x5xn}YjRXR$)Q;wfUEY}V_84hj%N9J+Wi*H+hWf?v`{ic%@V}2OZW&SHPRou!& zbafJFJsj&Oy|`hU9)^NIGsmXyWD!Y$motvZnfW+X7YWhkp;^oEa zz54PIuWn;Bm;Gl9J?NrXxSSzpo$I13{HpTEL>pG3KA&h=rJ$k6r#xGgs^+p5=XE*O zq7-1SM0u1m>=IP*xsYvsu8LtAX2*5^bR=@P`}DBqaC$HE!=^?VB@yu?G}1${1HsSY=trc2B=oZff;S(tg(Ey-CtErZr)FquBM z%aFHKWP$3A>Yg|0h&kQixi&ufDLBA{WbUe4y<6#`UGUIT`fPz+ZpQtI2`F4^IFNzr z-cqu5#(MXWa-ulugN_Nw+0-fJCg#bw+~viy_Oq|X-zGWK8jVp#b(cJDNYl@MI)H2h zj^-|z$xgEgoJ9af&2h`=Jx0F=L9H@%DWFTsx^j{I&4s}e3Q2yM;BpzUmPbF;m?2%! zrjPr}G@DA-v@C#sv=V^wCw>&nG^bPpLZJH*Btk;r&b5JXbE$C&!^vRU}9eME3xyBN2%uA)| zlUN@X;8LDEDPp0+CnF4-fH;d2BGp&TvnrN}fcDgCz#U?Shqz4!Qw7wS#!UrDdZP1^ ziK1L#=&xTj1>_17?{vq-+-h>TZo|!1_Wp^(mPTOAafjk;1w-^;oZDNF;kD`w(9Y0` zv-t-iW=pb=HZKk`Az|aYYM&NpV zHieBzDCYzIy#Uz;8e-&De2emt((*$(*nuvzPLuR4b=l7X9Hip%XXaBXu*(#`)&qVP zw~&c+J=R-2FfD(V6h5=8N0)bS`=#2_L(=vICYo?cF~T7E!exrGudv$r)94}ub9|<4 zG-K`RsM)vW%2E-JviTDnM)PO(&dD7*M#-ZlG0CUi^SjF1*Th%$s!QC5M{acufQ#3jNjQZZ7Hw~j4d2{OujX1} z8Z$VrSgE3ZLit^gBcimPUzz??*Q%O zS@PNNteiaPy))oT_*||Hbm9V_O8utf8dpJq?XSXG+G~mq#O;h5F9NaD4H6um?>N;u zc)tD$4@E8#?j^C)xBdlwq;=zDhKE`(qZ@=B;@)g+jinW|eU0J3hoF~jgp;B@4lk5{ zIj#Tg!5vty!pV0<-ufTJnADBcOKnSDs&`bSb~Sj!>w{E+79O00X|xmxo+yJQJN5%X z-)&*d*Z9=Ir}r1^Wzf9zlAM-pB{YxudW1=rDr{SWGp-)|oGA3-o;Q0?F7c^OD5Z<7 zB=qqkX`c@Z`fDE?V^3xnev_0qCq%{!db@2FX0Z-goI-?(DYgqTZS)OpUHzto*8|{t z24WwB92Q!OazrH|7`fwC=BUgNTu>_`gsFde%pYo!Z4QK1ex;7fAp0_Pr#Axw& zM}+@itrHGb+ha*btrf8ueqv3QZN10!Y5#T9LXGuM5c`s7^n1>K*?-}g?>Q{1&x~p@I9c3@~D_u@zMv#RFbLG&3_&Da&rj+c1De#n>z*=RXdxJKYDi zjU^X%U$&*Uu_E8m=QFr8Z3r@K--{!EXry!vq|Ek`qy%+qC6>NdX-2V{UE6Z;`{yaO zQnus9hSP_k)E1CTQnQ?u)X~k{ExGbD$9xEORY90qxrj^ys`O=JFS}zS-F%>|NG-lt zA7Mw8UTFqHO+(T(jUR&!=M)*znRR*`hyG#Pp*Zl%*U=3ZQ;PZ{gZv(r*Z|xMM>@R+ zMp$~vjCYckVnq%K-siR%E4G-^Q zNQNm6dMjJd>ZA#{131+?tttXWos|1D%6K!N#H7_1Zw4>~ZH?G-Jc$(by^+r(alzXw zDlQyf6%kv_E&SZU=I8j!Jne1YpkdsT+PQG~RYKQ>nXtuBYE{GtY9r~RD(qJyt{6<0 zz-9>QxcB0kq7vboybG_0JDuU-t@UNd4ocUPEbB=nlRx!3SvK zcADS%b^fPlP9oJ$!1%cHh>R!tt6~NplCs{Fu@G_;YR3YM8{(29`MU_ttM4NC`7Z9o z)OxLdcWETfmSE$)C>`|{y}y3TBLMXL{sWH6JweuTNL%d~1P^4p(Xc*seGQ&m%W^Na z8m;6yo}5J+JjS?2*4knXtsXMUvq01J17x#(0@N^@_a0t_~lMJnCbGyF>tt_pBHQAB-x< zb2NEjazyCJWKx_mpvWa-e)nSr%uo7aje8NzV-*!QLz^vdi!KlIde2T`JK|x{wV;k5 zkk|F@45I(Xd{UtS$;;nWgtb9)c8^p~YKP_tTV>pR_q4vd`ol^{1VHrg&Kfwy1tZo@ zWf3RlZh7|?K*BO^-xJXXsnZ~V7dSCe2h%(GjqUu1zG+W%%OG<(Y=wZ$^>q%+#|oWz z>&bz9h9C*(2BtWtcVbAB+OysaJY{#I&3vB!IGci90BenP2H1gwpwooUDOt#Q*J^bt zk0Hq3ioLr41-O8zDPU6a=BmZQaNu8e+J-L`>fW~IdC2w$)8PfXXZ-!h7Cn__vb#7S zflIeu^Km0pbE6(xB2pRkP8`VkzYoDy9pagzcdUs_WVm<%(%NRnR z=m`s)^7KRRLKBgCzy0g7JWSRV*%o>ERHxuca?Mtj`bs@!YS+gI%7sjMc&b*x0GlXYg!P&u^F&J1`eDEj^Cl_1rTX_0G+QDkPp_CT- zAS1%|MBr+&Qu}7&KVK^2N~2k&gVH0=MEsrMxA}66cl~48Vf6yn2oxMMQ{%(+J7;zd z&&>IixJ@$IMTjW8nLkMaB=PYkwkyzS+SZ?iwiDLj8BJonJe56|S-PBaq5T$UYcOMCzOWH;0`)4^%G G#{UlkhxEAs diff --git a/src/content/templates/template books/UnusedTemplates/Template Maker/placeHolder.png b/src/content/templates/template books/UnusedTemplates/Template Maker/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/Wall Calendar/Wall Calendar.pug b/src/content/templates/template books/Wall Calendar/Wall Calendar.pug index 93b5b647cdc0..df5d35d68156 100644 --- a/src/content/templates/template books/Wall Calendar/Wall Calendar.pug +++ b/src/content/templates/template books/Wall Calendar/Wall Calendar.pug @@ -18,7 +18,7 @@ mixin field-classOnChild(internalClass) mixin image-largePage - requireZeroArguments('image', arguments); .bloom-canvas(style="opacity: 1; overflow: hidden;") - img(src="placeHolder.png", width=attributes.initialImageWidth, alt='Could not load the picture') + img(src="placeHolder.png", width=attributes.initialImageWidth) block html diff --git a/src/content/templates/template books/Wall Calendar/placeHolder.png b/src/content/templates/template books/Wall Calendar/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 zcmeI0_fr#Eu*XA{s)zytf^?87O+chd?=1QL3euHY33 zAkw8=LsO&+^0@!R`{liz&wh8#&e@qWd*;mSoD>T)eP#wO1^@uSY-pfk1prWhuH2lC z>MAoJQqz;u zGTx-Wy&@$eGxcp|+S{zO%&hdx?2OEu^sN8L$jW(}otv4R_ckXlGbb-A7oL>|%g%#m z!{9ma{9IT;4!j^2UXYhx2+J?ZEBFssK@q&LIKQw2UR0W2R8mk}T3Gz9pro|0q^z*y zT~TRSaVetc9isRhqNJ?6w5*~8QC^C;(u#NGm1X5s?<%UxDyk5b)#X+HQBhTcsH!cm zs;Q{1sjR83szz4Spek$8l{Lt!T4Z%Cx(bP^L0&1Q8i}q!VQSHJHE3)t23L#5ATf1U zpfEUO9Tr_zkF2Xl)#1=s90pfkhiyP%8_+mBroIt_YpAPlz}7d`HQ;d#SK5TdH`e0` zSUdsO)Lh@#)X+%46Nrt3<_2O5p3vM#Y;J09ArM>f&25d%ZA~rhO)ag&mUcpGTXSm% zp{>28t&`Z^)!f$6+TPjL(b?YFbwx*4_Z6KzyqamAn(GYa43)%sVv9 zE!YcS;pQ6{Ds83<qy`AXGleW|06^QR-os0prY}{-rwdb!?ld%@s!9rXUy~ND<=EbEi z$$TZ3IfK0IDm*!T&&G+a*xwcyrkN!om*7K1%gsva3aX)>4JnUjP9}>Q)R_JPeTt{% zW&&ktC^9oe(`Whd0Xf8y=FFN@m2qwsY6EdxwF_K#X84deAMK3XJ^EBXI^fLD@*$PG z^l$tCz?%tEkn`@MI$}s=hcN*YhOV&iBmU(B6JJ^L+^Vt1 z1km?7s#!a+Cfj3}Plm~bkV7kRwzgvsM-R~M7Kvfw*1K_%42c4*I5!!7MCpuLZ0d76 zzi2iOIW&UOBory4%s0s}G>pl3xk1D4(D3j&W0Be~vuCzZR&2I_I=!s`vE^L!!dxq> z-($P252nP8QF}EjwNavu!5NQp9Z8TxWD)l-Oi*u#s2ZcC{op!8HJx7u*-28L=0(^? z>atB^o?D$6OLe(oh~sn9z0KJA(P# zSYG`|9PEwk1*<7fJ0sdZ$8FV3G;$yzLk=Q@G6~niZ5zQTjt5JOz?P>SvBq7RAf;uw z!2UL81bUYecSKFXj!7d#&mjl-a-a;%lg>s;Lg}96u1@mTg1o$VlpZB;vzh&&5$y|iz1OPMv2pwKW#s-v^tUe}hl9z8v0Or}+sn?l)6Q$&e zjP@LFT|1|ZCo}tTg5wGsA6YKBHNp!xH0vmPrIQuTD3n2KVM~rnBw<@p{MWu32It?h zg%Ww<@5{YU7iDJ{140SZ5^+FFH)t(mVLwuxgDIs%0h~@tU&?S4#Qo4d{8_gVA3E}% zIUC^zi<0uf_By`aEY?l~OH5@k%-6Nq9;>|0k)1O2iJ(a#EYf0i?WM!)-j7y`1AwP+d~ zwM>tlaSVYJ2g)*nT8C^$<-A~CviJ~mce+W*`w5xO*>ROYv9a37jq z?s{ADJSWJb|#iKTBv&bQ@zRRXf0DB0Hz_d7eQn|Pbq3d9@?{h6=U7(+lIYI z-*UxDP^)6WX3!QL6;iloz%Vo%^sQS?Fl*x0P&Kfn1LrAt$poI+00S#^F~TOKGc|an~ZdAg8@P9F->wmIMk^9 zY(AnTd-w5AQBo4JbK($aHVOoZ>|GaT!Wfx=UZ~(MsvlTFADzf3Xt%U)7BB;0oz!Hb z9|F16U@Fii)v%*!I~yG5uB7pMFiqMyL9&vJ3*0Ete`H$<^S_P@4i+fqoV6l={(fX; z^oiu&g7_OD&vQm8T2W7bM}iRI@*iTsO4)wH>f@_9an)C&=)}f%5wyT>w;<@Z_yB8d z(L~_~w&)X_rGD;EIIa`hKa~fE$hVID>9R@u%KU96pjK4h&eZ)aEa?a_u3IFXhQJ>0R;W?#n z->9Fg&^Ce--4|X9xjSwJT}*{3LZb0&TO~V}x%)H)cl{ttKP@T;Qsub7iXzx2A`Rr` z(A|x5xn}YjRXR$)Q;wfUEY}V_84hj%N9J+Wi*H+hWf?v`{ic%@V}2OZW&SHPRou!& zbafJFJsj&Oy|`hU9)^NIGsmXyWD!Y$motvZnfW+X7YWhkp;^oEa zz54PIuWn;Bm;Gl9J?NrXxSSzpo$I13{HpTEL>pG3KA&h=rJ$k6r#xGgs^+p5=XE*O zq7-1SM0u1m>=IP*xsYvsu8LtAX2*5^bR=@P`}DBqaC$HE!=^?VB@yu?G}1${1HsSY=trc2B=oZff;S(tg(Ey-CtErZr)FquBM z%aFHKWP$3A>Yg|0h&kQixi&ufDLBA{WbUe4y<6#`UGUIT`fPz+ZpQtI2`F4^IFNzr z-cqu5#(MXWa-ulugN_Nw+0-fJCg#bw+~viy_Oq|X-zGWK8jVp#b(cJDNYl@MI)H2h zj^-|z$xgEgoJ9af&2h`=Jx0F=L9H@%DWFTsx^j{I&4s}e3Q2yM;BpzUmPbF;m?2%! zrjPr}G@DA-v@C#sv=V^wCw>&nG^bPpLZJH*Btk;r&b5JXbE$C&!^vRU}9eME3xyBN2%uA)| zlUN@X;8LDEDPp0+CnF4-fH;d2BGp&TvnrN}fcDgCz#U?Shqz4!Qw7wS#!UrDdZP1^ ziK1L#=&xTj1>_17?{vq-+-h>TZo|!1_Wp^(mPTOAafjk;1w-^;oZDNF;kD`w(9Y0` zv-t-iW=pb=HZKk`Az|aYYM&NpV zHieBzDCYzIy#Uz;8e-&De2emt((*$(*nuvzPLuR4b=l7X9Hip%XXaBXu*(#`)&qVP zw~&c+J=R-2FfD(V6h5=8N0)bS`=#2_L(=vICYo?cF~T7E!exrGudv$r)94}ub9|<4 zG-K`RsM)vW%2E-JviTDnM)PO(&dD7*M#-ZlG0CUi^SjF1*Th%$s!QC5M{acufQ#3jNjQZZ7Hw~j4d2{OujX1} z8Z$VrSgE3ZLit^gBcimPUzz??*Q%O zS@PNNteiaPy))oT_*||Hbm9V_O8utf8dpJq?XSXG+G~mq#O;h5F9NaD4H6um?>N;u zc)tD$4@E8#?j^C)xBdlwq;=zDhKE`(qZ@=B;@)g+jinW|eU0J3hoF~jgp;B@4lk5{ zIj#Tg!5vty!pV0<-ufTJnADBcOKnSDs&`bSb~Sj!>w{E+79O00X|xmxo+yJQJN5%X z-)&*d*Z9=Ir}r1^Wzf9zlAM-pB{YxudW1=rDr{SWGp-)|oGA3-o;Q0?F7c^OD5Z<7 zB=qqkX`c@Z`fDE?V^3xnev_0qCq%{!db@2FX0Z-goI-?(DYgqTZS)OpUHzto*8|{t z24WwB92Q!OazrH|7`fwC=BUgNTu>_`gsFde%pYo!Z4QK1ex;7fAp0_Pr#Axw& zM}+@itrHGb+ha*btrf8ueqv3QZN10!Y5#T9LXGuM5c`s7^n1>K*?-}g?>Q{1&x~p@I9c3@~D_u@zMv#RFbLG&3_&Da&rj+c1De#n>z*=RXdxJKYDi zjU^X%U$&*Uu_E8m=QFr8Z3r@K--{!EXry!vq|Ek`qy%+qC6>NdX-2V{UE6Z;`{yaO zQnus9hSP_k)E1CTQnQ?u)X~k{ExGbD$9xEORY90qxrj^ys`O=JFS}zS-F%>|NG-lt zA7Mw8UTFqHO+(T(jUR&!=M)*znRR*`hyG#Pp*Zl%*U=3ZQ;PZ{gZv(r*Z|xMM>@R+ zMp$~vjCYckVnq%K-siR%E4G-^Q zNQNm6dMjJd>ZA#{131+?tttXWos|1D%6K!N#H7_1Zw4>~ZH?G-Jc$(by^+r(alzXw zDlQyf6%kv_E&SZU=I8j!Jne1YpkdsT+PQG~RYKQ>nXtuBYE{GtY9r~RD(qJyt{6<0 zz-9>QxcB0kq7vboybG_0JDuU-t@UNd4ocUPEbB=nlRx!3SvK zcADS%b^fPlP9oJ$!1%cHh>R!tt6~NplCs{Fu@G_;YR3YM8{(29`MU_ttM4NC`7Z9o z)OxLdcWETfmSE$)C>`|{y}y3TBLMXL{sWH6JweuTNL%d~1P^4p(Xc*seGQ&m%W^Na z8m;6yo}5J+JjS?2*4knXtsXMUvq01J17x#(0@N^@_a0t_~lMJnCbGyF>tt_pBHQAB-x< zb2NEjazyCJWKx_mpvWa-e)nSr%uo7aje8NzV-*!QLz^vdi!KlIde2T`JK|x{wV;k5 zkk|F@45I(Xd{UtS$;;nWgtb9)c8^p~YKP_tTV>pR_q4vd`ol^{1VHrg&Kfwy1tZo@ zWf3RlZh7|?K*BO^-xJXXsnZ~V7dSCe2h%(GjqUu1zG+W%%OG<(Y=wZ$^>q%+#|oWz z>&bz9h9C*(2BtWtcVbAB+OysaJY{#I&3vB!IGci90BenP2H1gwpwooUDOt#Q*J^bt zk0Hq3ioLr41-O8zDPU6a=BmZQaNu8e+J-L`>fW~IdC2w$)8PfXXZ-!h7Cn__vb#7S zflIeu^Km0pbE6(xB2pRkP8`VkzYoDy9pagzcdUs_WVm<%(%NRnR z=m`s)^7KRRLKBgCzy0g7JWSRV*%o>ERHxuca?Mtj`bs@!YS+gI%7sjMc&b*x0GlXYg!P&u^F&J1`eDEj^Cl_1rTX_0G+QDkPp_CT- zAS1%|MBr+&Qu}7&KVK^2N~2k&gVH0=MEsrMxA}66cl~48Vf6yn2oxMMQ{%(+J7;zd z&&>IixJ@$IMTjW8nLkMaB=PYkwkyzS+SZ?iwiDLj8BJonJe56|S-PBaq5T$UYcOMCzOWH;0`)4^%G G#{UlkhxEAs diff --git a/src/content/templates/template books/eBook/placeHolder.png b/src/content/templates/template books/eBook/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs diff --git a/src/content/templates/template books/placeHolder.png b/src/content/templates/template books/placeHolder.png deleted file mode 100644 index f4ebcbf84861fb01e82b234e6f7bce1ea2761d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6734 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 G#{UlkhxEAs