Skip to content

Commit

Permalink
mimeType for FileAttachment (#281)
Browse files Browse the repository at this point in the history
* mimeType for FileAttachment

* coerce mimeType to string, if present
  • Loading branch information
mbostock authored Apr 26, 2022
1 parent 21e5d9a commit ddce1e1
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 24 deletions.
19 changes: 1 addition & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -408,24 +408,7 @@ const document = await FileAttachment("index.html").html();

*Note: this function is not part of the Observable standard library (in notebooks), but is provided by this module as a means for defining custom file attachment implementations when working directly with the Observable runtime.*

Returns a [*FileAttachment*](#FileAttachment) function given the specified *resolve* function. The *resolve* function is an async function that takes a *name* and returns a URL at which the file of that name can be loaded. For example:

```js
const FileAttachment = FileAttachments((name) =>
`https://my.server/notebooks/demo/${name}`
);
```

Or, with a more complex example, calling an API to produce temporary URLs:

```js
const FileAttachment = FileAttachments(async (name) =>
if (cachedUrls.has(name)) return cachedUrls.get(name);
const url = await fetchSignedFileUrl(notebookId, name);
cachedUrls.set(name, url);
return url;
);
```
Returns a [*FileAttachment*](#FileAttachment) function given the specified *resolve* function. The *resolve* function is a function that takes a *name* and returns either an object {url, mimeType} representing the requested file if it exists, or null if the file does not exist. The url field (though not the object itself!) may be represented as a Promise if the URL is not yet known, such as for a file that is currently being uploaded. The mimeType must be a string, or undefined if the mime type is not known. For backwards compatibility, the *resolve* function may instead return just a URL, either a string or a promise.

### Generators

Expand Down
17 changes: 11 additions & 6 deletions src/fileAttachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ async function dsv(file, delimiter, {array = false, typed = false} = {}) {
}

export class AbstractFile {
constructor(name) {
constructor(name, mimeType) {
Object.defineProperty(this, "name", {value: name, enumerable: true});
if (mimeType !== undefined) Object.defineProperty(this, "mimeType", {value: mimeType + "", enumerable: true});
}
async blob() {
return (await remote_fetch(this)).blob();
Expand Down Expand Up @@ -79,8 +80,8 @@ export class AbstractFile {
}

class FileAttachment extends AbstractFile {
constructor(url, name) {
super(name);
constructor(url, name, mimeType) {
super(name, mimeType);
Object.defineProperty(this, "_url", {value: url});
}
async url() {
Expand All @@ -95,9 +96,13 @@ export function NoFileAttachments(name) {
export default function FileAttachments(resolve) {
return Object.assign(
name => {
const url = resolve(name += ""); // Returns a Promise, string, or null.
if (url == null) throw new Error(`File not found: ${name}`);
return new FileAttachment(url, name);
const result = resolve(name += "");
if (result == null) throw new Error(`File not found: ${name}`);
if (typeof result === "object" && "url" in result) {
const {url, mimeType} = result;
return new FileAttachment(url, name, mimeType);
}
return new FileAttachment(result, name);
},
{prototype: FileAttachment.prototype} // instanceof
);
Expand Down

0 comments on commit ddce1e1

Please sign in to comment.