mdx-syntax-highlighting.test.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import mdx from '@astrojs/mdx';
  2. import { describe, it } from 'node:test';
  3. import * as assert from 'node:assert/strict';
  4. import { parseHTML } from 'linkedom';
  5. import { loadFixture } from '../../../astro/test/test-utils.js';
  6. import shikiTwoslash from 'remark-shiki-twoslash';
  7. import rehypePrettyCode from 'rehype-pretty-code';
  8. const FIXTURE_ROOT = new URL('./fixtures/mdx-syntax-hightlighting/', import.meta.url);
  9. describe('MDX syntax highlighting', () => {
  10. describe('shiki', () => {
  11. it('works', async () => {
  12. const fixture = await loadFixture({
  13. root: FIXTURE_ROOT,
  14. markdown: {
  15. syntaxHighlight: 'shiki',
  16. },
  17. integrations: [mdx()],
  18. });
  19. await fixture.build();
  20. const html = await fixture.readFile('/index.html');
  21. const { document } = parseHTML(html);
  22. const shikiCodeBlock = document.querySelector('pre.astro-code');
  23. assert.notEqual(shikiCodeBlock, null);
  24. assert.equal(shikiCodeBlock.getAttribute('style').includes('background-color:#24292e'), true);
  25. });
  26. it('respects markdown.shikiConfig.theme', async () => {
  27. const fixture = await loadFixture({
  28. root: FIXTURE_ROOT,
  29. markdown: {
  30. syntaxHighlight: 'shiki',
  31. shikiConfig: {
  32. theme: 'dracula',
  33. },
  34. },
  35. integrations: [mdx()],
  36. });
  37. await fixture.build();
  38. const html = await fixture.readFile('/index.html');
  39. const { document } = parseHTML(html);
  40. const shikiCodeBlock = document.querySelector('pre.astro-code');
  41. assert.notEqual(shikiCodeBlock, null);
  42. assert.equal(shikiCodeBlock.getAttribute('style').includes('background-color:#282A36'), true);
  43. });
  44. });
  45. describe('prism', () => {
  46. it('works', async () => {
  47. const fixture = await loadFixture({
  48. root: FIXTURE_ROOT,
  49. markdown: {
  50. syntaxHighlight: 'prism',
  51. },
  52. integrations: [mdx()],
  53. });
  54. await fixture.build();
  55. const html = await fixture.readFile('/index.html');
  56. const { document } = parseHTML(html);
  57. const prismCodeBlock = document.querySelector('pre.language-astro');
  58. assert.notEqual(prismCodeBlock, null);
  59. });
  60. for (const extendMarkdownConfig of [true, false]) {
  61. it(`respects syntaxHighlight when extendMarkdownConfig = ${extendMarkdownConfig}`, async () => {
  62. const fixture = await loadFixture({
  63. root: FIXTURE_ROOT,
  64. markdown: {
  65. syntaxHighlight: 'shiki',
  66. },
  67. integrations: [
  68. mdx({
  69. extendMarkdownConfig,
  70. syntaxHighlight: 'prism',
  71. }),
  72. ],
  73. });
  74. await fixture.build();
  75. const html = await fixture.readFile('/index.html');
  76. const { document } = parseHTML(html);
  77. const shikiCodeBlock = document.querySelector('pre.astro-code');
  78. assert.equal(shikiCodeBlock, null, 'Markdown config syntaxHighlight used unexpectedly');
  79. const prismCodeBlock = document.querySelector('pre.language-astro');
  80. assert.notEqual(prismCodeBlock, null);
  81. });
  82. }
  83. });
  84. it('supports custom highlighter - shiki-twoslash', async () => {
  85. const fixture = await loadFixture({
  86. root: FIXTURE_ROOT,
  87. markdown: {
  88. syntaxHighlight: false,
  89. },
  90. integrations: [
  91. mdx({
  92. remarkPlugins: [shikiTwoslash.default ?? shikiTwoslash],
  93. }),
  94. ],
  95. });
  96. await fixture.build();
  97. const html = await fixture.readFile('/index.html');
  98. const { document } = parseHTML(html);
  99. const twoslashCodeBlock = document.querySelector('pre.shiki');
  100. assert.notEqual(twoslashCodeBlock, null);
  101. });
  102. it('supports custom highlighter - rehype-pretty-code', async () => {
  103. const fixture = await loadFixture({
  104. root: FIXTURE_ROOT,
  105. markdown: {
  106. syntaxHighlight: false,
  107. },
  108. integrations: [
  109. mdx({
  110. rehypePlugins: [
  111. [
  112. rehypePrettyCode,
  113. {
  114. onVisitHighlightedLine(node) {
  115. node.properties.style = 'background-color:#000000';
  116. },
  117. },
  118. ],
  119. ],
  120. }),
  121. ],
  122. });
  123. await fixture.build();
  124. const html = await fixture.readFile('/index.html');
  125. assert.equal(html.includes('style="background-color:#000000"'), true);
  126. });
  127. });