MarkdownTokens.svelte 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <script lang="ts">
  2. import { onMount } from 'svelte';
  3. import type { Token } from 'marked';
  4. import { revertSanitizedResponseContent, unescapeHtml } from '$lib/utils';
  5. import CodeBlock from '$lib/components/chat/Messages/CodeBlock.svelte';
  6. import MarkdownInlineTokens from '$lib/components/chat/Messages/MarkdownInlineTokens.svelte';
  7. import KatexRenderer from './KatexRenderer.svelte';
  8. export let id: string;
  9. export let tokens: Token[];
  10. export let top = true;
  11. const headerComponent = (depth: number) => {
  12. return 'h' + depth;
  13. };
  14. </script>
  15. <!-- {JSON.stringify(tokens)} -->
  16. {#each tokens as token, tokenIdx}
  17. {#if token.type === 'hr'}
  18. <hr />
  19. {:else if token.type === 'heading'}
  20. <svelte:element this={headerComponent(token.depth)}>
  21. <MarkdownInlineTokens id={`${id}-${tokenIdx}-h`} tokens={token.tokens} />
  22. </svelte:element>
  23. {:else if token.type === 'code'}
  24. <CodeBlock
  25. id={`${id}-${tokenIdx}`}
  26. {token}
  27. lang={token?.lang ?? ''}
  28. code={revertSanitizedResponseContent(token?.text ?? '')}
  29. />
  30. {:else if token.type === 'table'}
  31. <table>
  32. <thead>
  33. <tr>
  34. {#each token.header as header, headerIdx}
  35. <th style={token.align[headerIdx] ? '' : `text-align: ${token.align[headerIdx]}`}>
  36. <MarkdownInlineTokens
  37. id={`${id}-${tokenIdx}-header-${headerIdx}`}
  38. tokens={header.tokens}
  39. />
  40. </th>
  41. {/each}
  42. </tr>
  43. </thead>
  44. <tbody>
  45. {#each token.rows as row, rowIdx}
  46. <tr>
  47. {#each row ?? [] as cell, cellIdx}
  48. <td style={token.align[cellIdx] ? '' : `text-align: ${token.align[cellIdx]}`}>
  49. <MarkdownInlineTokens
  50. id={`${id}-${tokenIdx}-row-${rowIdx}-${cellIdx}`}
  51. tokens={cell.tokens}
  52. />
  53. </td>
  54. {/each}
  55. </tr>
  56. {/each}
  57. </tbody>
  58. </table>
  59. {:else if token.type === 'blockquote'}
  60. <blockquote>
  61. <svelte:self id={`${id}-${tokenIdx}`} tokens={token.tokens} />
  62. </blockquote>
  63. {:else if token.type === 'list'}
  64. {#if token.ordered}
  65. <ol start={token.start || 1}>
  66. {#each token.items as item, itemIdx}
  67. <li>
  68. <svelte:self
  69. id={`${id}-${tokenIdx}-${itemIdx}`}
  70. tokens={item.tokens}
  71. top={token.loose}
  72. />
  73. </li>
  74. {/each}
  75. </ol>
  76. {:else}
  77. <ul>
  78. {#each token.items as item, itemIdx}
  79. <li>
  80. <svelte:self
  81. id={`${id}-${tokenIdx}-${itemIdx}`}
  82. tokens={item.tokens}
  83. top={token.loose}
  84. />
  85. </li>
  86. {/each}
  87. </ul>
  88. {/if}
  89. {:else if token.type === 'html'}
  90. {@html token.text}
  91. {:else if token.type === 'paragraph'}
  92. <p>
  93. <MarkdownInlineTokens id={`${id}-${tokenIdx}-p`} tokens={token.tokens ?? []} />
  94. </p>
  95. {:else if token.type === 'text'}
  96. {#if top}
  97. <p>
  98. {#if token.tokens}
  99. <MarkdownInlineTokens id={`${id}-${tokenIdx}-t`} tokens={token.tokens} />
  100. {:else}
  101. {unescapeHtml(token.text)}
  102. {/if}
  103. </p>
  104. {:else if token.tokens}
  105. <MarkdownInlineTokens id={`${id}-${tokenIdx}-p`} tokens={token.tokens ?? []} />
  106. {:else}
  107. {unescapeHtml(token.text)}
  108. {/if}
  109. {:else if token.type === 'inlineKatex'}
  110. {#if token.text}
  111. <KatexRenderer
  112. content={revertSanitizedResponseContent(token.text)}
  113. displayMode={token?.displayMode ?? false}
  114. />
  115. {/if}
  116. {:else if token.type === 'blockKatex'}
  117. {#if token.text}
  118. <KatexRenderer
  119. content={revertSanitizedResponseContent(token.text)}
  120. displayMode={token?.displayMode ?? false}
  121. />
  122. {/if}
  123. {:else if token.type === 'space'}
  124. {''}
  125. {:else}
  126. {console.log('Unknown token', token)}
  127. {/if}
  128. {/each}