Relative urls for assets

Hi everyone!

I got a quick question.

I’m using relative paths (e.g. <img src='stories/6d63e887/dc32788d3.jpg' /> for my assets as an editor source format. It’s basically an S3 path.

A Node View resolves that url later on like so:

class ImageView {
  constructor (node) {
    this.dom = document.createElement('img')
    this.dom.src = `https://letsken.imgix.net/${node.attrs.src}?fit=max&w=1536&fm=jpg`
  }
}

Everything works just fine. But since I’m using HTML for storing content I need to do a bit of DOM action with the source content, to load the editor state:

DOMParser.fromSchema(schema).parse('<p>hello</p><img src='stories/6d63e887/dc32788d3.jpg' />')
const el = document.createElement('div')
el.innerHTML = data.content

Now, I am ending up with annoying browser load errors. Can this be avoided somehow? Like is there another way of getting the editorState from an HTML string that doesn’t require to use a real DOM?

@marijn is this a sound approach generally to use sanitized HTML for exchange and storage of articles? The other alternative would be storing ProseMirror’s JSON representation, but that seems less accessible to me. And eats more bytes.

Thank you for any help!

To avoid the loading errors I could use a data-src instead of src attribute but that feels like an arbitrary decision. My document model is so simple, that using the standard HTML tags seemed reasonable. However it is really a source format, and not meant to be displayed directly.

what is data in this ? If it is a node from DOMParser.fromSchema(schema).parse(...), is it possible to set innerHTML to a Node Fragment (data.content) ?

data.content is an HTML string as received from the server API: e.g.

'<h1>Hello World</h1><p>foo</p><img src="path/to/image.jpg">'
const element = document.createElement('div');
    element.innerHTML = content.trim();
    const doc = DOMParser.fromSchema(schema).parse(element, parseOptions);

// go ahead with creating my editor with doc 

doing something like the above has worked from me without any errors.

if the images are having loading errors when the temporary dom element is created prosemirror should also have errors with those images. for which i feel using a data-s3-src is a good alternative, as you are anyway not using the src in the true sense ( a src attribute should be used for image source only).

Your code example is a bit confusing (DOMParser.parse doesn’t take a string, and it’s unclear how the lines below that relate to the first line), but you may be interested in document.implementation.createHTMLDocument, which allows you to create a detached document where the browser will simply parse stuff, without trying to actually resolve anything or trigger any events.

Thank you for the pointer! That is a great solution.

And yes, sorry, my example was wrong. Here’s the complete code that’s working now.

  const data = {
    title: 'Hello World',
    content: '<p>hello</p><img src="stories/6d63e887/dc32788d3.jpg">'
  }
  const doc = document.implementation.createHTMLDocument()
  const html = [
    `<h1>${data.title}</h1>`,
    data.content
  ].join('')
  doc.body.innerHTML = html
  DOMParser.fromSchema(schema).parse(doc.body)

@kepta thanks for your suggestion too. The serialisation format in my case is meant as a pure source format, so it doesn’t even need to be “valid HTML” as it’s never shows directly in the browser. I could have chosen XML to make this separation more clear, but it’s just convenient to use HTML here too, as I don’t need to add a conversion layer. So I think i will stick with source src and a display src property. :slight_smile: