diff --git a/src/muya/lib/assets/styles/index.css b/src/muya/lib/assets/styles/index.css index 95a47f773..115d9d359 100644 --- a/src/muya/lib/assets/styles/index.css +++ b/src/muya/lib/assets/styles/index.css @@ -755,33 +755,49 @@ span.ag-warn.ag-emoji-marked-text { vertical-align: middle; } +.ag-inline-image, +.ag-image-container { + font-size: 0; + line-height: 0; +} + .ag-inline-image { - display: flex; + display: inline-block; position: relative; background: var(--codeBlockBgColor); - border-radius: 3px; - overflow: hidden; - margin: 0 auto; - justify-content: space-around; + border-radius: 2px; } .ag-inline-image .ag-image-container { + display: inline-block; position: relative; - overflow: hidden; } .ag-inline-image.ag-image-success { background: transparent; } -.ag-inline-image a.ag-image-icon-turninto, -.ag-inline-image a.ag-image-icon-delete { +.ag-inline-image .ag-image-buttons { opacity: 0; display: none; + flex-direction: row; + justify-content: space-around; + align-items: center; + position: absolute; + border-radius: 6px; + top: 10px; + width: 75px; + height: 40px; + right: 10px; +} + +.ag-inline-image a.ag-image-icon-turninto, +.ag-inline-image a.ag-image-icon-delete { + display: flex; + justify-content: space-around; + align-items: center; width: 30px; height: 30px; - position: absolute; - top: 15px; background: rgba(50, 54, 58, .5); border-radius: 12px; cursor: pointer; @@ -798,14 +814,6 @@ span.ag-warn.ag-emoji-marked-text { background: rgba(50, 54, 58, .8); } -.ag-inline-image a.ag-image-icon-turninto { - right: 60px; -} - -.ag-inline-image a.ag-image-icon-delete { - right: 15px; -} - .ag-inline-image a.ag-image-icon-success, .ag-inline-image a.ag-image-icon-fail, .ag-inline-image a.ag-image-icon-close { @@ -883,13 +891,9 @@ span.ag-warn.ag-emoji-marked-text { display: block; } -.ag-inline-image.ag-image-success:hover a.ag-image-icon-turninto, -.ag-inline-image.ag-image-success:hover a.ag-image-icon-delete { +.ag-inline-image.ag-image-success:hover span.ag-image-buttons { opacity: 1; display: flex; - align-items: center; - justify-content: space-around; - z-index: 1; } .ag-inline-image.ag-empty-image:hover a.ag-image-icon-close, @@ -924,6 +928,13 @@ span.ag-warn.ag-emoji-marked-text { color: var(--iconColor); } +.ag-inline-image.ag-small-image .ag-image-buttons { + top: -40px; + left: 50%; + transform: translateX(-50%); + background: var(--floatBgColor); +} + .ag-image-marked-text ~ img { display: block; margin: 0 auto; diff --git a/src/muya/lib/config/index.js b/src/muya/lib/config/index.js index 69b608286..87108c19c 100644 --- a/src/muya/lib/config/index.js +++ b/src/muya/lib/config/index.js @@ -96,6 +96,7 @@ export const CLASS_OR_ID = genUpper2LowerKeyHash([ 'AG_HTML_PREVIEW', 'AG_HTML_TAG', 'AG_IMAGE_FAIL', + 'AG_IMAGE_BUTTONS', 'AG_IMAGE_LOADING', 'AG_EMPTY_IMAGE', 'AG_IMAGE_MARKED_TEXT', diff --git a/src/muya/lib/parser/render/renderInlines/image.js b/src/muya/lib/parser/render/renderInlines/image.js index 21eec47bc..ab1947bdc 100644 --- a/src/muya/lib/parser/render/renderInlines/image.js +++ b/src/muya/lib/parser/render/renderInlines/image.js @@ -32,11 +32,13 @@ export default function image (h, cursor, block, token, outerClass) { } let id let isSuccess + let width + let height let { src } = imageInfo const alt = token.alt + encodeURI(token.backlash.first) const { title } = token if (src) { - ({ id, isSuccess } = this.loadImageAsync(imageInfo, alt)) + ({ id, isSuccess, width, height } = this.loadImageAsync(imageInfo, alt)) } let wrapperSelector = id ? `span#${id}.${CLASS_OR_ID.AG_INLINE_IMAGE}` @@ -48,8 +50,14 @@ export default function image (h, cursor, block, token, outerClass) { renderIcon(h, 'ag-image-icon-close', DeleteIcon) ] const toolIcons = [ - renderIcon(h, 'ag-image-icon-turninto', ImageEditIcon), - renderIcon(h, 'ag-image-icon-delete', DeleteIcon) + h(`span.${CLASS_OR_ID.AG_IMAGE_BUTTONS}`, { + attrs: { + contenteditable: 'false' + } + }, [ + renderIcon(h, 'ag-image-icon-turninto', ImageEditIcon), + renderIcon(h, 'ag-image-icon-delete', DeleteIcon) + ]) ] const renderImageContainer = (...args) => { return h(`span.${CLASS_OR_ID.AG_IMAGE_CONTAINER}`, {}, args) @@ -82,6 +90,9 @@ export default function image (h, cursor, block, token, outerClass) { wrapperSelector += `.${CLASS_OR_ID.AG_IMAGE_LOADING}` } else if (isSuccess === true) { wrapperSelector += `.${CLASS_OR_ID.AG_IMAGE_SUCCESS}` + if (typeof width === 'number' && typeof height === 'number' && (width < 100 || height < 100)) { + wrapperSelector += '.ag-small-image' + } } else { wrapperSelector += `.${CLASS_OR_ID.AG_IMAGE_FAIL}` } diff --git a/src/muya/lib/parser/render/renderInlines/loadImageAsync.js b/src/muya/lib/parser/render/renderInlines/loadImageAsync.js index 0538f3e5e..9da894cbf 100644 --- a/src/muya/lib/parser/render/renderInlines/loadImageAsync.js +++ b/src/muya/lib/parser/render/renderInlines/loadImageAsync.js @@ -6,11 +6,13 @@ export default function loadImageAsync (imageInfo, alt, className, imageClass) { const { src, isUnknownType } = imageInfo let id let isSuccess + let w + let h if (!this.loadImageMap.has(src)) { id = getUniqueId() loadImage(src, isUnknownType) - .then(url => { + .then(({ url, width, height }) => { const imageText = document.querySelector(`#${id}`) const img = document.createElement('img') img.src = url @@ -29,6 +31,10 @@ export default function loadImageAsync (imageInfo, alt, className, imageClass) { imageContainer.appendChild(img) imageText.classList.remove('ag-image-loading') imageText.classList.add('ag-image-success') + // Add `ag-small-image` class name to inline image wrapper if the image is smaller than 100px. + if (width < 100 || height < 100) { + imageText.classList.add('ag-small-image') + } } else { insertAfter(img, imageText) operateClassName(imageText, 'add', className) @@ -39,7 +45,9 @@ export default function loadImageAsync (imageInfo, alt, className, imageClass) { } this.loadImageMap.set(src, { id, - isSuccess: true + isSuccess: true, + width, + height }) }) .catch(() => { @@ -64,7 +72,9 @@ export default function loadImageAsync (imageInfo, alt, className, imageClass) { const imageInfo = this.loadImageMap.get(src) id = imageInfo.id isSuccess = imageInfo.isSuccess + w = imageInfo.width + h = imageInfo.height } - return { id, isSuccess } + return { id, isSuccess, width: w, height: h } } diff --git a/src/muya/lib/utils/index.js b/src/muya/lib/utils/index.js index be716d80c..d1ffec698 100644 --- a/src/muya/lib/utils/index.js +++ b/src/muya/lib/utils/index.js @@ -142,7 +142,11 @@ export const loadImage = async (url, detectContentType = false) => { return new Promise((resolve, reject) => { const image = new Image() image.onload = () => { - resolve(url) + resolve({ + url, + width: image.width, + height: image.height + }) } image.onerror = err => { reject(err)