Skip to content
Merged
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
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,59 @@ This recursive function calculates factorials.

See `examples/two-column-examples.md` for comprehensive examples.

### Custom Column Widths

You can specify custom width percentages for two-column layouts to create asymmetric layouts:

````markdown
:::columns[70]
### Main Content (70%)

This column gets 70% of the width
|||

### Sidebar (30%)

This column gets the remaining 30%
:::
````

**Features:**
- Specify left column width as a percentage: `:::columns[width]`
- Right column automatically gets the remaining width (100 - left%)
- Width must be between 1 and 99
- Backward compatible: `:::columns` without width still creates 50/50 split
- Perfect for layouts with primary content and sidebars

**Common use cases:**
- **70/30 split**: Wide main content with narrow sidebar for notes or links
- **60/40 split**: Code reviews with implementation and review comments
- **30/70 split**: Quick stats or table of contents with detailed content

**Example - 70/30 Layout:**

````markdown
:::columns[70]
### Main Content (70%)

- Detailed explanations
- Code examples that need more width
- Main narrative
- Primary visuals

|||

### Sidebar (30%)

**Quick Notes:**
- Key points
- References
- Tips
:::
````

See `examples/features.md` for live examples of different column width configurations.

### Wide Slide Mode

For slides with wide tables or content that needs more horizontal space, use the `<!--SLIDE:wide-->` directive:
Expand Down Expand Up @@ -516,6 +569,7 @@ markdeck present examples/code-examples.md
- [x] PyPI distribution ✓
- [x] Multiple themes (dark/light/beige) ✓
- [x] Two-column layouts ✓
- [x] Custom column widths ✓
- [x] Wide slide mode ✓
- [ ] Slide transitions
- [ ] Media embedding improvements
Expand Down
26 changes: 26 additions & 0 deletions capture_screenshots.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,29 @@ async def capture_screenshots():
print("Capturing two-column layout (Code & Explanation)...")
await page.screenshot(path="screenshots/two_column_example.png")

# ===== Custom Column Width Screenshots =====
print("\n=== Capturing Custom Column Width Screenshots ===")

# Navigate to slide 32 (Custom Width Example: 30/70 Narrow Left)
print("Navigating to custom width example (30/70)...")
await page.goto("http://127.0.0.1:8888/")
await page.wait_for_selector(".slide-content", timeout=10000)
await asyncio.sleep(1)

for i in range(32):
await page.keyboard.press("ArrowRight")
await asyncio.sleep(0.2)

await asyncio.sleep(1)

# Screenshot 12: Custom column width 30/70
# Note: Using 70_30 filename but showing 30/70 slide per user request
print("Capturing custom column width (30/70 split)...")
await page.screenshot(path="screenshots/column_width_70_30.png")

# Keep the existing 30/70 screenshot (already generated)
# No need to regenerate - it's already correct

await browser.close()
print("\n✅ All screenshots captured successfully!")
print("\nScreenshots saved in: screenshots/")
Expand All @@ -165,6 +188,9 @@ async def capture_screenshots():
print(" - wide_slide_example.png")
print("\nTwo-Column Layout Screenshots:")
print(" - two_column_example.png")
print("\nCustom Column Width Screenshots:")
print(" - column_width_70_30.png")
print(" - column_width_30_70.png")


def backup_existing_screenshots(screenshots_dir: Path, backup_dir: Path) -> bool:
Expand Down
116 changes: 116 additions & 0 deletions examples/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,122 @@ graph TB

---

## Two-Column with Custom Width

You can now specify a percentage width for the first column using `:::columns[width]`:

```markdown
:::columns[70]
This column gets 70% of the width
|||
This column gets the remaining 30%
:::
```

The width must be between 1 and 99.

---

## Custom Width Example: 70/30 Split

:::columns[70]
### Main Content (70%)

This is the primary content area with more space:

- Perfect for detailed explanations
- Code examples that need more width
- Main narrative or story
- Primary visual elements

The wider column draws more attention and is ideal for the most important content on your slide.

|||

### Sidebar (30%)

**Notes**:

- Key points
- Quick refs
- Links
- Tips

Short, concise supporting information.
:::

---

## Custom Width Example: 60/40 Code Review

:::columns[60]
### Implementation

```python
class DataProcessor:
def __init__(self, data):
self.data = data
self.results = []

def process(self):
for item in self.data:
result = self.transform(item)
self.results.append(result)
return self.results

def transform(self, item):
return item.upper()
```

|||

### Review Notes

**Strengths**:
- Clear structure
- Good naming
- Simple logic

**Suggestions**:
- Add type hints
- Handle errors
- Add docstrings
- Use list comprehension

**Performance**: O(n) time complexity
:::

---

## Custom Width Example: 30/70 Narrow Left

:::columns[30]
### Quick Stats

**Users**: 10K+

**Uptime**: 99.9%

**Response**: <100ms

**Rating**: ⭐⭐⭐⭐⭐

|||

### Detailed Analysis

Our platform has grown significantly over the past year, achieving remarkable metrics:

- **User Growth**: From 1,000 to over 10,000 active users
- **Reliability**: Maintained 99.9% uptime with zero critical incidents
- **Performance**: Average API response time under 100ms
- **Satisfaction**: Consistent 5-star ratings across all review platforms

The success is attributed to our focus on performance, reliability, and user experience. We continue to invest in infrastructure and optimization.
:::

---

## Performance

MarkDeck is designed to be:
Expand Down
2 changes: 1 addition & 1 deletion markdeck/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""MarkDeck - A lightweight markdown presentation tool."""

__version__ = "0.5.0"
__version__ = "0.6.0"
31 changes: 27 additions & 4 deletions markdeck/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ def _transform_columns(self) -> None:
Right content
:::

Or with percentage width:
:::columns[60]
Left content (60% width)
|||
Right content (40% width)
:::

Into special markers that the frontend will process:
<!-- COLUMN:LEFT:START -->
Left content (markdown)
Expand All @@ -80,6 +87,14 @@ def _transform_columns(self) -> None:
Right content (markdown)
<!-- COLUMN:RIGHT:END -->

Or with width:
<!-- COLUMN:LEFT:START:60 -->
Left content (markdown)
<!-- COLUMN:LEFT:END -->
<!-- COLUMN:RIGHT:START -->
Right content (markdown)
<!-- COLUMN:RIGHT:END -->

The frontend (slides.js) will find these markers and render the markdown
in each column, allowing mermaid diagrams and other features to work.

Expand All @@ -99,11 +114,13 @@ def save_code_block(match):
code_block_pattern, save_code_block, self.content, flags=re.DOTALL
)

# Pattern to match column blocks (more forgiving with whitespace)
column_pattern = r":::columns\s*\n(.*?)\s*\n:::"
# Pattern to match column blocks with optional width percentage
# Matches: :::columns or :::columns[60]
column_pattern = r":::columns(?:\[(\d+)\])?\s*\n(.*?)\s*\n:::"

def replace_columns(match):
content = match.group(1)
width_percent = match.group(1) # Can be None if no width specified
content = match.group(2)
# Split on ||| separator (more forgiving with whitespace)
parts = re.split(r"\s*\|\|\|\s*", content, maxsplit=1)

Expand All @@ -112,9 +129,15 @@ def replace_columns(match):
right_content = parts[1].strip()

# Create marker structure that preserves markdown
# Include width in left column marker if specified
if width_percent:
left_start_marker = f"<!-- COLUMN:LEFT:START:{width_percent} -->"
else:
left_start_marker = "<!-- COLUMN:LEFT:START -->"

# The frontend will process these markers after marked.js runs
return (
"<!-- COLUMN:LEFT:START -->\n"
f"{left_start_marker}\n"
f"{left_content}\n"
"<!-- COLUMN:LEFT:END -->\n"
"<!-- COLUMN:RIGHT:START -->\n"
Expand Down
25 changes: 20 additions & 5 deletions markdeck/static/slides.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,16 +263,21 @@ class SlideShow {
processColumnMarkers(markdown) {
// Find and process column markers created by the parser
// This must be called BEFORE marked.parse() to preserve the markdown
const leftStart = '<!-- COLUMN:LEFT:START -->';
const leftStartPattern = /<!-- COLUMN:LEFT:START(?::(\d+))? -->/;
const leftEnd = '<!-- COLUMN:LEFT:END -->';
const rightStart = '<!-- COLUMN:RIGHT:START -->';
const rightEnd = '<!-- COLUMN:RIGHT:END -->';

// Check if this slide has column markers
if (!markdown.includes(leftStart)) {
const leftStartMatch = markdown.match(leftStartPattern);
if (!leftStartMatch) {
return null; // No columns, caller should parse normally
}

// Extract width percentage if present (e.g., "60" from <!-- COLUMN:LEFT:START:60 -->)
const leftWidthPercent = leftStartMatch[1] ? parseInt(leftStartMatch[1], 10) : null;
const leftStart = leftStartMatch[0];

// Extract left column markdown (before marked.parse)
const leftStartIdx = markdown.indexOf(leftStart);
const leftEndIdx = markdown.indexOf(leftEnd);
Expand All @@ -294,11 +299,21 @@ class SlideShow {
const leftHtml = marked.parse(leftMarkdown);
const rightHtml = marked.parse(rightMarkdown);

// Create the two-column HTML structure
// Apply width styles if specified
let leftStyle = '';
let rightStyle = '';
if (leftWidthPercent !== null) {
// Validate width is between 1 and 99
const validWidth = Math.max(1, Math.min(99, leftWidthPercent));
leftStyle = ` style="flex: 0 0 ${validWidth}%;"`;
rightStyle = ` style="flex: 1;"`;
}

// Create the two-column HTML structure with optional width styles
const columnsHtml = `
<div class="columns-container">
<div class="column-left">${leftHtml}</div>
<div class="column-right">${rightHtml}</div>
<div class="column-left"${leftStyle}>${leftHtml}</div>
<div class="column-right"${rightStyle}>${rightHtml}</div>
</div>
`;

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "markdeck"
version = "0.5.0"
version = "0.6.0"
description = "A lightweight markdown presentation tool"
readme = "README.md"
requires-python = ">=3.11"
Expand Down
Binary file added screenshots/column_width_30_70.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/column_width_70_30.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading