Nuxt + Markdown-it: Cannot convert object to primitive value
Hello,
I am trying to use markdown-it in my application. It works fine on Nuxt and other serverless platforms like Vercel, but it does not work on Cloudflare Workers for some reason.
Here is my code:
Here is a minimum repro example I have made: https://github.com/Geometrically/repro-nuxt-markdown. Let me know what I can do to fix this.
The full error and calltrace is:
29 Replies
Okay, I see what is happening, but not sure why yet
It's in this URL format function:
For some reason, the
url
being passed into this is... odd. .hostname
on it is a Proxy, so then when it tries to serialise that, it blows up.If I manually hotpatch it and comment out the hostname accessors, it works, but obviously without a hostname; https://up.jross.me/8nr73wc6
I'm digging in to try and see where this Proxy is coming from, and why it's in place
vue in general adds proxies to a lot of things
the weird thing I'm confused about is why workers causes it
i was thinking maybe a missing polyfill from nodejs or something? but when I looked at the code point I couldn't find anything related
if you do url.hostname.value does it work?
Workers isn't node, so a lot of weird stuff like this that works in other envs, doesn't here
Nope,
.value
doesn't work either
Do you know where this format
function is coming from? The bundled output from nuxt isn't the easiest to work through 😅it's all from markdown-it
this might not have anything to do with nuxt, it might be a workers only issue
https://github.com/markdown-it/markdown-it
Okay it's coming from https://github.com/markdown-it/mdurl/blob/master/format.js
Which is used in
normalizeLink
, which is used in linkify-it
Yeah there's something deeply weird happening here with how this is being Proxy'd and then stringified. This is probably about as deep as I'm gonna dive into this rabbit hole though, so your best bet is probably going to be to try and reproduce this manually with a Proxy
or something, to determine if it's a Workers issue and if/how it can be fixed.
My gut would say this is just some weird Proxy usage that Workers is handling more to-spec, whereas other envs are more loose with handling.
I've found it! @geometrically parsed.hostname = punycode.toASCII(parsed.hostname);
Wow
punycode
is a nodejs thing and not available in Workers
so this is getting mangledcan I make my own polyfill?
You might be able to polyfill
punycode
, but that's probably gonna be a massive polyfillwell, luckily I don't think anything we use has punycode support
so it could just return the passed string
right?
or I could pull in https://www.npmjs.com/package/punycode
npm
punycode
A robust Punycode converter that fully complies to RFC 3492 and RFC 5891, and works on nearly all JavaScript platforms.. Latest version: 2.3.0, last published: 5 months ago. Start using punycode in your project by running
npm i punycode
. There are 1711 other projects in the npm registry using punycode.yeah if you stub out this, it should work: https://github.com/markdown-it/markdown-it/blob/2b6cac25823af011ff3bc7628bc9b06e483c5a08/lib/index.js#L59
or you could do that, yeah
is there a good guide on making polyfills? a little confused on how to do it for this case specifically
like since it's not my project
Not really - I'd probably
patch-package
it or something honestly
lemme take a quick lookshould I still make an issue in workers? I guess the module is deprecated but it would be a pretty easy fix
oh, I found a way to do it
You could open an issue in https://github.com/cloudflare/workerd to support
punycode
, but I'd be surprised if there's much want to support deprecated modules
Your best bet is probably opening an issue in https://github.com/markdown-it/markdown-it and recommending they use a maintained solution like https://www.npmjs.com/package/tr46 or https://www.npmjs.com/package/punycode over the node.js version. so this can work in non-node environments easily
And then doing something hacky in the meantime to polyfill / stub itthanks a lot for your help james 😄
i'll open an issue in the markdown it repo and figure out a hack around it
I've got a very hacky solution working
lemme PR this to your repro and you can use whatever bits you think are most helpful
that would be great, yeah I tried pnpm patch but realized I would have to edit the dist/minfied version
Something like this: https://github.com/Geometrically/repro-nuxt-markdown/pull/1
Yeah I essentially had to fork
markdown-it
, edit it there, rebuild to grab dist
, and then patch it in
My actual code change was this
wow git sucks with minified files lol
yeah lol
my change is very naive, assumes
URL
exists, etc. but something like that will fix it if they can land it upstream
I also don't know for sure how URL
handles punycode, so that should probably be tested to replicate the old behaviour
But it works, and your App.vue
renders 😄yup! well it looks like this patch will be needed for a while anyways, since the mantainer is fairly inactive
Yep 🙂 Glad we got through that - that was a fun one to dive into haha
@James how did you rebuild it btw? found another issue so need to compile it, but the repo doesn't have a build cmd lol
it was
npm run browserify
if I recallthanks!