marked icon indicating copy to clipboard operation
marked copied to clipboard

Image urls with get variables

Open jenstornell opened this issue 5 years ago • 9 comments

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?

jenstornell avatar Aug 27 '19 08:08 jenstornell

that url seems to work just fine in an image. demo

Could you share some markdown that isn't working?

UziTech avatar Aug 27 '19 13:08 UziTech

@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 = '![](domain.com/images/96449.jpg)';
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.

jenstornell avatar Aug 27 '19 13:08 jenstornell

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.

UziTech avatar Aug 27 '19 17:08 UziTech

Sorry. Playing with tags.

joshbruce avatar Sep 07 '19 08:09 joshbruce

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.

jenstornell avatar Sep 10 '19 07:09 jenstornell

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 = '![image](/url.png)';
const html = marked(md, { renderer });

console.log(html);
// <p><img src="/fields/markdown/get/image?path=/url.png" alt="image"></p>

UziTech avatar Sep 10 '19 13:09 UziTech

@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!

jenstornell avatar Sep 11 '19 08:09 jenstornell

@UziTech Can you add data-img attribute dynamically to img

Hideer avatar Sep 30 '19 09:09 Hideer

@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}"/>`;
};

UziTech avatar Sep 30 '19 13:09 UziTech

closing as stale. I don't think we will change the behavior of baseUrl

UziTech avatar Nov 21 '22 06:11 UziTech