Skip to content

Commit

Permalink
feat: support rendering from pre-processed tokens (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
Abacus Lever authored Jul 21, 2022
1 parent aa4bc51 commit 00301f3
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 6 deletions.
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,36 @@ Just like with React Markdown, this package doesn't use `{@html ...}` unless you

The SvelteMarkdown component accepts the following options:

- `source` - _string_ The Markdown source to be parsed.
- `source` - _string_ or _array_ The Markdown source to be parsed, or an array of tokens to be rendered directly.
- `renderers` - _object (optional)_ An object where the keys represent a node type 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`.
- `options` - _object (optional)_ An object containing [options for Marked](https://marked.js.org/using_advanced#options)

## Rendering From Tokens

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:

```html
<script>
import SvelteMarkdown from 'svelte-markdown'
import { marked } from 'marked'
const tokens = marked.lexer('this is an **example**')
marked.walkTokens(tokens, token=> {
if (token.type == 'strong') token.type = 'em'
token.raw = token.raw.toUpperCase()
})
</script>

<SvelteMarkdown source={tokens} />
```

This will render the following:

```html
<p>THIS IS AN <em>EXAMPLE</em></p>
```

## Events

A `parsed` event will be fired when the final tokens have been calculated, allowing you to access the raw token array if needed for things like generating Table of Contents from headings.
Expand Down
9 changes: 6 additions & 3 deletions src/SvelteMarkdown.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { Lexer, Slugger, defaultOptions, defaultRenderers } from './markdown-parser'
import { key } from './context'
export let source = ''
export let source = []
export let renderers = {}
export let options = {}
export let isInline = false
Expand All @@ -15,9 +15,12 @@
let lexer;
let mounted;
$: preprocessed = Array.isArray(source)
$: slugger = source ? new Slugger : undefined
$: combinedOptions = { ...defaultOptions, ...options }
$: {
$: if (preprocessed) {
tokens = source
} else {
lexer = new Lexer(combinedOptions)
tokens = isInline ? lexer.inlineTokens(source) : lexer.lex(source)
Expand All @@ -31,7 +34,7 @@
slug: (val) => slugger ? slugger.slug(val) : '',
getOptions: () => combinedOptions
})
$: mounted && dispatch('parsed', { tokens })
$: mounted && !preprocessed && dispatch('parsed', { tokens })
onMount(() => {
mounted = true
Expand Down
31 changes: 31 additions & 0 deletions tests/svelte-markdown.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import '@testing-library/jest-dom/extend-expect'

import { render, screen } from '@testing-library/svelte'

import SvelteMarkdown from '../src/SvelteMarkdown.svelte'

describe('testing initialization', () => {
beforeAll(() => {
console.warn = jest.fn()
})

test('accepts pre-processed tokens as source', () => {
render(SvelteMarkdown, { source: [{
type: 'paragraph',
raw: 'this is an **example**',
text: 'this is an **example**',
tokens: [
{ type: 'text', raw: 'this is an ', text: 'this is an ' },
{ type: 'strong',
raw: '**example**',
text: 'example',
tokens: [ { type: 'text', raw: 'example', text: 'example' } ],
},
],
}]})

const element = screen.getByText('example')
expect(element).toBeInTheDocument()
expect(element).toContainHTML('<strong>example</strong>')
})
})
4 changes: 2 additions & 2 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ type Renderers = {
}
type Props = {
/**
* The Markdown source to be parsed.
* The Markdown source to be parsed, or an array of tokens to be rendered directly.
*/
source: string
source: string|TokensList

/**
* An object where the keys represent a node type and the value is a Svelte component. This
Expand Down

0 comments on commit 00301f3

Please sign in to comment.