| name | markdown-content |
| description | Work with markdown content system, MarkdownContent models, and cotton components in markdown. Use when working with content models or adding markdown components. |
| allowed-tools | Read, Grep, Glob |
Markdown Content System
When to Use This Skill
Use this Skill when:
- Working with content models - Topic, Activity, Course, Form, FormContent
- Rendering markdown - Using rendered_content() or {% markdown %}
- Adding markdown components - Creating cotton components for content
- User mentions "markdown", "content", "rendered_content"
- Debugging content rendering - Issues with markdown or sanitization
- Modifying MARKDOWN_ALLOWED_TAGS - Adding new component support
Models with Markdown Content
These models extend MarkdownContent and have a content TextField:
- Topic, Activity, Course, Form, FormContent -
freedom_ls/content_engine/models.py
Rendering
html = topic.rendered_content()
{{ topic.rendered_content }}
What happens:
- Markdown -> HTML (extensions: fenced_code, mdx_headdown, tables)
- Sanitize with nh3 (only
MARKDOWN_ALLOWED_TAGS allowed)
- Render Cotton components
- Return safe HTML
Cotton Components in Markdown
Location: freedom_ls/content_engine/templates/cotton/
Available: callout.html, youtube.html, picture.html, content-link.html
Usage:
<c-callout level="info" title="Note">Content here</c-callout>
<c-youtube video_id="abc123"></c-youtube>
<c-picture src="images/file.svg" alt="Alt text"></c-picture>
<c-content-link path="other.md">link</c-content-link>
Adding New Components
- Create
freedom_ls/content_engine/templates/cotton/<name>.html
- Register in
config/settings_base.py:
MARKDOWN_ALLOWED_TAGS = {
"c-name": {"attr1", "attr2"},
}
- Use in markdown:
<c-name attr1="value"></c-name>
Notes
- H1 becomes H2 (mdx_headdown prevents title conflicts)
- Relative paths resolved via
calculate_path_from_root()
- Template tag:
{% markdown text %} renders standalone markdown