@humanspeak/svelte-markdown 0.7.10 → 0.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -270
- package/dist/Parser.svelte +16 -6
- package/dist/Parser.svelte.d.ts +11 -3
- package/dist/renderers/html/A.svelte.d.ts +3 -2
- package/dist/renderers/html/Abbr.svelte.d.ts +3 -2
- package/dist/renderers/html/Address.svelte.d.ts +3 -2
- package/dist/renderers/html/Article.svelte.d.ts +3 -2
- package/dist/renderers/html/Aside.svelte.d.ts +3 -2
- package/dist/renderers/html/Audio.svelte.d.ts +3 -2
- package/dist/renderers/html/B.svelte.d.ts +3 -2
- package/dist/renderers/html/Bdi.svelte.d.ts +3 -2
- package/dist/renderers/html/Bdo.svelte.d.ts +3 -2
- package/dist/renderers/html/Blockquote.svelte.d.ts +3 -2
- package/dist/renderers/html/Button.svelte.d.ts +3 -2
- package/dist/renderers/html/Canvas.svelte.d.ts +3 -2
- package/dist/renderers/html/Cite.svelte.d.ts +3 -2
- package/dist/renderers/html/Code.svelte.d.ts +3 -2
- package/dist/renderers/html/Datalist.svelte.d.ts +3 -2
- package/dist/renderers/html/Dd.svelte.d.ts +3 -2
- package/dist/renderers/html/Del.svelte.d.ts +3 -2
- package/dist/renderers/html/Details.svelte.d.ts +3 -2
- package/dist/renderers/html/Dfn.svelte.d.ts +3 -2
- package/dist/renderers/html/Dialog.svelte.d.ts +3 -2
- package/dist/renderers/html/Div.svelte.d.ts +3 -2
- package/dist/renderers/html/Dl.svelte.d.ts +3 -2
- package/dist/renderers/html/Dt.svelte.d.ts +3 -2
- package/dist/renderers/html/Em.svelte.d.ts +3 -2
- package/dist/renderers/html/Embed.svelte.d.ts +3 -2
- package/dist/renderers/html/Fieldset.svelte.d.ts +3 -2
- package/dist/renderers/html/Footer.svelte.d.ts +3 -2
- package/dist/renderers/html/Form.svelte.d.ts +3 -2
- package/dist/renderers/html/H1.svelte.d.ts +3 -2
- package/dist/renderers/html/H2.svelte.d.ts +3 -2
- package/dist/renderers/html/H3.svelte.d.ts +3 -2
- package/dist/renderers/html/H4.svelte.d.ts +3 -2
- package/dist/renderers/html/H5.svelte.d.ts +3 -2
- package/dist/renderers/html/H6.svelte.d.ts +3 -2
- package/dist/renderers/html/Header.svelte.d.ts +3 -2
- package/dist/renderers/html/Hgroup.svelte.d.ts +3 -2
- package/dist/renderers/html/Hr.svelte.d.ts +3 -2
- package/dist/renderers/html/I.svelte.d.ts +3 -2
- package/dist/renderers/html/Iframe.svelte.d.ts +3 -2
- package/dist/renderers/html/Img.svelte.d.ts +3 -2
- package/dist/renderers/html/Input.svelte.d.ts +3 -2
- package/dist/renderers/html/Kbd.svelte.d.ts +3 -2
- package/dist/renderers/html/Label.svelte.d.ts +3 -2
- package/dist/renderers/html/Legend.svelte.d.ts +3 -2
- package/dist/renderers/html/Li.svelte.d.ts +3 -2
- package/dist/renderers/html/Main.svelte.d.ts +3 -2
- package/dist/renderers/html/Mark.svelte.d.ts +3 -2
- package/dist/renderers/html/Menu.svelte.d.ts +3 -2
- package/dist/renderers/html/Meter.svelte.d.ts +3 -2
- package/dist/renderers/html/Nav.svelte.d.ts +3 -2
- package/dist/renderers/html/Ol.svelte.d.ts +3 -2
- package/dist/renderers/html/Optgroup.svelte.d.ts +3 -2
- package/dist/renderers/html/Option.svelte.d.ts +3 -2
- package/dist/renderers/html/Output.svelte.d.ts +3 -2
- package/dist/renderers/html/P.svelte.d.ts +3 -2
- package/dist/renderers/html/Param.svelte.d.ts +3 -2
- package/dist/renderers/html/Picture.svelte.d.ts +3 -2
- package/dist/renderers/html/Pre.svelte.d.ts +3 -2
- package/dist/renderers/html/Progress.svelte.d.ts +3 -2
- package/dist/renderers/html/S.svelte.d.ts +3 -2
- package/dist/renderers/html/Samp.svelte.d.ts +3 -2
- package/dist/renderers/html/Section.svelte.d.ts +3 -2
- package/dist/renderers/html/Select.svelte.d.ts +3 -2
- package/dist/renderers/html/Small.svelte.d.ts +3 -2
- package/dist/renderers/html/Source.svelte.d.ts +3 -2
- package/dist/renderers/html/Span.svelte.d.ts +3 -2
- package/dist/renderers/html/Strong.svelte.d.ts +3 -2
- package/dist/renderers/html/Sub.svelte.d.ts +3 -2
- package/dist/renderers/html/Summary.svelte.d.ts +3 -2
- package/dist/renderers/html/Sup.svelte.d.ts +3 -2
- package/dist/renderers/html/Table.svelte.d.ts +3 -2
- package/dist/renderers/html/Tbody.svelte.d.ts +3 -2
- package/dist/renderers/html/Td.svelte.d.ts +3 -2
- package/dist/renderers/html/Textarea.svelte.d.ts +3 -2
- package/dist/renderers/html/Tfoot.svelte.d.ts +3 -2
- package/dist/renderers/html/Th.svelte.d.ts +3 -2
- package/dist/renderers/html/Thead.svelte.d.ts +3 -2
- package/dist/renderers/html/Tr.svelte.d.ts +3 -2
- package/dist/renderers/html/Track.svelte.d.ts +3 -2
- package/dist/renderers/html/U.svelte.d.ts +3 -2
- package/dist/renderers/html/Ul.svelte.d.ts +3 -2
- package/dist/renderers/html/Var.svelte.d.ts +3 -2
- package/package.json +70 -66
package/README.md
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @humanspeak/svelte-markdown
|
|
2
|
+
|
|
3
|
+
A powerful, customizable markdown renderer for Svelte with TypeScript support. Built as a successor to the original svelte-markdown package by Pablo Berganza, now maintained and enhanced by Humanspeak, Inc.
|
|
2
4
|
|
|
3
5
|
[](https://www.npmjs.com/package/@humanspeak/svelte-markdown)
|
|
4
6
|
[](https://github.com/humanspeak/svelte-markdown/actions/workflows/npm-publish.yml)
|
|
@@ -6,20 +8,24 @@
|
|
|
6
8
|
[](https://github.com/humanspeak/svelte-markdown/blob/main/LICENSE.md)
|
|
7
9
|
[](https://www.npmjs.com/package/@humanspeak/svelte-markdown)
|
|
8
10
|
[](https://github.com/humanspeak/svelte-markdown/actions/workflows/codeql.yml)
|
|
11
|
+
[](https://trunk.io)
|
|
9
12
|
[](http://www.typescriptlang.org/)
|
|
10
13
|
[](https://www.npmjs.com/package/@humanspeak/svelte-markdown)
|
|
11
14
|
[](https://github.com/humanspeak/svelte-markdown/graphs/commit-activity)
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Feel free to play with it and leave comments on its [homepage](https://markdown.svelte.page)
|
|
16
|
+
## Features
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
- 🚀 Full markdown syntax support through Marked
|
|
19
|
+
- 💪 Complete TypeScript support with strict typing
|
|
20
|
+
- 🎨 Customizable component rendering system
|
|
21
|
+
- 🔒 Secure HTML parsing via HTMLParser2
|
|
22
|
+
- 🎯 GitHub-style slug generation for headers
|
|
23
|
+
- ♿ WCAG 2.1 accessibility compliance
|
|
24
|
+
- 🧪 Comprehensive test coverage (vitest and playwright)
|
|
25
|
+
- 🔄 Svelte 5 runes compatibility
|
|
18
26
|
|
|
19
27
|
## Installation
|
|
20
28
|
|
|
21
|
-
You can install it with
|
|
22
|
-
|
|
23
29
|
```bash
|
|
24
30
|
npm i -S @humanspeak/svelte-markdown
|
|
25
31
|
```
|
|
@@ -31,7 +37,31 @@ pnpm add @humanspeak/svelte-markdown
|
|
|
31
37
|
yarn add @humanspeak/svelte-markdown
|
|
32
38
|
```
|
|
33
39
|
|
|
34
|
-
##
|
|
40
|
+
## External Dependencies
|
|
41
|
+
|
|
42
|
+
This package carefully selects its dependencies to provide a robust and maintainable solution:
|
|
43
|
+
|
|
44
|
+
### Core Dependencies
|
|
45
|
+
|
|
46
|
+
- **marked**
|
|
47
|
+
|
|
48
|
+
- Industry-standard markdown parser
|
|
49
|
+
- Battle-tested in production
|
|
50
|
+
- Extensive security features
|
|
51
|
+
|
|
52
|
+
- **github-slugger**
|
|
53
|
+
|
|
54
|
+
- GitHub-style heading ID generation
|
|
55
|
+
- Unicode support
|
|
56
|
+
- Collision handling
|
|
57
|
+
|
|
58
|
+
- **htmlparser2**
|
|
59
|
+
|
|
60
|
+
- High-performance HTML parsing
|
|
61
|
+
- Streaming capabilities
|
|
62
|
+
- Security-focused design
|
|
63
|
+
|
|
64
|
+
## Basic Usage
|
|
35
65
|
|
|
36
66
|
```svelte
|
|
37
67
|
<script lang="ts">
|
|
@@ -54,7 +84,7 @@ This is a paragraph with **bold** and <em>mixed HTML</em>.
|
|
|
54
84
|
|
|
55
85
|
## TypeScript Support
|
|
56
86
|
|
|
57
|
-
The package is written in TypeScript and includes full type definitions
|
|
87
|
+
The package is written in TypeScript and includes full type definitions:
|
|
58
88
|
|
|
59
89
|
```typescript
|
|
60
90
|
import type {
|
|
@@ -88,166 +118,47 @@ Here's a complete example of a custom renderer with TypeScript support:
|
|
|
88
118
|
</a>
|
|
89
119
|
```
|
|
90
120
|
|
|
91
|
-
##
|
|
92
|
-
|
|
93
|
-
```svelte
|
|
94
|
-
<script lang="ts">
|
|
95
|
-
import SvelteMarkdown from '@humanspeak/svelte-markdown'
|
|
96
|
-
const source = `
|
|
97
|
-
# This is a header
|
|
98
|
-
|
|
99
|
-
This is a paragraph.
|
|
100
|
-
|
|
101
|
-
* This is a list
|
|
102
|
-
* With two items
|
|
103
|
-
1. And a sublist
|
|
104
|
-
2. That is ordered
|
|
105
|
-
* With another
|
|
106
|
-
* Sublist inside
|
|
107
|
-
|
|
108
|
-
| And this is | A table |
|
|
109
|
-
|-------------|---------|
|
|
110
|
-
| With two | columns |`
|
|
111
|
-
</script>
|
|
112
|
-
|
|
113
|
-
<SvelteMarkdown {source} />
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
This would render something like
|
|
117
|
-
|
|
118
|
-
```html
|
|
119
|
-
<h1>This is a header</h1>
|
|
120
|
-
<p>This is a paragraph.</p>
|
|
121
|
-
<ul>
|
|
122
|
-
<li>This is a list</li>
|
|
123
|
-
<li>
|
|
124
|
-
With two items
|
|
125
|
-
<ol start="1">
|
|
126
|
-
<li>And a sublist</li>
|
|
127
|
-
<li>
|
|
128
|
-
That is ordered
|
|
129
|
-
<ul>
|
|
130
|
-
<li>With another</li>
|
|
131
|
-
<li>Sublist inside</li>
|
|
132
|
-
</ul>
|
|
133
|
-
</li>
|
|
134
|
-
</ol>
|
|
135
|
-
</li>
|
|
136
|
-
</ul>
|
|
137
|
-
<table>
|
|
138
|
-
<thead>
|
|
139
|
-
<tr>
|
|
140
|
-
<th>And this is</th>
|
|
141
|
-
<th>A table</th>
|
|
142
|
-
</tr>
|
|
143
|
-
</thead>
|
|
144
|
-
<tbody>
|
|
145
|
-
<tr>
|
|
146
|
-
<td>With two</td>
|
|
147
|
-
<td>columns</td>
|
|
148
|
-
</tr>
|
|
149
|
-
</tbody>
|
|
150
|
-
</table>
|
|
151
|
-
```
|
|
121
|
+
## Advanced Features
|
|
152
122
|
|
|
153
|
-
|
|
123
|
+
### Table Support with Mixed Content
|
|
154
124
|
|
|
155
|
-
|
|
125
|
+
The package excels at handling complex nested structures and mixed content:
|
|
156
126
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
- `renderes.html` - _object (optional)_ An object where the key represents the HTML tag and the value is a Svelte component. This object will be merged with the default renderers. For now you can check how the default renderers are written in the source code at `src/renderers/html`.
|
|
164
|
-
- `options` - _object (optional)_ An object containing [options for Marked](https://marked.js.org/using_advanced#options)
|
|
165
|
-
|
|
166
|
-
## Renderers
|
|
167
|
-
|
|
168
|
-
To create custom renderer for an element, you can create a Svelte component with the default props ([you can check them here](https://marked.js.org/using_pro#renderer)), for example:
|
|
169
|
-
|
|
170
|
-
_`ImageComponent.svelte`_
|
|
171
|
-
|
|
172
|
-
```svelte
|
|
173
|
-
<script lang="ts">
|
|
174
|
-
interface Props {
|
|
175
|
-
href?: string
|
|
176
|
-
title?: string
|
|
177
|
-
text?: string
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const { href = '', title = undefined, text = '' }: Props = $props()
|
|
181
|
-
</script>
|
|
182
|
-
|
|
183
|
-
<img src={href} {title} alt={text} />
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
So you can import the component and pass to the `renderers` props:
|
|
187
|
-
|
|
188
|
-
```svelte
|
|
189
|
-
<script lang="ts">
|
|
190
|
-
import SvelteMarkdown from '@humanspeak/svelte-markdown'
|
|
191
|
-
import ImageComponent from './renderers/ImageComponent.svelte'
|
|
192
|
-
export let content
|
|
193
|
-
</script>
|
|
194
|
-
|
|
195
|
-
<SvelteMarkdown source={content} renderers={{ image: ImageComponent }} />
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
## Rendering From Tokens
|
|
199
|
-
|
|
200
|
-
For greater flexibility, an array of tokens may be given as `source`, in which case parsing is skipped and the tokens will be rendered directly. This alows you to generate and transform the tokens freely beforehand. Example:
|
|
201
|
-
|
|
202
|
-
```html
|
|
203
|
-
<script lang="ts">
|
|
204
|
-
import SvelteMarkdown from '@humanspeak/svelte-markdown'
|
|
205
|
-
import { marked } from 'marked'
|
|
206
|
-
|
|
207
|
-
const tokens = marked.lexer('this is an **example**')
|
|
208
|
-
|
|
209
|
-
marked.walkTokens(tokens, (token) => {
|
|
210
|
-
if (token.type == 'strong') token.type = 'em'
|
|
211
|
-
token.raw = token.raw.toUpperCase()
|
|
212
|
-
})
|
|
213
|
-
</script>
|
|
214
|
-
|
|
215
|
-
<SvelteMarkdown source="{tokens}" />
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
This will render the following:
|
|
219
|
-
|
|
220
|
-
```html
|
|
221
|
-
<p>THIS IS AN <em>EXAMPLE</em></p>
|
|
127
|
+
```markdown
|
|
128
|
+
| Type | Content |
|
|
129
|
+
| ---------- | --------------------------------------- |
|
|
130
|
+
| Nested | <div>**bold** and _italic_</div> |
|
|
131
|
+
| Mixed List | <ul><li>Item 1</li><li>Item 2</li></ul> |
|
|
132
|
+
| Code | <code>`inline code`</code> |
|
|
222
133
|
```
|
|
223
134
|
|
|
224
|
-
|
|
135
|
+
### HTML in Markdown
|
|
225
136
|
|
|
226
|
-
|
|
137
|
+
Seamlessly mix HTML and Markdown:
|
|
227
138
|
|
|
228
|
-
```
|
|
229
|
-
<
|
|
230
|
-
|
|
139
|
+
```markdown
|
|
140
|
+
<div style="color: blue">
|
|
141
|
+
### This is a Markdown heading inside HTML
|
|
142
|
+
And here's some **bold** text too!
|
|
143
|
+
</div>
|
|
231
144
|
|
|
232
|
-
|
|
145
|
+
<details>
|
|
146
|
+
<summary>Click to expand</summary>
|
|
233
147
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
</script>
|
|
148
|
+
- This is a markdown list
|
|
149
|
+
- Inside an HTML details element
|
|
150
|
+
- Supporting **bold** and _italic_ text
|
|
238
151
|
|
|
239
|
-
|
|
152
|
+
</details>
|
|
240
153
|
```
|
|
241
154
|
|
|
242
|
-
## Available
|
|
243
|
-
|
|
244
|
-
These would be the property names expected by the `renderers` option.
|
|
155
|
+
## Available Renderers
|
|
245
156
|
|
|
246
|
-
- `text` - Text
|
|
157
|
+
- `text` - Text within other elements
|
|
247
158
|
- `paragraph` - Paragraph (`<p>`)
|
|
248
159
|
- `em` - Emphasis (`<em>`)
|
|
249
160
|
- `strong` - Strong/bold (`<strong>`)
|
|
250
|
-
- `hr` - Horizontal rule
|
|
161
|
+
- `hr` - Horizontal rule (`<hr>`)
|
|
251
162
|
- `blockquote` - Block quote (`<blockquote>`)
|
|
252
163
|
- `del` - Deleted/strike-through (`<del>`)
|
|
253
164
|
- `link` - Link (`<a>`)
|
|
@@ -266,145 +177,74 @@ These would be the property names expected by the `renderers` option.
|
|
|
266
177
|
|
|
267
178
|
### Optional List Renderers
|
|
268
179
|
|
|
269
|
-
For fine
|
|
270
|
-
If either key is missing, the default `listitem` will be used. There are two
|
|
271
|
-
optional keys in the `renderers` option which can provide this:
|
|
272
|
-
|
|
273
|
-
- `orderedlistitem` - A list item appearing inside an ordered list
|
|
274
|
-
- `unorderedlistitem` A list item appearing inside an un-ordered list
|
|
275
|
-
|
|
276
|
-
As an example, if we have an `orderedlistitem`:
|
|
277
|
-
|
|
278
|
-
```html
|
|
279
|
-
<style>
|
|
280
|
-
li::marker {
|
|
281
|
-
color: blue;
|
|
282
|
-
}
|
|
283
|
-
</style>
|
|
284
|
-
|
|
285
|
-
<li><slot></slot></li>
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
Then numbers at the start of ordered list items would be colored blue. Bullets at the start of unordered list items
|
|
289
|
-
would remain the default text color.
|
|
290
|
-
|
|
291
|
-
### Inline Markdown
|
|
292
|
-
|
|
293
|
-
To use [inline markdown](https://marked.js.org/using_advanced#inline), you can assign the prop `isInline` to the component.
|
|
294
|
-
|
|
295
|
-
```html
|
|
296
|
-
<SvelteMarkdown {source} isInline />
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
## HTML rendering
|
|
300
|
-
|
|
301
|
-
The package supports mixing HTML and Markdown content seamlessly within the same document. You can use HTML tags alongside Markdown syntax, and both will be properly rendered through their respective components.
|
|
302
|
-
|
|
303
|
-
### Basic HTML in Markdown
|
|
304
|
-
|
|
305
|
-
You can freely mix HTML tags with Markdown syntax:
|
|
306
|
-
|
|
307
|
-
```markdown
|
|
308
|
-
This is a **markdown** paragraph with <em>HTML emphasis</em> mixed in.
|
|
309
|
-
|
|
310
|
-
<div style="color: blue">
|
|
311
|
-
### This is a Markdown heading inside HTML
|
|
312
|
-
And here's some **bold** text too!
|
|
313
|
-
</div>
|
|
314
|
-
```
|
|
180
|
+
For fine-grained styling:
|
|
315
181
|
|
|
316
|
-
|
|
182
|
+
- `orderedlistitem` - Items in ordered lists
|
|
183
|
+
- `unorderedlistitem` - Items in unordered lists
|
|
317
184
|
|
|
318
|
-
|
|
185
|
+
### HTML Renderers
|
|
319
186
|
|
|
320
|
-
|
|
321
|
-
| Feature | Markdown | HTML |
|
|
322
|
-
| ------- | :---------: | ---------------------: |
|
|
323
|
-
| Bold | **text** | <strong>text</strong> |
|
|
324
|
-
| Italic | _text_ | <em>text</em> |
|
|
325
|
-
| Links | [text](url) | <a href="url">text</a> |
|
|
326
|
-
```
|
|
187
|
+
The `html` renderer is special and can be configured separately to handle HTML elements:
|
|
327
188
|
|
|
328
|
-
|
|
189
|
+
| Element | Description |
|
|
190
|
+
| -------- | -------------------- |
|
|
191
|
+
| `div` | Division element |
|
|
192
|
+
| `span` | Inline container |
|
|
193
|
+
| `table` | HTML table structure |
|
|
194
|
+
| `thead` | Table header group |
|
|
195
|
+
| `tbody` | Table body group |
|
|
196
|
+
| `tr` | Table row |
|
|
197
|
+
| `td` | Table data cell |
|
|
198
|
+
| `th` | Table header cell |
|
|
199
|
+
| `ul` | Unordered list |
|
|
200
|
+
| `ol` | Ordered list |
|
|
201
|
+
| `li` | List item |
|
|
202
|
+
| `code` | Code block |
|
|
203
|
+
| `em` | Emphasized text |
|
|
204
|
+
| `strong` | Strong text |
|
|
205
|
+
| `a` | Anchor/link |
|
|
206
|
+
| `img` | Image |
|
|
329
207
|
|
|
330
|
-
HTML
|
|
208
|
+
You can customize HTML rendering by providing your own components:
|
|
331
209
|
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
<summary>Click to expand</summary>
|
|
335
|
-
|
|
336
|
-
- This is a markdown list
|
|
337
|
-
- Inside an HTML details element
|
|
338
|
-
- Supporting **bold** and _italic_ text
|
|
339
|
-
|
|
340
|
-
</details>
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
### HTML Block Elements
|
|
344
|
-
|
|
345
|
-
HTML block elements can contain Markdown content:
|
|
346
|
-
|
|
347
|
-
```markdown
|
|
348
|
-
<blockquote>
|
|
349
|
-
### Markdown Heading in Blockquote
|
|
210
|
+
```typescript
|
|
211
|
+
import type { HtmlRenderers } from '@humanspeak/svelte-markdown'
|
|
350
212
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
213
|
+
const customHtmlRenderers: Partial<HtmlRenderers> = {
|
|
214
|
+
div: YourCustomDivComponent,
|
|
215
|
+
span: YourCustomSpanComponent
|
|
216
|
+
}
|
|
354
217
|
```
|
|
355
218
|
|
|
356
|
-
|
|
219
|
+
## Events
|
|
357
220
|
|
|
358
|
-
|
|
221
|
+
The component emits a `parsed` event when tokens are calculated:
|
|
359
222
|
|
|
360
223
|
```svelte
|
|
361
224
|
<script lang="ts">
|
|
362
225
|
import SvelteMarkdown from '@humanspeak/svelte-markdown'
|
|
363
|
-
import CustomBlockquote from './renderers/CustomBlockquote.svelte'
|
|
364
226
|
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
</blockquote>
|
|
369
|
-
`
|
|
227
|
+
const handleParsed = (tokens: Token[] | TokensList) => {
|
|
228
|
+
console.log('Parsed tokens:', tokens)
|
|
229
|
+
}
|
|
370
230
|
</script>
|
|
371
231
|
|
|
372
|
-
<SvelteMarkdown
|
|
373
|
-
{source}
|
|
374
|
-
renderers={{
|
|
375
|
-
html: {
|
|
376
|
-
blockquote: CustomBlockquote
|
|
377
|
-
}
|
|
378
|
-
}}
|
|
379
|
-
/>
|
|
232
|
+
<SvelteMarkdown {source} parsed={handleParsed} />
|
|
380
233
|
```
|
|
381
234
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
1. The HTML rendering is handled by dedicated Svelte components, ensuring proper integration with Svelte's reactivity system.
|
|
385
|
-
|
|
386
|
-
2. All HTML elements are sanitized by default for security. Custom HTML attributes are preserved and passed to the corresponding components.
|
|
387
|
-
|
|
388
|
-
3. The package includes renderers for all standard HTML5 elements, which can be found in the source code at `src/renderers/html/`.
|
|
389
|
-
|
|
390
|
-
4. When mixing HTML and Markdown, the parser maintains proper nesting and hierarchy of elements.
|
|
391
|
-
|
|
392
|
-
5. For security reasons, script tags and potentially harmful HTML attributes are stripped out during parsing.
|
|
393
|
-
|
|
394
|
-
## Developing
|
|
395
|
-
|
|
396
|
-
Some tests have been added to the `tests` folder. You can clone this repo and create another svelte app and link it to this repo to try modifying it.
|
|
235
|
+
## Props
|
|
397
236
|
|
|
398
|
-
|
|
237
|
+
| Prop | Type | Description |
|
|
238
|
+
| --------- | ----------------------- | ------------------------------------- |
|
|
239
|
+
| source | `string \| Token[]` | Markdown content or pre-parsed tokens |
|
|
240
|
+
| renderers | `Partial<Renderers>` | Custom component overrides |
|
|
241
|
+
| options | `SvelteMarkdownOptions` | Marked parser configuration |
|
|
242
|
+
| isInline | `boolean` | Toggle inline parsing mode |
|
|
399
243
|
|
|
400
|
-
|
|
401
|
-
- [Github-Slugger](https://github.com/Flet/github-slugger)
|
|
402
|
-
- [HTMLParser2](https://github.com/fb55/htmlparser2)
|
|
244
|
+
## License
|
|
403
245
|
|
|
404
|
-
|
|
246
|
+
MIT © [Humanspeak, Inc.](LICENSE.md)
|
|
405
247
|
|
|
406
|
-
|
|
407
|
-
- [Svelte](https://svelte.dev) - JavaScript front-end framework
|
|
408
|
-
- [Original](https://github.com/pablo-abc/svelte-markdown) - Original component
|
|
248
|
+
## Credits
|
|
409
249
|
|
|
410
250
|
Made with ♥ by [Humanspeak](https://humanspeak.com)
|
package/dist/Parser.svelte
CHANGED
|
@@ -34,6 +34,12 @@
|
|
|
34
34
|
* - Implements special logic for tables, lists, and HTML content
|
|
35
35
|
* - Handles component prop spreading carefully to avoid conflicts
|
|
36
36
|
* - Maintains type safety through TypeScript interfaces
|
|
37
|
+
* - HTML token handling in table cells uses type assertions for better type safety
|
|
38
|
+
* - Table cell HTML content is processed with proper token nesting and attribute preservation
|
|
39
|
+
* - Improved HTML component rendering with proper type checking for tag properties
|
|
40
|
+
* - Added support for nested markdown within HTML table cells (see test at lines 311-343 in SvelteMarkdown.test.ts)
|
|
41
|
+
* - Token cleanup utilities handle complex nested structures (see lines 105-127 in token-cleanup.test.ts)
|
|
42
|
+
* - HTML parsing maintains proper structure for both simple and complex nested elements
|
|
37
43
|
*
|
|
38
44
|
*/
|
|
39
45
|
|
|
@@ -103,15 +109,19 @@
|
|
|
103
109
|
align={(rest.align as string[])[i]}
|
|
104
110
|
{...cellRest}
|
|
105
111
|
>
|
|
106
|
-
{#if cells.type === 'html'}
|
|
107
|
-
{@const
|
|
108
|
-
|
|
112
|
+
{#if cells.tokens?.[0]?.type === 'html'}
|
|
113
|
+
{@const token = cells.tokens[0] as Token & {
|
|
114
|
+
tag: string
|
|
115
|
+
tokens?: Token[]
|
|
116
|
+
}}
|
|
117
|
+
{@const { tag, ...localRest } = token}
|
|
118
|
+
{@const htmlTag = tag as keyof typeof Html}
|
|
109
119
|
{#if htmlTag in Html}
|
|
110
120
|
{@const HtmlComponent = Html[htmlTag]}
|
|
111
|
-
<HtmlComponent {...
|
|
112
|
-
{#if
|
|
121
|
+
<HtmlComponent {...token}>
|
|
122
|
+
{#if token.tokens?.length}
|
|
113
123
|
<Parser
|
|
114
|
-
tokens={
|
|
124
|
+
tokens={token.tokens}
|
|
115
125
|
{renderers}
|
|
116
126
|
{...localRest}
|
|
117
127
|
/>
|
package/dist/Parser.svelte.d.ts
CHANGED
|
@@ -33,19 +33,27 @@
|
|
|
33
33
|
* - Implements special logic for tables, lists, and HTML content
|
|
34
34
|
* - Handles component prop spreading carefully to avoid conflicts
|
|
35
35
|
* - Maintains type safety through TypeScript interfaces
|
|
36
|
+
* - HTML token handling in table cells uses type assertions for better type safety
|
|
37
|
+
* - Table cell HTML content is processed with proper token nesting and attribute preservation
|
|
38
|
+
* - Improved HTML component rendering with proper type checking for tag properties
|
|
39
|
+
* - Added support for nested markdown within HTML table cells (see test at lines 311-343 in SvelteMarkdown.test.ts)
|
|
40
|
+
* - Token cleanup utilities handle complex nested structures (see lines 105-127 in token-cleanup.test.ts)
|
|
41
|
+
* - HTML parsing maintains proper structure for both simple and complex nested elements
|
|
36
42
|
*
|
|
37
43
|
*/
|
|
38
44
|
import Parser from './Parser.svelte';
|
|
39
45
|
import type { Renderers, Token, TokensList, Tokens } from './utils/markdown-parser.js';
|
|
40
|
-
|
|
46
|
+
interface Props {
|
|
41
47
|
type?: string;
|
|
42
48
|
tokens?: Token[] | TokensList;
|
|
43
49
|
header?: Tokens.TableCell[];
|
|
44
50
|
rows?: Tokens.TableCell[][];
|
|
45
51
|
ordered?: boolean;
|
|
46
52
|
renderers: Renderers;
|
|
47
|
-
}
|
|
53
|
+
}
|
|
54
|
+
type $$ComponentProps = Props & {
|
|
48
55
|
[key: string]: unknown;
|
|
49
|
-
}
|
|
56
|
+
};
|
|
57
|
+
declare const Parser: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
50
58
|
type Parser = ReturnType<typeof Parser>;
|
|
51
59
|
export default Parser;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const A: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type A = ReturnType<typeof A>;
|
|
7
8
|
export default A;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const Abbr: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type Abbr = ReturnType<typeof Abbr>;
|
|
7
8
|
export default Abbr;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const Address: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type Address = ReturnType<typeof Address>;
|
|
7
8
|
export default Address;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const Article: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type Article = ReturnType<typeof Article>;
|
|
7
8
|
export default Article;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const Aside: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type Aside = ReturnType<typeof Aside>;
|
|
7
8
|
export default Aside;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const Audio: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type Audio = ReturnType<typeof Audio>;
|
|
7
8
|
export default Audio;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const B: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type B = ReturnType<typeof B>;
|
|
7
8
|
export default B;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const Bdi: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type Bdi = ReturnType<typeof Bdi>;
|
|
7
8
|
export default Bdi;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const Bdo: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type Bdo = ReturnType<typeof Bdo>;
|
|
7
8
|
export default Bdo;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const Blockquote: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type Blockquote = ReturnType<typeof Blockquote>;
|
|
7
8
|
export default Blockquote;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
interface Props {
|
|
3
3
|
children?: Snippet;
|
|
4
4
|
attributes?: Record<string, any>;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const Button: import("svelte").Component<Props, {}, "">;
|
|
6
7
|
type Button = ReturnType<typeof Button>;
|
|
7
8
|
export default Button;
|