You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	Clipper: Better handling of images when multiple images have the same source but with different dimensions
This commit is contained in:
		| @@ -61,14 +61,19 @@ | |||||||
| 		const output = {}; | 		const output = {}; | ||||||
| 		for (let i = 0; i < images.length; i++) { | 		for (let i = 0; i < images.length; i++) { | ||||||
| 			const img = images[i]; | 			const img = images[i]; | ||||||
|  | 			if (img.classList && img.classList.contains('joplin-clipper-hidden')) continue; | ||||||
|  |  | ||||||
| 			let src = imageSrc(img); | 			let src = imageSrc(img); | ||||||
| 			src = forceAbsoluteUrls ? absoluteUrl(src) : src; | 			src = forceAbsoluteUrls ? absoluteUrl(src) : src; | ||||||
| 			output[src] = { |  | ||||||
|  | 			if (!output[src]) output[src] = []; | ||||||
|  |  | ||||||
|  | 			output[src].push({ | ||||||
| 				width: img.width, | 				width: img.width, | ||||||
| 				height: img.height, | 				height: img.height, | ||||||
| 				naturalWidth: img.naturalWidth, | 				naturalWidth: img.naturalWidth, | ||||||
| 				naturalHeight: img.naturalHeight, | 				naturalHeight: img.naturalHeight, | ||||||
| 			}; | 			}); | ||||||
| 		} | 		} | ||||||
| 		return output; | 		return output; | ||||||
| 	} | 	} | ||||||
| @@ -98,17 +103,18 @@ | |||||||
| 	// Cleans up element by removing all its invisible children (which we don't want to render as Markdown) | 	// Cleans up element by removing all its invisible children (which we don't want to render as Markdown) | ||||||
| 	// And hard-code the image dimensions so that the information can be used by the clipper server to | 	// And hard-code the image dimensions so that the information can be used by the clipper server to | ||||||
| 	// display them at the right sizes in the notes. | 	// display them at the right sizes in the notes. | ||||||
| 	function cleanUpElement(element, imageSizes) { | 	function cleanUpElement(element, imageSizes, imageIndexes) { | ||||||
| 		const childNodes = element.childNodes; | 		const childNodes = element.childNodes; | ||||||
|  | 		const hiddenNodes = []; | ||||||
|  |  | ||||||
| 		for (let i = childNodes.length - 1; i >= 0; i--) { | 		for (let i = 0; i < childNodes.length; i++) { | ||||||
| 			const node = childNodes[i]; | 			const node = childNodes[i]; | ||||||
| 			const nodeName = node.nodeName.toLowerCase(); | 			const nodeName = node.nodeName.toLowerCase(); | ||||||
|  |  | ||||||
| 			const isHidden = node && node.classList && node.classList.contains('joplin-clipper-hidden'); | 			const isHidden = node && node.classList && node.classList.contains('joplin-clipper-hidden'); | ||||||
|  |  | ||||||
| 			if (isHidden) { | 			if (isHidden) { | ||||||
| 				element.removeChild(node); | 				hiddenNodes.push(node); | ||||||
| 			} else { | 			} else { | ||||||
|  |  | ||||||
| 				// If the data-joplin-clipper-value has been set earlier, create a new DIV element | 				// If the data-joplin-clipper-value has been set earlier, create a new DIV element | ||||||
| @@ -123,16 +129,23 @@ | |||||||
| 				if (nodeName === 'img') { | 				if (nodeName === 'img') { | ||||||
| 					const src = absoluteUrl(imageSrc(node)); | 					const src = absoluteUrl(imageSrc(node)); | ||||||
| 					node.setAttribute('src', src); | 					node.setAttribute('src', src); | ||||||
| 					const imageSize = imageSizes[src]; | 					if (!(src in imageIndexes)) imageIndexes[src] = 0; | ||||||
|  | 					const imageSize = imageSizes[src][imageIndexes[src]]; | ||||||
|  | 					imageIndexes[src]++; | ||||||
| 					if (imageSize) { | 					if (imageSize) { | ||||||
| 						node.width = imageSize.width; | 						node.width = imageSize.width; | ||||||
| 						node.height = imageSize.height; | 						node.height = imageSize.height; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				cleanUpElement(node, imageSizes); | 				cleanUpElement(node, imageSizes, imageIndexes); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		for (const hiddenNode of hiddenNodes) { | ||||||
|  | 			if (!hiddenNode.parentNode) continue; | ||||||
|  | 			hiddenNode.parentNode.remove(hiddenNode); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// When we clone the document before cleaning it, we lose some of the information that might have been set via CSS or | 	// When we clone the document before cleaning it, we lose some of the information that might have been set via CSS or | ||||||
| @@ -292,7 +305,8 @@ | |||||||
| 			// directly on the document, so we make a copy of it first. | 			// directly on the document, so we make a copy of it first. | ||||||
| 			const cleanDocument = document.body.cloneNode(true); | 			const cleanDocument = document.body.cloneNode(true); | ||||||
| 			const imageSizes = getImageSizes(document, true); | 			const imageSizes = getImageSizes(document, true); | ||||||
| 			cleanUpElement(cleanDocument, imageSizes); | 			const imageIndexes = {}; | ||||||
|  | 			cleanUpElement(cleanDocument, imageSizes, imageIndexes); | ||||||
|  |  | ||||||
| 			const stylesheets = command.preProcessFor === 'html' ? getStyleSheets(document) : null; | 			const stylesheets = command.preProcessFor === 'html' ? getStyleSheets(document) : null; | ||||||
| 			return clippedContentResponse(pageTitle(), cleanDocument.innerHTML, imageSizes, getAnchorNames(document), stylesheets); | 			return clippedContentResponse(pageTitle(), cleanDocument.innerHTML, imageSizes, getAnchorNames(document), stylesheets); | ||||||
| @@ -305,7 +319,8 @@ | |||||||
| 			const container = document.createElement('div'); | 			const container = document.createElement('div'); | ||||||
| 			container.appendChild(range.cloneContents()); | 			container.appendChild(range.cloneContents()); | ||||||
| 			const imageSizes = getImageSizes(document, true); | 			const imageSizes = getImageSizes(document, true); | ||||||
| 			cleanUpElement(container, imageSizes); | 			const imageIndexes = {}; | ||||||
|  | 			cleanUpElement(container, imageSizes, imageIndexes); | ||||||
| 			return clippedContentResponse(pageTitle(), container.innerHTML, getImageSizes(document), getAnchorNames(document)); | 			return clippedContentResponse(pageTitle(), container.innerHTML, getImageSizes(document), getAnchorNames(document)); | ||||||
|  |  | ||||||
| 		} else if (command.name === 'screenshot') { | 		} else if (command.name === 'screenshot') { | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ class HtmlToHtml { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// We need this extra style so that the images don't overflow | 		// We need this extra style so that the images don't overflow | ||||||
| 		const extraStyle = '<style>img {max-width: 100%;height: auto;}</style>' | 		const extraStyle = ''; //<style>img {max-width: 100%;height: auto;}</style>' | ||||||
|  |  | ||||||
| 		return { | 		return { | ||||||
| 			html: extraStyle + htmlUtils.headAndBodyHtml(dom.window.document), | 			html: extraStyle + htmlUtils.headAndBodyHtml(dom.window.document), | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ const md5 = require('md5'); | |||||||
| const { shim } = require('lib/shim'); | const { shim } = require('lib/shim'); | ||||||
| const HtmlToMd = require('lib/HtmlToMd'); | const HtmlToMd = require('lib/HtmlToMd'); | ||||||
| const urlUtils = require('lib/urlUtils.js'); | const urlUtils = require('lib/urlUtils.js'); | ||||||
|  | const ArrayUtils = require('lib/ArrayUtils.js'); | ||||||
| const { netUtils } = require('lib/net-utils'); | const { netUtils } = require('lib/net-utils'); | ||||||
| const { fileExtension, safeFileExtension, safeFilename, filename } = require('lib/path-utils'); | const { fileExtension, safeFileExtension, safeFilename, filename } = require('lib/path-utils'); | ||||||
| const ApiResponse = require('lib/services/rest/ApiResponse'); | const ApiResponse = require('lib/services/rest/ApiResponse'); | ||||||
| @@ -371,7 +372,7 @@ class Api { | |||||||
|  |  | ||||||
| 			let note = await this.requestNoteToNote_(requestNote); | 			let note = await this.requestNoteToNote_(requestNote); | ||||||
|  |  | ||||||
| 			const imageUrls = markupLanguageUtils.extractImageUrls(note.markup_language, note.body); | 			const imageUrls = ArrayUtils.unique(markupLanguageUtils.extractImageUrls(note.markup_language, note.body)); | ||||||
|  |  | ||||||
| 			this.logger().info('Request (' + requestId + '): Downloading images: ' + imageUrls.length); | 			this.logger().info('Request (' + requestId + '): Downloading images: ' + imageUrls.length); | ||||||
|  |  | ||||||
| @@ -618,6 +619,8 @@ class Api { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	replaceImageUrlsByResources_(markupLanguage, md, urls, imageSizes) { | 	replaceImageUrlsByResources_(markupLanguage, md, urls, imageSizes) { | ||||||
|  | 		const imageSizesIndexes = {}; | ||||||
|  |  | ||||||
| 		if (markupLanguage === Note.MARKUP_LANGUAGE_HTML) { | 		if (markupLanguage === Note.MARKUP_LANGUAGE_HTML) { | ||||||
| 			return htmlUtils.replaceImageUrls(md, imageUrl => { | 			return htmlUtils.replaceImageUrls(md, imageUrl => { | ||||||
| 				const urlInfo = urls[imageUrl]; | 				const urlInfo = urls[imageUrl]; | ||||||
| @@ -628,7 +631,9 @@ class Api { | |||||||
| 			let output = md.replace(/(!\[.*?\]\()([^\s\)]+)(.*?\))/g, (match, before, imageUrl, after) => { | 			let output = md.replace(/(!\[.*?\]\()([^\s\)]+)(.*?\))/g, (match, before, imageUrl, after) => { | ||||||
| 				const urlInfo = urls[imageUrl]; | 				const urlInfo = urls[imageUrl]; | ||||||
| 				if (!urlInfo || !urlInfo.resource) return before + imageUrl + after; | 				if (!urlInfo || !urlInfo.resource) return before + imageUrl + after; | ||||||
| 				const imageSize = imageSizes[urlInfo.originalUrl]; | 				if (!(urlInfo.originalUrl in imageSizesIndexes)) imageSizesIndexes[urlInfo.originalUrl] = 0; | ||||||
|  | 				const imageSize = imageSizes[urlInfo.originalUrl][imageSizesIndexes[urlInfo.originalUrl]]; | ||||||
|  | 				imageSizesIndexes[urlInfo.originalUrl]++; | ||||||
| 				const resourceUrl = Resource.internalUrl(urlInfo.resource); | 				const resourceUrl = Resource.internalUrl(urlInfo.resource); | ||||||
|  |  | ||||||
| 				if (imageSize && (imageSize.naturalWidth !== imageSize.width || imageSize.naturalHeight !== imageSize.height)) { | 				if (imageSize && (imageSize.naturalWidth !== imageSize.width || imageSize.naturalHeight !== imageSize.height)) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user