marked
marked copied to clipboard
Image urls with get variables
I'm building a tool where I preview the content with Marked. I have the images in URLs like this:
http://server/api/read/?path=domain.com/images/167424.jpg
Marked will crush this URL because it contains a GET variable. To fix it, I needed to comment out a part of the resolveUrl.
if (!baseUrls[' ' + base]) {
// we can ignore everything in base after the last slash of its path component,
// but we might need to add _that_
// https://tools.ietf.org/html/rfc3986#section-3
if (/^[^:]+:\/*[^/]*$/.test(base)) {
baseUrls[' ' + base] = base + '/';
} else {
baseUrls[' ' + base] = rtrim(base, '/', true);
}
}
base = baseUrls[' ' + base];
Remove the above, and it works as expected.
To make it work in the long run with URLs like this, maybe make this function less agressive?
that url seems to work just fine in an image. demo
Could you share some markdown that isn't working?
@UziTech Yes, in your example it works.
I have been able to reproduce the issue. In order to do so I needed to involve baseUrl
as well. The simplest to me was to use jsfiddle, so that's what I did.
https://jsfiddle.net/xLktp30m/2/
js
In the console log you will see an image tag without the get variable.
let markdown = '';
let root = 'https://example.com/api?test=';
let results = marked(markdown, { baseUrl: root });
console.log(results);
document.querySelector('textarea').value = results;
html (optional)
<textarea></textarea>
In conclusion it's the baseUrl
that is too agressive in my case.
Yes the baseUrl
must end with a slash. I'm not sure why that was a requirement originally but we are going to be deprecating that option in the future so I don't think there are any plans to change that requirement.
Sorry. Playing with tags.
As I use Vue with Vue CLI 3 I don't want to edit the code of the library (I use it as dependency). Instead, I've come up with a hacky workaround. Maybe someone will find it useful.
const markdown = '# Markdown with images';
const baseUrl = "/fields/markdown/get/image/";
let marked = Marked(markdown, {
baseUrl: baseUrl
});
marked = marked.replace(
' src="' + baseUrl,
' src="/fields/markdown/get/image?path='
);
console.log(marked);
Basically I search and replace the image baseUrl. You need to set a baseUrl that ends with a slash that you can later replace.
- Does not match external image urls with http, https etc.
- The chance of a conflict is quite low if the
baseUrl
is more specific.
Improvements are welcome.
You could also override the renderer to provide the base url
const marked = require('marked');
const renderer = new marked.Renderer();
const baseUrl = '/fields/markdown/get/image?path=';
const originalRendererLink = renderer.link.bind(renderer);
const originalRendererImage = renderer.image.bind(renderer);
renderer.link = (href, title, text) => {
href = baseUrl + href;
return originalRendererLink(href, title, text);
};
renderer.image = (href, title, text) => {
href = baseUrl + href;
return originalRendererImage(href, title, text);
};
const md = '';
const html = marked(md, { renderer });
console.log(html);
// <p><img src="/fields/markdown/get/image?path=/url.png" alt="image"></p>
@UziTech It's a bit more code, but it should be much more reliable in all cases and not a hack. It works as expected!
Thanks!
@UziTech Can you add data-img attribute dynamically to img
@Hideer You can return whatever you want in the renderer.image
function
e.g.
renderer.image = (href, title, text) => {
return `<img src="${href}" data-img="${href}" alt="${text}" title="${title}"/>`;
};
closing as stale. I don't think we will change the behavior of baseUrl