download JSON disappears: Is this an issue of syntax (and how to 'escape' it all)?

I am trying to inject the content of a markdown cell into a JSON object. I can’t access the ‘download as JSON’ feature when I attempt this.

Am I correct to assume that this is because the contents of the markdown cell ‘break’ the JSON because of some characters that ought to be escaped? Is there a way I can achieve this sort of manual JSON object creation into which I import from a markdown cell without too much fuss?

Not quite. Your object contains a DOM element that cannot be serialized. If you want the cell content to be downloadable as JSON, you’ll have to reference your rendered markdown like this:

{
    // ...
     content: intro_within_md.outerHTML,
}

When you open a cell menu, Observable will query the cell’s download type from the worker. Inside the worker script is some proprietary code that attempts to determine the data type. For objects it will iterate over all properties (up to a limit) and check each property value. You can search for “downloadType” in your dev tools to find the relevant sources.

2 Likes

Note that you can also handle the conversion yourself by adding a toJSON() method to the DOM element:

{
  // ...
  content: Object.assign(intro_within_md, {
    toJSON() { return this.outerHTML }
  }),
}

To test the result without having to select “Download JSON”, create a new cell with:

JSON.stringify(intro_data_md)

or

JSON.parse(JSON.stringify(intro_data_md))
2 Likes

Thanks @mootari! As usual, you’re clear explanations help a lot.

Just for my deeper understanding: All observable cells using template literals are converted into DOM elements, and to use them correctly in a JSON object, I have to specify which of those DOM elements I wish to select and print.

You’ve pointed me to .outerHTML twice this week. I’ll clearly need to read up more on these elements and to better learn how to read cell output (not only when it’s printed back into a notebook).

Thanks again!

No, basic template literals will only return a string. But when you tag a template literal, then the tagged template literal will return whatever the tag function returns.

When you use one of the tag functions from Observable’s stdlib (html, md, svg, tex), then those tagged template literals will return the DOM element (and DOM tree) that has been created by the respective tag function.

Note that this behavior is unrelated to Observable or its runtime. You can create and use your own tag functions, like @stwind did for glsl, @bgchen for MathJax, or @shaunlebron for wasm.

2 Likes