Skip to content
Draft
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
67 changes: 52 additions & 15 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Project Overview

MkDocs Quiz is a plugin for MkDocs that creates interactive quizzes directly in markdown documentation. It processes custom `<?quiz?>` tags in markdown files and converts them to interactive HTML/JS quiz elements.
MkDocs Quiz is a plugin for MkDocs that creates interactive quizzes directly in markdown documentation. It processes custom `<quiz>` tags in markdown files and converts them to interactive HTML/JS quiz elements. Supports both multiple-choice and fill-in-the-blank question types.

## Architecture

Expand All @@ -19,6 +19,26 @@ This is a MkDocs plugin that hooks into the MkDocs build pipeline:
2. `on_page_markdown()` - Processes markdown to convert quiz tags to placeholders and stores quiz HTML
3. `on_page_content()` - Replaces placeholders with actual quiz HTML and injects CSS/JS assets

### Quiz Types

The plugin supports two types of quizzes:

1. **Multiple-choice quizzes**: Use checkbox syntax (`- [x]` for correct, `- [ ]` for incorrect)
- Single correct answer → radio buttons
- Multiple correct answers → checkboxes
- Auto-submit option for single-choice (default: enabled)

2. **Fill-in-the-blank quizzes**: Use double square brackets (`[[answer]]`) to mark blanks
- Supports single or multiple blanks in one question
- Case-insensitive validation (trimmed whitespace)
- Markdown formatting works around blanks
- Always requires explicit submit button

The plugin automatically detects which type based on the content:

- If `[[...]]` patterns are found → fill-in-the-blank
- Otherwise → multiple-choice (requires checkbox items)

### Quiz Processing Flow

1. **Code block masking** (`_mask_code_blocks`):
Expand All @@ -28,20 +48,30 @@ This is a MkDocs plugin that hooks into the MkDocs build pipeline:
2. **Markdown parsing** (`on_page_markdown`):
- Regex pattern `<quiz>(.*?)</quiz>` finds quiz blocks
- Each quiz is passed to `_process_quiz()` method
- Quiz syntax uses markdown checkbox lists: `- [x]` for correct answers, `- [ ]` for incorrect
- Question is everything before the first checkbox answer
- Content section (optional) is everything after the last answer
- Single correct answer = radio buttons; multiple correct = checkboxes
- `_process_quiz()` detects quiz type using `_is_fill_in_blank_quiz()`
- **Multiple-choice**: Uses checkbox lists (`- [x]` correct, `- [ ]` incorrect)
- Question is everything before the first checkbox answer
- Content section (optional) is everything after the last answer
- Single correct answer = radio buttons; multiple correct = checkboxes
- **Fill-in-the-blank**: Uses `[[answer]]` patterns
- Question text with blanks replaced by text inputs
- Correct answers stored in `data-answer` attributes (HTML-escaped)
- Content section separated by horizontal rule (`---`)
- Quizzes replaced with placeholders (`<!-- MKDOCS_QUIZ_PLACEHOLDER_N -->`) in markdown

3. **HTML generation** (`_process_quiz`):
- Parses quiz lines to extract question, answers, and content
- Converts question and answers from markdown to HTML using `markdown_converter`
- Uses the same `markdown_extensions` configured in `mkdocs.yml` for conversion
- This enables features like `pymdownx.superfences`, `pymdownx.highlight`, admonitions, etc.
- Generates form HTML with proper input types (radio/checkbox)
- Adds `correct` attribute to correct answers (used by JS)
- Content section is hidden until quiz is answered
3. **HTML generation** (`_process_quiz` and `_process_fill_in_blank_quiz`):
- **Multiple-choice**: Parses quiz lines to extract question, answers, and content
- Converts question and answers from markdown to HTML using `markdown_converter`
- Uses the same `markdown_extensions` configured in `mkdocs.yml` for conversion
- This enables features like `pymdownx.superfences`, `pymdownx.highlight`, admonitions, etc.
- Generates form HTML with proper input types (radio/checkbox)
- Adds `correct` attribute to correct answers (used by JS)
- **Fill-in-the-blank**: Replaces `[[answer]]` with text inputs
- Uses HTML comment placeholders (`<!--BLANK_PLACEHOLDER_N-->`) during markdown conversion
- Replaces placeholders with `<input type="text" class="quiz-blank-input">`
- Stores correct answers in `data-answer` attributes (HTML-escaped)
- Adds `autocomplete="off"` to prevent browser autofill
- Content section is hidden until quiz is answered (both types)
- Each quiz gets unique ID for deep linking (`id="quiz-N"`)
- Quiz HTML is stored in `_quiz_storage` dict keyed by page path

Expand All @@ -63,11 +93,18 @@ The [quiz.js](mkdocs_quiz/js/quiz.js) file:
- Creates progress sidebar automatically when multiple quizzes exist
- Dispatches `quizProgressUpdate` custom events for integration
- **Form handling**: Attaches submit handlers to all `.quiz` forms on page load
- **Validation**: Validates selected answers against `[correct]` attribute
- **Validation**:
- **Multiple-choice**: Validates selected answers against `[correct]` attribute
- **Fill-in-the-blank**: Compares input values with `data-answer` attributes
- Case-insensitive comparison using `normalizeAnswer()` (trim + lowercase)
- All blanks must be correct for quiz to pass
- **Visual feedback**: Shows/hides content section, adds `.correct` and `.wrong` classes
- **Auto-submit**: If enabled and single-choice (radio), submits on selection change
- **Fill-in-the-blank**: Wrong answers show correct answer as placeholder if `show_correct` enabled
- **Auto-submit**: If enabled and single-choice (radio), submits on selection change (multiple-choice only)
- **Persistence**: Restores quiz state from localStorage on page load
- **Fill-in-the-blank**: Saves user input values in `selectedValues` array
- **Reset functionality**: "Try Again" button to reset individual quizzes (if not disabled after submit)
- **Fill-in-the-blank**: Clears input values and removes styling
- **Helper**: `resetFieldset()` clears previous styling before re-validation

### Configuration Options
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ A modern MkDocs plugin to create interactive quizzes directly in your markdown d
## Features

- ✨ **Simple markdown syntax** - Create quizzes using GitHub-flavored markdown checkboxes
- 🎯 **Single and multiple choice** - One correct answer = radio buttons, multiple = checkboxes
- 🎯 **Multiple quiz types** - Single choice (radio), multiple choice (checkboxes), and fill-in-the-blank
- ⚡ **Instant feedback** - Visual indicators show correct/incorrect answers
- 📊 **Progress tracking** - Automatic progress sidebar and results panel, with confetti 🎉
- 💾 **Results saved** - Answers are saved to the browser's local storage
Expand Down
102 changes: 102 additions & 0 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,108 @@ The content section is optional:
</quiz>
```

## Fill-in-the-Blank Quizzes

Fill-in-the-blank quizzes allow users to type answers into text fields. These are perfect for recall-based questions where users need to remember specific terms, values, or concepts.

### Single Blank

Use double square brackets `[[answer]]` to create a blank:

=== "Example"

<quiz>
The capital of France is [[Paris]].
</quiz>

=== "Syntax"

```markdown
<quiz>
The capital of France is [[Paris]].
</quiz>
```

### Multiple Blanks

You can include multiple blanks in a single question:

=== "Example"

<quiz>
Python was created by [[Guido van Rossum]] and first released in [[1991]].
</quiz>

=== "Syntax"

```markdown
<quiz>
Python was created by [[Guido van Rossum]] and first released in [[1991]].
</quiz>
```

### Fill-in-the-Blank with Content

To add optional content (explanations, additional information) to fill-in-the-blank quizzes, use a horizontal rule `---` to separate the question from the content:

=== "Example"

<quiz>
2 + 2 = [[4]]

---
That's correct! Basic arithmetic is fundamental to programming.
</quiz>

=== "Syntax"

```markdown
<quiz>
2 + 2 = [[4]]

---
That's correct! Basic arithmetic is fundamental to programming.
</quiz>
```

### Complex Fill-in-the-Blank

Fill-in-the-blank quizzes support markdown formatting around the blanks and rich content after the horizontal rule:

=== "Example"

<quiz>
Some markdown:

The answer is [[foo]].

Another answer is [[bar]].

---
This *content* is only shown after answering.

It can have **bold**, `code`, and other markdown formatting.
</quiz>

=== "Syntax"

```markdown
<quiz>
Some markdown:

The answer is [[foo]].

Another answer is [[bar]].

---
This *content* is only shown after answering.

It can have **bold**, `code`, and other markdown formatting.
</quiz>
```

**Note:** Answers are case-insensitive and whitespace is trimmed. So "Paris", "paris", and " PARIS " are all accepted.

## Answer Syntax Variations

All of these checkbox formats are supported:
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ A modern MkDocs plugin to create interactive quizzes directly in your markdown d
## Features

- ✨ **Simple markdown syntax** - Create quizzes using GitHub-flavored markdown checkboxes
- 🎯 **Single and multiple choice** - One correct answer = radio buttons, multiple = checkboxes
- 🎯 **Multiple quiz types** - Single choice (radio), multiple choice (checkboxes), and fill-in-the-blank
- ⚡ **Instant feedback** - Visual indicators show correct/incorrect answers
- 📊 **Progress tracking** - Automatic progress sidebar and results panel, with confetti :tada:
- 💾 **Results saved** - Answers are saved to the browser's local storage
Expand Down
59 changes: 59 additions & 0 deletions mkdocs_quiz/css/quiz.css
Original file line number Diff line number Diff line change
Expand Up @@ -357,3 +357,62 @@ input[type="radio"].wrong {
color: #f44336;
background-color: rgba(244, 67, 54, 0.15);
}

/* Fill-in-the-blank quiz styles */
.quiz-blank-input {
border: none;
border-bottom: 2px solid var(--md-default-fg-color--light, #999);
background-color: transparent;
padding: 0.2rem 0.5rem;
font-size: inherit;
font-family: inherit;
color: var(--md-default-fg-color);
transition:
border-color 0.2s,
background-color 0.2s;
min-width: 100px;
outline: none;
}

.quiz-blank-input:focus {
border-bottom-color: var(--md-primary-fg-color, #1976d2);
background-color: var(--md-default-bg-color--light, rgba(0, 0, 0, 0.02));
}

.quiz-blank-input.correct {
border-bottom-color: #198754;
background-color: rgba(25, 135, 84, 0.1);
color: #198754;
}

.quiz-blank-input.wrong {
border-bottom-color: #dc3545;
background-color: rgba(220, 53, 69, 0.1);
color: #dc3545;
}

.quiz-blank-input:disabled {
opacity: 0.7;
cursor: not-allowed;
}

/* Dark mode adjustments for fill-in-the-blank */
[data-md-color-scheme="slate"] .quiz-blank-input {
border-bottom-color: rgba(255, 255, 255, 0.3);
}

[data-md-color-scheme="slate"] .quiz-blank-input:focus {
background-color: rgba(255, 255, 255, 0.05);
}

[data-md-color-scheme="slate"] .quiz-blank-input.correct {
border-bottom-color: #4caf50;
background-color: rgba(76, 175, 80, 0.15);
color: #4caf50;
}

[data-md-color-scheme="slate"] .quiz-blank-input.wrong {
border-bottom-color: #f44336;
background-color: rgba(244, 67, 54, 0.15);
color: #f44336;
}
Loading