The RichText components provide safe HTML rendering with built-in XSS protection and Markdown support.
Renders rich HTML content with optional sanitization for XSS protection.
@Composable
fun RichText(
htmlContent: String,
modifier: Modifier = Modifier(),
sanitize: Boolean = true
)
Parameters:
htmlContent - The HTML content to rendermodifier - The modifier to apply to this componentsanitize - Whether to sanitize the HTML content (default: true)Example:
RichText(
htmlContent = """
<h1>Welcome to Our App</h1>
<p>This is <strong>bold</strong> and <em>italic</em> text.</p>
<ul>
<li>Feature 1</li>
<li>Feature 2</li>
<li>Feature 3</li>
</ul>
""",
sanitize = true
)
Renders trusted HTML content with minimal sanitization. Use this for content you control and trust.
@Composable
fun Html(
htmlContent: String,
modifier: Modifier = Modifier()
)
Parameters:
htmlContent - The trusted HTML content to rendermodifier - The modifier to apply to this componentExample:
Html(
htmlContent = """
<div class="custom-widget">
<script src="https://trusted-widget.com/widget.js"></script>
<div id="widget-container"></div>
</div>
"""
)
Renders Markdown content by converting it to safe HTML.
@Composable
fun Markdown(
markdownContent: String,
modifier: Modifier = Modifier()
)
Parameters:
markdownContent - The Markdown content to rendermodifier - The modifier to apply to this componentExample:
Markdown(
markdownContent = """
# Getting Started
Welcome to our **amazing** application!
## Features
- Easy to use
- *Powerful* functionality
- Great performance
[Learn more](https://example.com)
```kotlin
fun hello() {
println("Hello, World!")
}
```
"""
)
The RichText component includes built-in XSS protection when sanitize = true (default).
The following HTML elements are preserved during sanitization:
<p>, <span>, <div>, <br><h1>, <h2>, <h3>, <h4>, <h5>, <h6><strong>, <b>, <em>, <i>, <u><ul>, <ol>, <li><a> (with safe href attributes)<code>, <pre><blockquote><table>, <thead>, <tbody>, <tr>, <th>, <td>The following dangerous elements are removed:
<script>, <noscript><form>, <input>, <button>, <textarea>, <select><object>, <embed>, <applet>, <iframe><meta>, <link>, <style> (use GlobalStyle instead)The following dangerous attributes are removed:
onclick, onload, onerror, onmouseover, etc.href="javascript:...", src="javascript:..."The Markdown component supports a subset of CommonMark:
# H1 Header
## H2 Header
### H3 Header
#### H4 Header
##### H5 Header
###### H6 Header
**Bold text**
*Italic text*
`Inline code`
- Unordered list item 1
- Unordered list item 2
1. Ordered list item 1
2. Ordered list item 2
[Link text](https://example.com)
[Link with title](https://example.com "Link title")
```kotlin
fun hello() {
println("Hello, World!")
}
### Blockquotes
```markdown
> This is a blockquote
> It can span multiple lines
@Composable
fun UserComment(comment: UserCommentData) {
RichText(
htmlContent = comment.htmlContent,
sanitize = true // Always true for user content
)
}
@Composable
fun AdminDashboard() {
// Only use Html for content you control
Html(
htmlContent = """
<div class="admin-widget">
<iframe src="/admin/analytics" width="100%" height="400"></iframe>
</div>
"""
)
}
@Composable
fun SafeRichText(content: String) {
val sanitizedContent = content
.replace(Regex("href=[\"'](?!https?://)[^\"']*[\"']"), "href=\"#\"")
RichText(
htmlContent = sanitizedContent,
sanitize = true
)
}
@Composable
fun StyledArticle() {
GlobalStyle("""
.article-content {
font-family: Georgia, serif;
line-height: 1.6;
color: #333;
}
.article-content h1 {
color: #2c3e50;
border-bottom: 2px solid #3498db;
padding-bottom: 0.5rem;
}
.article-content h2 {
color: #34495e;
margin-top: 2rem;
}
.article-content p {
margin-bottom: 1rem;
}
.article-content code {
background: #f8f9fa;
padding: 0.125rem 0.25rem;
border-radius: 0.25rem;
font-family: 'Monaco', monospace;
}
.article-content blockquote {
border-left: 4px solid #3498db;
padding-left: 1rem;
margin: 1rem 0;
font-style: italic;
color: #7f8c8d;
}
""")
RichText(
htmlContent = """
<div class="article-content">
<h1>Article Title</h1>
<p>This is the article content with <code>inline code</code>.</p>
<blockquote>
This is a quote from someone important.
</blockquote>
<h2>Section Title</h2>
<p>More content here...</p>
</div>
""",
sanitize = true
)
}
@Composable
fun ModifiedRichText() {
RichText(
htmlContent = "<p>Styled content</p>",
modifier = Modifier()
.style("max-width", "800px")
.style("margin", "0 auto")
.style("padding", "2rem")
.style("background", "#f8f9fa")
.style("border-radius", "8px")
.style("box-shadow", "0 2px 4px rgba(0,0,0,0.1)")
)
}
@Composable
fun BlogPost(post: BlogPostData) {
Column {
// Title
Text(
text = post.title,
modifier = Modifier().style("font-size", "2rem").style("font-weight", "bold")
)
// Metadata
Text(
text = "By ${post.author} on ${post.date}",
modifier = Modifier().style("color", "#666").style("margin-bottom", "1rem")
)
// Content
RichText(
htmlContent = post.htmlContent,
sanitize = true,
modifier = Modifier().style("line-height", "1.6")
)
// Tags
Row {
post.tags.forEach { tag ->
Text(
text = "#$tag",
modifier = Modifier()
.style("background", "#e9ecef")
.style("padding", "0.25rem 0.5rem")
.style("border-radius", "1rem")
.style("font-size", "0.875rem")
.style("margin-right", "0.5rem")
)
}
}
}
}
@Composable
fun DocumentationViewer(markdownContent: String) {
GlobalStyle("""
.docs {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
.docs h1, .docs h2, .docs h3 {
margin-top: 2rem;
margin-bottom: 1rem;
}
.docs pre {
background: #f6f8fa;
padding: 1rem;
border-radius: 6px;
overflow-x: auto;
}
.docs code {
background: #f6f8fa;
padding: 0.125rem 0.25rem;
border-radius: 3px;
font-size: 0.875rem;
}
""")
Markdown(
markdownContent = markdownContent,
modifier = Modifier().style("class", "docs")
)
}
@Composable
fun OptimizedRichText(content: String) {
val sanitizedContent = remember(content) {
// Cache sanitized content
sanitizeHtml(content)
}
Html(htmlContent = sanitizedContent)
}