Marked: Image urls with get variables

Created on 27 Aug 2019  路  9Comments  路  Source: markedjs/marked

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?

L2 - annoying

Most helpful comment

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>

All 9 comments

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 = '![](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.

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 = '![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 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}"/>`;
};
Was this page helpful?
0 / 5 - 0 ratings

Related issues

priyesh-diukar picture priyesh-diukar  路  3Comments

vsemozhetbyt picture vsemozhetbyt  路  4Comments

raguay picture raguay  路  4Comments

eGavr picture eGavr  路  4Comments

james4388 picture james4388  路  3Comments