Is there a way to create a parsable Dom without running the code? I'll explain future;
I receive a whole bunch of CK-editor created code as a HTML, but want to parse elements from this to create a specified view. For example I'll like to grasp the first paragraph as an Intro and the first Image as a primary image. I'n addition I want to retrieve all images to create a gallery.
For doing this I've created a simple, but effective function:
export const getFromContent = (html, qsa) => {
const elm = document.createElement("DIV");
elm.innerHTML = html;
let r = elm.querySelectorAll(qsa);
return r;
}
This work almost perfect- the only issue is that is adds everything to the DOM (do I use the term correctly?), which means that all resources gets loaded even if it does not show on the Page.
In my example I would like to load all images through //res.cloudinary.com/ com compress images before shown, but since all images already is loaded, this wont be necessary.
Is there a way to get to keep the good "version" of this with just basic JS?
PS: I know that I could rewrite all "src" to "presrc" with a REGEX, but I would really like to do this without changing the code, and thereby create space for errors.
Best regards Richard
This work almost perfect- the only issue is that is adds everything to the DOM...
It creates DOM elements (that's why you're doing it!😀), but it doesn't add them to the window's document. That code will not load images referenced by src or stylesheets referenced by href, and will not run code in script elements. Those img/link/script elements will be in the div you've created, but that div is not in the document. In the case of the images and stylesheets, they'd be loaded if you put the div in the document (the script elements would not be executed even then), but not before.
That said, you might want to look at using DOMParser instead.
export const getFromContent = (html, qsa) => {
const dom = DOMParser.parseFromString(html, "text/html");
let r = dom.querySelectorAll(qsa);
return r;
}
Note that, again, any images or stylesheets or similar referenced by the elements you return from that (the ones matched by the selector and returned in the NodeList from querySelectorAll) will be loaded if those elements are added to a window's document.
Note: When accepting user input and rendering it as HTML, it's often important to sanitize that input before using it, to remove unwanted content. For instance, I mentioned that script elements wouldn't be evaluated, and that's true, but if the content had <img src="javascript:doSomethingNefarious()"> in it, and you appended that image to a document (directly or indirectly), that doSomethingNefarious() code would be executed. Similarly, <div onclick="doSomethingNefarious()">x</div>.
If you search for "HTML sanitizer" you'll find a lot of different libraries out there that say they'll do it for you. The problem is significant enough, though, that a means of doing it is in the process of being standardized as the Sanitization API. Early days yet, but it's a very promising development. With the API in its current (very draft) form, you could do:
export const getFromContent = (html, qsa) => {
const div = document.createElement("div");
div.setHTML(html); // <== `setHTML` is a new method that sanitizes.
// Here I'm using the default sanitizer, but you
// could create one with your own custom settings
// and pass it as the second argument
let r = div.querySelectorAll(qsa);
return r;
}
But the API is still in flux.