From 596193c7120010efe81b9fe055cf79babe5a327b Mon Sep 17 00:00:00 2001 From: ianhi Date: Thu, 26 Mar 2020 23:21:23 -0400 Subject: [PATCH 01/13] attachfiles with spaces in name encode the URIs of attachments to be valid. --- packages/cells/src/widget.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index facce4ae29d1..3eebbd447e55 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1169,7 +1169,8 @@ export abstract class AttachmentsCell extends Cell { * Modify the cell source to include a reference to the attachment. */ protected abstract updateCellSourceWithAttachment( - attachmentName: string + attachmentName: string, + URI: string ): void; /** @@ -1325,8 +1326,9 @@ export abstract class AttachmentsCell extends Cell { const mimeType = matches[1]; const encodedData = matches[3]; const bundle: nbformat.IMimeBundle = { [mimeType]: encodedData }; - this.model.attachments.set(blob.name, bundle); - this.updateCellSourceWithAttachment(blob.name); + const URI = encodeURI(blob.name) + this.model.attachments.set(URI, bundle); + this.updateCellSourceWithAttachment(blob.name, URI); }; reader.onerror = evt => { console.error(`Failed to attach ${blob.name}` + evt); @@ -1445,8 +1447,8 @@ export class MarkdownCell extends AttachmentsCell { /** * Modify the cell source to include a reference to the attachment. */ - protected updateCellSourceWithAttachment(attachmentName: string) { - const textToBeAppended = `![${attachmentName}](attachment:${attachmentName})`; + protected updateCellSourceWithAttachment(attachmentName: string, URI: string) { + const textToBeAppended = `![${attachmentName}](attachment:${URI})`; this.model.value.insert(this.model.value.text.length, textToBeAppended); } From e5bef35cb8f4e740e07b6b9f97eb93d8491ffcdb Mon Sep 17 00:00:00 2001 From: ianhi Date: Thu, 26 Mar 2020 23:23:55 -0400 Subject: [PATCH 02/13] add URI encoding to lumino events --- packages/cells/src/widget.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index 3eebbd447e55..3294f41e5f3f 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1273,9 +1273,9 @@ export abstract class AttachmentsCell extends Cell { CONTENTS_MIME_RICH ) as DirListing.IContentsThunk; if (model.type === 'file') { - this.updateCellSourceWithAttachment(model.name); + this.updateCellSourceWithAttachment(model.name, encodeURI(model.name)); void withContent().then(fullModel => { - this.model.attachments.set(fullModel.name, { + this.model.attachments.set(encodeURI(fullModel.name), { [fullModel.mimetype]: fullModel.content }); }); @@ -1283,10 +1283,10 @@ export abstract class AttachmentsCell extends Cell { } else { // Pure mimetype, no useful name to infer const name = UUID.uuid4(); - this.model.attachments.set(name, { + this.model.attachments.set(encodeURI(name), { [mimeType]: event.mimeData.getData(mimeType) }); - this.updateCellSourceWithAttachment(name); + this.updateCellSourceWithAttachment(name, encodeURI(name)); } } } From 7931e0c801c440e22b34f6553040a376cdf315b0 Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Fri, 27 Mar 2020 10:52:29 -0400 Subject: [PATCH 03/13] Make URI argument optional Co-Authored-By: Jason Grout --- packages/cells/src/widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index 3294f41e5f3f..3076c4685d04 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1170,7 +1170,7 @@ export abstract class AttachmentsCell extends Cell { */ protected abstract updateCellSourceWithAttachment( attachmentName: string, - URI: string + URI?: string ): void; /** From 81ef6f1fc8387e72dff06acf719f43a550982093 Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Fri, 27 Mar 2020 10:52:42 -0400 Subject: [PATCH 04/13] Make URI argument optional Co-Authored-By: Jason Grout --- packages/cells/src/widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index 3076c4685d04..3f10fe50deea 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1447,7 +1447,7 @@ export class MarkdownCell extends AttachmentsCell { /** * Modify the cell source to include a reference to the attachment. */ - protected updateCellSourceWithAttachment(attachmentName: string, URI: string) { + protected updateCellSourceWithAttachment(attachmentName: string, URI?: string) { const textToBeAppended = `![${attachmentName}](attachment:${URI})`; this.model.value.insert(this.model.value.text.length, textToBeAppended); } From 37485fdf6d77fdfa9988d50912d13ab02b912217 Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Fri, 27 Mar 2020 10:54:58 -0400 Subject: [PATCH 05/13] Use URI if exists, otherwise attachement name Co-Authored-By: Jason Grout --- packages/cells/src/widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index 3f10fe50deea..c013e1ffec0f 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1448,7 +1448,7 @@ export class MarkdownCell extends AttachmentsCell { * Modify the cell source to include a reference to the attachment. */ protected updateCellSourceWithAttachment(attachmentName: string, URI?: string) { - const textToBeAppended = `![${attachmentName}](attachment:${URI})`; + const textToBeAppended = `![${attachmentName}](attachment:${URI ?? attachmentName})`; this.model.value.insert(this.model.value.text.length, textToBeAppended); } From f30bac374bcb0ab4a8eab6a6e303cb546b46c5e2 Mon Sep 17 00:00:00 2001 From: ianhi Date: Fri, 27 Mar 2020 14:46:01 -0400 Subject: [PATCH 06/13] Don't overwrite existing attachments Checks if the cell already has an attachment using that name. If yes then start adding numbers such that image.png will become image_1.png etc. The regex is used for this splitting in order to only split on the final . (i.e. allow filenames such as image.image.png) and to include the . for reconstructing the filename. --- packages/cells/src/widget.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index c013e1ffec0f..c255d2281bcb 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1326,7 +1326,17 @@ export abstract class AttachmentsCell extends Cell { const mimeType = matches[1]; const encodedData = matches[3]; const bundle: nbformat.IMimeBundle = { [mimeType]: encodedData }; - const URI = encodeURI(blob.name) + + // Find an unused URI + let URI = encodeURI(blob.name) + let URI_array = URI.split(/(\.)(?=[^\.]+$)/); + URI_array.splice(1, 0, ''); + let i = 1; + while (this.model.attachments.has(URI)){ + URI_array[1] = `_${i}`; + URI = URI_array.join(''); + i = i+1; + } this.model.attachments.set(URI, bundle); this.updateCellSourceWithAttachment(blob.name, URI); }; From c315c2fe195fdbcf28383321209cf7e065ef5007 Mon Sep 17 00:00:00 2001 From: ianhi Date: Sat, 28 Mar 2020 23:28:50 -0400 Subject: [PATCH 07/13] Use UUID for URI Use uuid4 to generate the URI in all instances, if the file has an extension preserve that information. Also add a check if the file type is an image which is currently the only valid markdown embedding. --- packages/cells/src/widget.ts | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index c255d2281bcb..f24ed21e73d1 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1273,20 +1273,21 @@ export abstract class AttachmentsCell extends Cell { CONTENTS_MIME_RICH ) as DirListing.IContentsThunk; if (model.type === 'file') { - this.updateCellSourceWithAttachment(model.name, encodeURI(model.name)); + const URI = this._generateURI(model.name); + this.updateCellSourceWithAttachment(model.name, URI); void withContent().then(fullModel => { - this.model.attachments.set(encodeURI(fullModel.name), { + this.model.attachments.set(URI, { [fullModel.mimetype]: fullModel.content }); }); } } else { // Pure mimetype, no useful name to infer - const name = UUID.uuid4(); - this.model.attachments.set(encodeURI(name), { + const URI = UUID.uuid4(); + this.model.attachments.set(URI, { [mimeType]: event.mimeData.getData(mimeType) }); - this.updateCellSourceWithAttachment(name, encodeURI(name)); + this.updateCellSourceWithAttachment(URI, URI); } } } @@ -1326,19 +1327,12 @@ export abstract class AttachmentsCell extends Cell { const mimeType = matches[1]; const encodedData = matches[3]; const bundle: nbformat.IMimeBundle = { [mimeType]: encodedData }; + const URI = this._generateURI(blob.name); - // Find an unused URI - let URI = encodeURI(blob.name) - let URI_array = URI.split(/(\.)(?=[^\.]+$)/); - URI_array.splice(1, 0, ''); - let i = 1; - while (this.model.attachments.has(URI)){ - URI_array[1] = `_${i}`; - URI = URI_array.join(''); - i = i+1; + if (mimeType.includes('image')){ + this.model.attachments.set(URI, bundle); + this.updateCellSourceWithAttachment(name, URI); } - this.model.attachments.set(URI, bundle); - this.updateCellSourceWithAttachment(blob.name, URI); }; reader.onerror = evt => { console.error(`Failed to attach ${blob.name}` + evt); @@ -1346,6 +1340,15 @@ export abstract class AttachmentsCell extends Cell { reader.readAsDataURL(blob); } + /** + * Generates a unique URI for a file + * while preserving the file extension. + */ + private _generateURI(name: string): string { + const lastIndex = name.lastIndexOf('.'); + return lastIndex !== -1 ? UUID.uuid4().concat(name.substring(lastIndex)) : UUID.uuid4(); + } + /** * The model used by the widget. */ From 2123d2e62b51291366ff60bb85b7d9ab259649ff Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Sat, 28 Mar 2020 23:33:35 -0400 Subject: [PATCH 08/13] encode name as valid URI when no URI provided Co-Authored-By: Jason Grout --- packages/cells/src/widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index f24ed21e73d1..4b48d97632f5 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1461,7 +1461,7 @@ export class MarkdownCell extends AttachmentsCell { * Modify the cell source to include a reference to the attachment. */ protected updateCellSourceWithAttachment(attachmentName: string, URI?: string) { - const textToBeAppended = `![${attachmentName}](attachment:${URI ?? attachmentName})`; + const textToBeAppended = `![${attachmentName}](attachment:${URI ?? encodeURI(attachmentName)})`; this.model.value.insert(this.model.value.text.length, textToBeAppended); } From 359615499828851e0d31f38a04fd02a3a1fb17e2 Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Sun, 29 Mar 2020 01:15:51 -0400 Subject: [PATCH 09/13] Stricter mimetype test Co-Authored-By: Jason Grout --- packages/cells/src/widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index 4b48d97632f5..0bea4cae044c 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1329,7 +1329,7 @@ export abstract class AttachmentsCell extends Cell { const bundle: nbformat.IMimeBundle = { [mimeType]: encodedData }; const URI = this._generateURI(blob.name); - if (mimeType.includes('image')){ + if (mimeType.startsWith('image/')){ this.model.attachments.set(URI, bundle); this.updateCellSourceWithAttachment(name, URI); } From 2622eb630207c882b2ac9a7a88e85cc6690351eb Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Sun, 29 Mar 2020 01:16:21 -0400 Subject: [PATCH 10/13] give generateURI a default argument Co-Authored-By: Jason Grout --- packages/cells/src/widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index 0bea4cae044c..932722fa5327 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1344,7 +1344,7 @@ export abstract class AttachmentsCell extends Cell { * Generates a unique URI for a file * while preserving the file extension. */ - private _generateURI(name: string): string { + private _generateURI(name = ''): string { const lastIndex = name.lastIndexOf('.'); return lastIndex !== -1 ? UUID.uuid4().concat(name.substring(lastIndex)) : UUID.uuid4(); } From 1ac18038f37fa95e5659ddc57384304295d15239 Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Sun, 29 Mar 2020 01:16:40 -0400 Subject: [PATCH 11/13] Always use generateURI Co-Authored-By: Jason Grout --- packages/cells/src/widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index 932722fa5327..ebe2ad22a9d4 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1283,7 +1283,7 @@ export abstract class AttachmentsCell extends Cell { } } else { // Pure mimetype, no useful name to infer - const URI = UUID.uuid4(); + const URI = this._generateURI(); this.model.attachments.set(URI, { [mimeType]: event.mimeData.getData(mimeType) }); From ac5df285199468e077effd865d2eec2864d91448 Mon Sep 17 00:00:00 2001 From: Jason Grout Date: Mon, 30 Mar 2020 13:46:17 -0700 Subject: [PATCH 12/13] Do not encode the attachment name by default This reverts a suggested change that breaks backwards compatibility --- packages/cells/src/widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index ebe2ad22a9d4..4b1af4978fb6 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1461,7 +1461,7 @@ export class MarkdownCell extends AttachmentsCell { * Modify the cell source to include a reference to the attachment. */ protected updateCellSourceWithAttachment(attachmentName: string, URI?: string) { - const textToBeAppended = `![${attachmentName}](attachment:${URI ?? encodeURI(attachmentName)})`; + const textToBeAppended = `![${attachmentName}](attachment:${URI ?? attachmentName})`; this.model.value.insert(this.model.value.text.length, textToBeAppended); } From 7fc5005fe8ec19318dc44ab5cf82179861d47ca7 Mon Sep 17 00:00:00 2001 From: Saul Shanabrook Date: Mon, 30 Mar 2020 17:27:25 -0400 Subject: [PATCH 13/13] Update packages/cells/src/widget.ts --- packages/cells/src/widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cells/src/widget.ts b/packages/cells/src/widget.ts index 4b1af4978fb6..293fa502ec0c 100644 --- a/packages/cells/src/widget.ts +++ b/packages/cells/src/widget.ts @@ -1331,7 +1331,7 @@ export abstract class AttachmentsCell extends Cell { if (mimeType.startsWith('image/')){ this.model.attachments.set(URI, bundle); - this.updateCellSourceWithAttachment(name, URI); + this.updateCellSourceWithAttachment(blob.name, URI); } }; reader.onerror = evt => {