pngwn / MDsveX

A markdown preprocessor for Svelte.
https://mdsvex.pngwn.io
MIT License
2.36k stars 102 forks source link

Anchor element href encoding causes SvelteKit to crash on build #435

Open JasherIO opened 2 years ago

JasherIO commented 2 years ago

Issue

%7B is decoded by mdsvex in anchor hrefs, then vite-plugin-svelte errors out on build with "Unexpected token" (I did not see an error with npm run dev)

[vite-plugin-svelte] C:/Users/<user>/Documents/Projects/jasher.io-svelte-kit/src/routes/blog/2018-08-29-rival-series-hosts-play-ins-saturday-sunday.md:12:63 Unexpected token
file: C:/Users/<user>/Documents/Projects/jasher.io-svelte-kit/src/routes/blog/2018-08-29-rival-series-hosts-play-ins-saturday-sunday.md:12:63
 10 |  <Layout_MDSVEX_DEFAULT {...$$props} {...metadata}>
 11 |  <p>Teams from Europe and North America have battled over the past month for 128 spots for this weekend’s play-ins. 4 teams in Europe and 6 teams in North America have a chance at qualifying for Rival Series. Make sure to bookmark the <a
 12 |    href="https://smash.gg/league/rlcs-season-6/schedule?filter={%22upcoming%22%3Atrue}"
                                                                      ^
 13 |    rel="nofollow"
 14 |  >brackets</a> to stay up-to-date.</p>
> C:/Users/<user>/Documents/Projects/jasher.io-svelte-kit/src/routes/blog/2018-08-29-rival-series-hosts-play-ins-saturday-sunday.md:12:63 Unexpected token

Reproducing

// test.js
const { compile } = require('mdsvex');

const body = `
  Teams from Europe and North America have battled over the past month for 128 spots for this weekend's play-ins. 4 teams in Europe and 6 teams in North America have a chance at qualifying for Rival Series. 
  Make sure to bookmark the [brackets](https://smash.gg/league/rlcs-season-6/schedule?filter=%7B%22upcoming%22%3Atrue%7D) to stay up-to-date.
`;

(async () => {
  const compiled = await compile(body, '');
  console.log(compiled);
})();
{
  code: '\n' +
    '<p>  Teams from Europe and North America have battled over the past month for 128 spots for this weekend’s play-ins. 4 teams in Europe and 6 teams in North America have a chance at qualifying for Rival Series.\n' +
    'Make sure to bookmark the <a\n' +
    '  href="https://smash.gg/league/rlcs-season-6/schedule?filter={%22upcoming%22%3Atrue}"\n' +
    '  rel="nofollow"\n' +
    '>brackets</a> to stay up-to-date.</p>\n',
  data: {},
  map: ''
}

Workaround

// mdsvex.config.js
import { defineMDSveXConfig as defineConfig } from 'mdsvex';
import rehype_urls from 'rehype-urls';

function encode(url) {
    return new URL(encodeURI(url.href));
};

const config = defineConfig({
    extensions: ['.svelte.md', '.md', '.svx'],

    layout: 'path_to_layout'

    smartypants: {
        dashes: 'oldschool'
    },

    remarkPlugins: [],
    rehypePlugins: [ [rehype_urls, encode] ]
});

export default config;
JasherIO commented 2 years ago

I was wrong about the workaround. It does remove the error in SvelteKit, but that is because the rehype plugin runs before mdsvex decodes %7B. So, whatever is causing it is after remark/rehype in the pipeline.

// mdsvex.config.js
import { defineMDSveXConfig as defineConfig } from 'mdsvex';
import rehype_urls from 'rehype-urls';

function encode(url) {
    const encoded = encodeURI(url.href);
    if (url.host === 'smash.gg') {
        console.log(`url.href: ${url.href}`);
        console.log(`encoded: ${encoded}`);
    }
    return encoded;
};

const config = defineConfig({
    extensions: ['.svelte.md', '.md', '.svx'],

    layout: 'path_to_layout'

    smartypants: {
        dashes: 'oldschool'
    },

    remarkPlugins: [],
    rehypePlugins: [ [rehype_urls, encode] ]
});

export default config;
url.href: https://smash.gg/league/rlcs-season-6/schedule?filter=%7B%22upcoming%22%3Atrue%7D
encoded: https://smash.gg/league/rlcs-season-6/schedule?filter=%257B%2522upcoming%2522%253Atrue%257D
pngwn commented 2 years ago

I was pretty certain that decoding was done right at the beginning of the parse process, before anything else actually happens but I could be wrong. Will look into this when I can.