@@ -5,12 +5,14 @@ import {showTemporaryTooltip} from '../modules/tippy.js';
5
5
import { GET , POST } from '../modules/fetch.js' ;
6
6
import { showErrorToast } from '../modules/toast.js' ;
7
7
import { createElementFromHTML , createElementFromAttrs } from '../utils/dom.js' ;
8
+ import { isImageFile , isVideoFile } from '../utils.js' ;
8
9
9
10
const { csrfToken, i18n} = window . config ;
10
11
11
12
// dropzone has its owner event dispatcher (emitter)
12
13
export const DropzoneCustomEventReloadFiles = 'dropzone-custom-reload-files' ;
13
14
export const DropzoneCustomEventRemovedFile = 'dropzone-custom-removed-file' ;
15
+ export const DropzoneCustomEventUploadDone = 'dropzone-custom-upload-done' ;
14
16
15
17
async function createDropzone ( el , opts ) {
16
18
const [ { Dropzone} ] = await Promise . all ( [
@@ -20,6 +22,26 @@ async function createDropzone(el, opts) {
20
22
return new Dropzone ( el , opts ) ;
21
23
}
22
24
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
+
23
45
function addCopyLink ( file ) {
24
46
// Create a "Copy Link" element, to conveniently copy the image or file link as Markdown to the clipboard
25
47
// The "<a>" element has a hardcoded cursor: pointer because the default is overridden by .dropzone
@@ -29,13 +51,7 @@ function addCopyLink(file) {
29
51
</div>` ) ;
30
52
copyLinkEl . addEventListener ( 'click' , async ( e ) => {
31
53
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 ) ) ;
39
55
showTemporaryTooltip ( e . target , success ? i18n . copy_success : i18n . copy_error ) ;
40
56
} ) ;
41
57
file . previewTemplate . append ( copyLinkEl ) ;
@@ -78,6 +94,7 @@ export async function initDropzone(dropzoneEl) {
78
94
const input = createElementFromAttrs ( 'input' , { name : 'files' , type : 'hidden' , id : `dropzone-file-${ resp . uuid } ` , value : resp . uuid } ) ;
79
95
dropzoneEl . querySelector ( '.files' ) . append ( input ) ;
80
96
addCopyLink ( file ) ;
97
+ dzInst . emit ( DropzoneCustomEventUploadDone , { file} ) ;
81
98
} ) ;
82
99
83
100
dzInst . on ( 'removedfile' , async ( file ) => {
@@ -114,7 +131,7 @@ export async function initDropzone(dropzoneEl) {
114
131
dzInst . emit ( 'addedfile' , attachment ) ;
115
132
dzInst . emit ( 'thumbnail' , attachment , imgSrc ) ;
116
133
dzInst . emit ( 'complete' , attachment ) ;
117
- addCopyLink ( attachment ) ;
134
+ addCopyLink ( attachment ) ; // it is from server response, so no "type"
118
135
fileUuidDict [ attachment . uuid ] = { submitted : true } ;
119
136
const input = createElementFromAttrs ( 'input' , { name : 'files' , type : 'hidden' , id : `dropzone-file-${ attachment . uuid } ` , value : attachment . uuid } ) ;
120
137
dropzoneEl . querySelector ( '.files' ) . append ( input ) ;
0 commit comments