@@ -5,12 +5,14 @@ import {showTemporaryTooltip} from '../modules/tippy.js';
55import { GET , POST } from '../modules/fetch.js' ;
66import { showErrorToast } from '../modules/toast.js' ;
77import { createElementFromHTML , createElementFromAttrs } from '../utils/dom.js' ;
8+ import { isImageFile , isVideoFile } from '../utils.js' ;
89
910const { csrfToken, i18n} = window . config ;
1011
1112// dropzone has its owner event dispatcher (emitter)
1213export const DropzoneCustomEventReloadFiles = 'dropzone-custom-reload-files' ;
1314export const DropzoneCustomEventRemovedFile = 'dropzone-custom-removed-file' ;
15+ export const DropzoneCustomEventUploadDone = 'dropzone-custom-upload-done' ;
1416
1517async function createDropzone ( el , opts ) {
1618 const [ { Dropzone} ] = await Promise . all ( [
@@ -20,6 +22,26 @@ async function createDropzone(el, opts) {
2022 return new Dropzone ( el , opts ) ;
2123}
2224
25+ export function generateMarkdownLinkForAttachment ( file , { width, dppx} = { } ) {
26+ let fileMarkdown = `[${ file . name } ](/attachments/${ file . uuid } )` ;
27+ if ( isImageFile ( file ) ) {
28+ fileMarkdown = `!${ fileMarkdown } ` ;
29+ if ( width > 0 && dppx > 1 ) {
30+ // Scale down images from HiDPI monitors. This uses the <img> tag because it's the only
31+ // method to change image size in Markdown that is supported by all implementations.
32+ // Make the image link relative to the repo path, then the final URL is "/sub-path/owner/repo/attachments/{uuid}"
33+ fileMarkdown = `<img width="${ Math . round ( width / dppx ) } " alt="${ htmlEscape ( file . name ) } " src="attachments/${ htmlEscape ( file . uuid ) } ">` ;
34+ } else {
35+ // Markdown always renders the image with a relative path, so the final URL is "/sub-path/owner/repo/attachments/{uuid}"
36+ // TODO: it should also use relative path for consistency, because absolute is ambiguous for "/sub-path/attachments" or "/attachments"
37+ fileMarkdown = `` ;
38+ }
39+ } else if ( isVideoFile ( file ) ) {
40+ fileMarkdown = `<video src="attachments/${ htmlEscape ( file . uuid ) } " title="${ htmlEscape ( file . name ) } " controls></video>` ;
41+ }
42+ return fileMarkdown ;
43+ }
44+
2345function addCopyLink ( file ) {
2446 // Create a "Copy Link" element, to conveniently copy the image or file link as Markdown to the clipboard
2547 // The "<a>" element has a hardcoded cursor: pointer because the default is overridden by .dropzone
@@ -29,13 +51,7 @@ function addCopyLink(file) {
2951</div>` ) ;
3052 copyLinkEl . addEventListener ( 'click' , async ( e ) => {
3153 e . preventDefault ( ) ;
32- let fileMarkdown = `[${ file . name } ](/attachments/${ file . uuid } )` ;
33- if ( file . type ?. startsWith ( 'image/' ) ) {
34- fileMarkdown = `!${ fileMarkdown } ` ;
35- } else if ( file . type ?. startsWith ( 'video/' ) ) {
36- fileMarkdown = `<video src="/attachments/${ htmlEscape ( file . uuid ) } " title="${ htmlEscape ( file . name ) } " controls></video>` ;
37- }
38- const success = await clippie ( fileMarkdown ) ;
54+ const success = await clippie ( generateMarkdownLinkForAttachment ( file ) ) ;
3955 showTemporaryTooltip ( e . target , success ? i18n . copy_success : i18n . copy_error ) ;
4056 } ) ;
4157 file . previewTemplate . append ( copyLinkEl ) ;
@@ -78,6 +94,7 @@ export async function initDropzone(dropzoneEl) {
7894 const input = createElementFromAttrs ( 'input' , { name : 'files' , type : 'hidden' , id : `dropzone-file-${ resp . uuid } ` , value : resp . uuid } ) ;
7995 dropzoneEl . querySelector ( '.files' ) . append ( input ) ;
8096 addCopyLink ( file ) ;
97+ dzInst . emit ( DropzoneCustomEventUploadDone , { file} ) ;
8198 } ) ;
8299
83100 dzInst . on ( 'removedfile' , async ( file ) => {
@@ -114,7 +131,7 @@ export async function initDropzone(dropzoneEl) {
114131 dzInst . emit ( 'addedfile' , attachment ) ;
115132 dzInst . emit ( 'thumbnail' , attachment , imgSrc ) ;
116133 dzInst . emit ( 'complete' , attachment ) ;
117- addCopyLink ( attachment ) ;
134+ addCopyLink ( attachment ) ; // it is from server response, so no "type"
118135 fileUuidDict [ attachment . uuid ] = { submitted : true } ;
119136 const input = createElementFromAttrs ( 'input' , { name : 'files' , type : 'hidden' , id : `dropzone-file-${ attachment . uuid } ` , value : attachment . uuid } ) ;
120137 dropzoneEl . querySelector ( '.files' ) . append ( input ) ;
0 commit comments