Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to keep all attributes as strings #605

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/shaggy-dolls-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"markdown-to-jsx": patch
---

Add option to keep all attributes as strings
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ The most lightweight, customizable React markdown component.
- [options.slugify](#optionsslugify)
- [options.namedCodesToUnicode](#optionsnamedcodestounicode)
- [options.disableParsingRawHTML](#optionsdisableparsingrawhtml)
- [options.convertBooleans](#optionsconvertbooleans)
- [Syntax highlighting](#syntax-highlighting)
- [Getting the smallest possible bundle size](#getting-the-smallest-possible-bundle-size)
- [Usage with Preact](#usage-with-preact)
Expand Down Expand Up @@ -525,6 +526,28 @@ compiler('This text has <span>html</span> in it but it won't be rendered', { dis
<span>This text has &lt;span&gt;html&lt;/span&gt; in it but it won't be rendered</span>
```

#### options.convertBooleans

By default, boolean attribute values are converted to boolean primitives. To disable this behavior, set convertBooleans to false

```jsx
const Capitalize = ({ value }: { value: string }) => {
return <>{value.toUpperCase()}</>
}

<Markdown options={{ convertBooleans: false, overrides: { Capitalize } }}>
<Capitalize value="true" />
</Markdown>;

// or

compiler('<Capitalize value="true" />', { convertBooleans: false, overrides: { Capitalize } });

// renders:
<>TRUE</>

```

### Syntax highlighting

When using [fenced code blocks](https://www.markdownguide.org/extended-syntax/#syntax-highlighting) with language annotation, that language will be added to the `<code>` element as `class="lang-${language}"`. For best results, you can use `options.overrides` to provide an appropriate syntax highlighting integration like this one using `highlight.js`:
Expand Down
27 changes: 27 additions & 0 deletions index.compiler.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4100,6 +4100,33 @@ describe('footnotes', () => {
})
})

describe('options.convertBooleans', () => {
const Capitalize = ({ value }: { value: string }) => {
return <>{value.toUpperCase()}</>
}

it('should convert boolean attribute values to boolean primitives by default', () => {
expect(() =>
render(
compiler('<Capitalize value="true"/>', {
overrides: { Capitalize },
})
)
).toThrowErrorMatchingInlineSnapshot(
`"value.toUpperCase is not a function"`
)
})
it('should leave attribute values of true/false as strings when convertBooleans is disabled ', () => {
render(
compiler('<Capitalize value="true"/>', {
convertBooleans: false,
overrides: { Capitalize },
})
)
expect(root.innerHTML).toMatchInlineSnapshot(`"TRUE"`)
})
})

describe('options.namedCodesToUnicode', () => {
// &amp; &gt; &lt; are already replaced by default
const content =
Expand Down
23 changes: 17 additions & 6 deletions index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,8 @@ function attributeValueToJSXPropValue(
tag: MarkdownToJSX.HTMLTags,
key: keyof React.AllHTMLAttributes<Element>,
value: string,
sanitizeUrlFn: MarkdownToJSX.Options['sanitizer']
sanitizeUrlFn: MarkdownToJSX.Options['sanitizer'],
convertBooleans: boolean
): any {
if (key === 'style') {
return value.split(/;\s?/).reduce(function (styles, kvPair) {
Expand All @@ -758,10 +759,12 @@ function attributeValueToJSXPropValue(
value = value.slice(1, value.length - 1)
}

if (value === 'true') {
return true
} else if (value === 'false') {
return false
if (convertBooleans) {
if (value === 'true') {
return true
} else if (value === 'false') {
return false
}
}

return value
Expand Down Expand Up @@ -1147,6 +1150,7 @@ export function compiler(
: namedCodesToUnicode

options.createElement = options.createElement || React.createElement
options.convertBooleans = options.convertBooleans ?? true

// JSX custom pragma
// eslint-disable-next-line no-unused-vars
Expand Down Expand Up @@ -1252,7 +1256,8 @@ export function compiler(
tag,
key,
value,
options.sanitizer
options.sanitizer,
options.convertBooleans
))

if (
Expand Down Expand Up @@ -2294,6 +2299,12 @@ export namespace MarkdownToJSX {
}

export type Options = Partial<{
/**
* Optionally convert boolean string attributes to boolean in JSX.
* Enabled by default
*/
convertBooleans: boolean

/**
* Ultimate control over the output of all rendered JSX.
*/
Expand Down
Loading