Claude
Skills
Sign in
Back

dailytags

Included with Lifetime
$97 forever

Comprehensive guide for using DailyTags - a Jetpack Compose markdown library that supports custom tags. Use this skill when working with markdown rendering, custom markup, rich text formatting in Compose, or creating pattern-based text parsers for Android applications. DailyTags parses text into nodes styled with AnnotatedString, providing a WebView-free solution for rendering markdown and HTML with full customization support.

Web Dev

What this skill does


# DailyTags Skill

## Overview

DailyTags is a flexible markdown library for Jetpack Compose that parses markup into rich text using AnnotatedString. It's lightweight (<50kb), fast, extensible, and requires no WebView.

**Key Capabilities:**
- ✅ Markdown parsing with built-in rules
- ✅ HTML support with built-in rules  
- ✅ Custom tag/markup creation via regex patterns
- ✅ Full styling control (SpanStyle, ParagraphStyle)
- ✅ Node-based parsing architecture
- ✅ Native Compose integration

**Important Limitation:**
- ⚠️ **Text content only** - Cannot render images, tables, checkboxes, or custom UI elements
- For non-text elements, use hybrid approach with regular Compose components

## Installation

### Gradle Setup

Add JitPack repository to your root `build.gradle`:

```gradle
allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}
```

Add dependency to your module `build.gradle`:

```gradle
dependencies {
    implementation "com.github.DmytroShuba:DailyTags:1.0.0"
}
```

**Current Version:** 1.0.0 (February 2022)  
**Min API Level:** 23+  
**License:** MIT

## Core Architecture

### Parsing Flow

```
Source Text → Rules → Parser → Nodes → Render → AnnotatedString → Text Composable
```

### Key Components

1. **SimpleMarkupParser**: Main parsing engine that processes text using rules
2. **Rules**: Pattern-based definitions for how to extract and style content
3. **Nodes**: Internal representation of parsed elements
4. **AnnotatedString**: Compose's rich text format (final output)

## Basic Usage

### 1. Simple Markdown Rendering

```kotlin
import com.dmytroshuba.dailytags.markdown.rules.MarkdownRules
import com.dmytroshuba.dailytags.core.simple.SimpleMarkupParser
import com.dmytroshuba.dailytags.core.simple.render
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable

@Composable
fun MarkdownText(source: String) {
    val parser = SimpleMarkupParser()
    val rules = MarkdownRules.toList()
    
    val content = parser
        .parse(source, rules)
        .render()
        .toAnnotatedString()
    
    Text(text = content)
}

// Usage
MarkdownText("**Bold text** and *italic text*")
```

### 2. Markdown + HTML Combined

```kotlin
import com.dmytroshuba.dailytags.markdown.rules.HtmlRules

@Composable
fun RichText(source: String) {
    val parser = SimpleMarkupParser()
    val rules = MarkdownRules.toList() + HtmlRules.toList()
    
    val content = parser
        .parse(source, rules)
        .render()
        .toAnnotatedString()
    
    Text(text = content)
}

// Usage
RichText("""
    <b>HTML bold</b> and **Markdown bold**
    <i>HTML italic</i> and *Markdown italic*
""")
```

## Custom Tags & Markup

### Creating Custom Rules

#### Step 1: Define Pattern

Use Java's `Pattern` class to create regex patterns:

```kotlin
import java.util.regex.Pattern

// Highlight tag: <hl-blue>text</hl-blue>
val PATTERN_HIGHLIGHT_BLUE = Pattern.compile("^<hl-blue>([\\s\\S]+?)<\\/hl-blue>")

// Spoiler tag: ||hidden text||
val PATTERN_SPOILER = Pattern.compile("^\\|\\|([\\s\\S]+?)\\|\\|")

// Mention tag: @username
val PATTERN_MENTION = Pattern.compile("^@([a-zA-Z0-9_]+)")

// Code language tag: ```kotlin code ```
val PATTERN_CODE_BLOCK = Pattern.compile("^```(\\w+)\\n([\\s\\S]+?)```")
```

#### Step 2: Convert Pattern to Rule

Use the `toRule()` extension function:

```kotlin
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import com.dmytroshuba.dailytags.core.simple.toRule

// Basic styling
val blueHighlightRule = PATTERN_HIGHLIGHT_BLUE.toRule(
    spanStyle = SpanStyle(
        color = Color.Blue,
        background = Color.Blue.copy(alpha = 0.1f)
    )
)

// Complex styling with multiple properties
val spoilerRule = PATTERN_SPOILER.toRule(
    spanStyle = SpanStyle(
        color = Color.Black,
        background = Color.DarkGray
    )
)

val mentionRule = PATTERN_MENTION.toRule(
    spanStyle = SpanStyle(
        color = Color(0xFF1DA1F2), // Twitter blue
        fontWeight = FontWeight.Bold
    )
)
```

#### Step 3: Use Custom Rules

```kotlin
@Composable
fun CustomMarkupText(source: String) {
    val parser = SimpleMarkupParser()
    
    // Combine built-in and custom rules
    val rules = MarkdownRules.toList() + listOf(
        blueHighlightRule,
        spoilerRule,
        mentionRule
    )
    
    val content = parser
        .parse(source, rules)
        .render()
        .toAnnotatedString()
    
    Text(text = content)
}

// Usage
CustomMarkupText("""
    Regular text with <hl-blue>blue highlight</hl-blue>
    This is a ||spoiler||
    Hey @username, check this out!
""")
```

## Advanced Patterns

### 1. Paragraph Styling

```kotlin
import androidx.compose.ui.text.ParagraphStyle
import androidx.compose.ui.unit.sp
import androidx.compose.ui.text.style.TextIndent

val PATTERN_QUOTE = Pattern.compile("^> (.+)$", Pattern.MULTILINE)

val quoteRule = PATTERN_QUOTE.toRule(
    spanStyle = SpanStyle(
        color = Color.Gray,
        fontStyle = FontStyle.Italic
    ),
    paragraphStyle = ParagraphStyle(
        textIndent = TextIndent(firstLine = 16.sp),
        lineHeight = 20.sp
    )
)
```

### 2. Multi-Group Patterns

Extract and style different groups separately:

```kotlin
// Pattern with capturing groups
val PATTERN_LINK = Pattern.compile("^\\[([^\\]]+)\\]\\(([^)]+)\\)")

// Custom rendering with different styles for text and URL
val linkRule = PATTERN_LINK.toRule(
    spanStyle = SpanStyle(
        color = Color.Blue,
        textDecoration = TextDecoration.Underline
    )
)
```

### 3. Nested Rules

Rules are processed in order, allowing nested markup:

```kotlin
val rules = listOf(
    // Process outer tags first
    blockquoteRule,
    // Then inner formatting
    boldRule,
    italicRule,
    codeRule
)
```

### 4. Conditional Styling

Create rules that apply different styles based on content:

```kotlin
val PATTERN_TAG = Pattern.compile("^#(\\w+)")

fun createTagRule(color: Color) = PATTERN_TAG.toRule(
    spanStyle = SpanStyle(
        color = color,
        fontWeight = FontWeight.Medium,
        background = color.copy(alpha = 0.1f)
    )
)

// Usage with different colors
val tagRules = listOf(
    createTagRule(Color.Red),
    createTagRule(Color.Blue),
    createTagRule(Color.Green)
)
```

## Important Limitations

**DailyTags works with TEXT CONTENT ONLY.** It cannot render:

- ❌ Images (including `![alt](url)` and `<img>` tags)
- ❌ Tables
- ❌ Checkboxes / Task lists
- ❌ Custom UI elements
- ❌ Embedded media (video, audio)
- ❌ Interactive widgets

**What this means:**
- Image syntax like `![Alt text](url)` will be parsed but NOT display an image
- Table markdown will be treated as plain text
- Checkbox syntax `- [ ]` will render as text, not interactive checkboxes
- Only text styling (bold, italic, color, etc.) is supported

**For these features, you need to:**
- Use regular Compose Image() composables separately
- Build custom UI components outside DailyTags
- Consider hybrid approaches (DailyTags for text, Compose for UI elements)

## Supported Markdown Features

### Text Formatting

- **Bold**: `**text**` or `__text__`
- *Italic*: `*text*` or `_text_`
- ~~Strikethrough~~: `~~text~~`
- `Inline code`: `` `code` ``
- Combined: `***bold italic***`

### Headings

```markdown
# H1 Heading
## H2 Heading
### H3 Heading
#### H4 Heading
##### H5 Heading
###### H6 Heading
```

### Lists

```markdown
- Unordered list item 1
- Unordered list item 2
  - Nested item

1. Ordered list item 1
2. Ordered list item 2
   1. Nested numbered item
```

### Links and Images (Text Only)

**Links:**
```markdown
[Link text](https://example.com)
```
Note: Links are styled but not clickable by default. Use ClickableText for interactivity.

**Images:**
```markdown
![Alt text](https://example.com/image.jpg)
```
⚠️ **Important:** Image markdown is parsed as text only - no actual image rendering. You'll see the alt text,

Related in Web Dev