#Nuxt + Markdown-it: Cannot convert object to primitive value

1 messages · Page 1 of 1 (latest)

fading dove
#

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:

<template>
  <div v-html="parsed">
  </div>
</template>
<script setup>
import { ref } from 'vue'
import MarkdownIt from 'markdown-it'

const md = new MarkdownIt('default', {
    html: true,
    linkify: true,
    breaks: false
  })

const markdown = 'https://modrinth.com'

const parsed = ref(md.render(markdown))
</script>

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:

TypeError: Cannot convert object to primitive value
    at Yc.format (core:user:repro-nuxi-markdown:19126:164)
    at MarkdownIt$1.normalizeLink (core:user:repro-nuxi-markdown:20480:27)
    at Array.Up (core:user:repro-nuxi-markdown:20146:377)
    at ParserInline$1.tokenize (core:user:repro-nuxi-markdown:20315:48)
    at ParserInline$1.parse (core:user:repro-nuxi-markdown:20326:17)
    at Array.Kl (core:user:repro-nuxi-markdown:19540:57)
    at Core.process (core:user:repro-nuxi-markdown:19586:15)
    at MarkdownIt$1.parse (core:user:repro-nuxi-markdown:20536:24)
    at MarkdownIt$1.render (core:user:repro-nuxi-markdown:20538:55)
    at setup (core:user:repro-nuxi-markdown:20795:23) {
  stack: TypeError: Cannot convert object to primitive valu…at setup (core:user:repro-nuxi-markdown:20795:23),
  message: Cannot convert object to primitive value
}
boreal nova
#

Okay, I see what is happening, but not sure why yet

#

It's in this URL format function:

var format = function format(url) {
  var result = '';

  result += url.protocol || '';
  result += url.slashes ? '//' : '';
  result += url.auth ? url.auth + '@' : '';

  if (url.hostname && url.hostname.indexOf(':') !== -1) {
    // ipv6 address
    result += '[' + url.hostname + ']';
  } else {
    result += url.hostname || '';
  }

  result += url.port ? ':' + url.port : '';
  result += url.pathname || '';
  result += url.search || '';
  result += url.hash || '';

  return result;
};
#

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.

#

I'm digging in to try and see where this Proxy is coming from, and why it's in place

fading dove
#

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?

boreal nova
#

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 😅

fading dove
#

it's all from markdown-it

#

this might not have anything to do with nuxt, it might be a workers only issue

boreal nova
#

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! @fading dove parsed.hostname = punycode.toASCII(parsed.hostname);

fading dove
#

Wow

boreal nova
#

punycode is a nodejs thing and not available in Workers

#

so this is getting mangled

fading dove
#

can I make my own polyfill?

boreal nova
#

You might be able to polyfill punycode, but that's probably gonna be a massive polyfill

fading dove
#

well, luckily I don't think anything we use has punycode support

#

so it could just return the passed string

#

right?

#
boreal nova
boreal nova
fading dove
#

like since it's not my project

boreal nova
#

Not really - I'd probably patch-package it or something honestly

#

lemme take a quick look

fading dove
#

should 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

boreal nova
#

And then doing something hacky in the meantime to polyfill / stub it

fading dove
#

thanks a lot for your help james 😄

#

i'll open an issue in the markdown it repo and figure out a hack around it

boreal nova
#

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

fading dove
#

that would be great, yeah I tried pnpm patch but realized I would have to edit the dist/minfied version

boreal nova
#

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

#
diff --git a/lib/index.js b/lib/index.js
index afec8d8..eb35705 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -11,7 +11,6 @@ var ParserBlock  = require('./parser_block');
 var ParserInline = require('./parser_inline');
 var LinkifyIt    = require('linkify-it');
 var mdurl        = require('mdurl');
-var punycode     = require('punycode');
 
 
 var config = {
@@ -56,7 +55,8 @@ function normalizeLink(url) {
     //
     if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {
       try {
-        parsed.hostname = punycode.toASCII(parsed.hostname);
+        var parsedUrl = new URL(parsed.href);
+        parsed.hostname = parsedUrl.hostname;
       } catch (er) { /**/ }
     }
   }
fading dove
#

wow git sucks with minified files lol

boreal nova
#

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 😄

fading dove
#

yup! well it looks like this patch will be needed for a while anyways, since the mantainer is fairly inactive

boreal nova
#

Yep 🙂 Glad we got through that - that was a fun one to dive into haha

fading dove
#

@boreal nova how did you rebuild it btw? found another issue so need to compile it, but the repo doesn't have a build cmd lol

boreal nova