summaryrefslogtreecommitdiff
path: root/packages/markdown/remark/src/rehype-islands.ts
blob: 099dc4d75c8de9d4946ba88ac8870097b857c2b2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import {SKIP, visit} from 'unist-util-visit';

// This fixes some confusing bugs coming from somewhere inside of our Markdown pipeline.
// `unist`/`remark`/`rehype` (not sure) often generate malformed HTML inside of <astro-root>
// For hydration to work properly, frameworks need the DOM to be the exact same on server/client.
// This reverts some "helpful corrections" that are applied to our perfectly valid HTML!
export default function rehypeIslands(): any {
  return function (node: any): any {
    return visit(node, 'element', (el) => {
      // Bugs only happen inside of <astro-root> islands
      if (el.tagName == 'astro-root') {
        visit(el, 'text', (child, index, parent) => {
          if (child.type === 'text') {
            // Sometimes comments can be trapped as text, which causes them to be escaped 
            // This casts them back to real HTML comments
            if (parent && child.value.indexOf('<!--') > -1 && index != null) {
              parent.children.splice(index, 1, { ...child, type: 'comment', value: child.value.replace('<!--', '').replace('-->', '').trim()});
              return [SKIP, index]
            }
            // For some reason `rehype` likes to inject extra linebreaks,
            // but React and Vue throw hydration errors when they see these!
            // This removes any extra linebreaks, which is fine because
            // framework compilers don't preserve them anyway
            child.value = child.value.replace(/\n+/g, '');
            return child;
          }
        })
      }
    });
  };
}