Static site generator supporting Markdown and reStructuredText
—
Specialized CLI utilities for site setup, content import, theme management, and plugin operations. These tools provide convenient interfaces for common Pelican workflow tasks.
Interactive site setup tool that creates initial project structure, configuration files, and basic content templates.
def main() -> None:
"""
Main entry point for pelican-quickstart command.
Provides interactive prompts for:
- Site title and author information
- URL structure and paths
- Timezone and language settings
- Theme selection
- Plugin preferences
- Makefile and automation setup
"""Command usage:
pelican-quickstartFeatures:
pelicanconf.py configuration filepublishconf.py for production settingsContent import utility supporting multiple blog platforms and formats for migrating existing content to Pelican.
def main() -> None:
"""
Main entry point for pelican-import command.
Supports importing from:
- WordPress XML exports
- Blogger XML exports
- Tumblr API
- Medium posts
- RSS/Atom feeds
- Dotclear exports
- Posterous backups
"""Command usage:
# WordPress import
pelican-import --wordpress wordpress-export.xml -o content/
# Blogger import
pelican-import --blogger blogger-export.xml -o content/
# RSS feed import
pelican-import --feed https://example.com/feed.xml -o content/
# Tumblr import (requires API key)
pelican-import --tumblr myblog.tumblr.com -o content/Import Features:
Theme management utility for installing, removing, and listing Pelican themes.
def main() -> None:
"""
Main entry point for pelican-themes command.
Operations:
- Install themes from local directories or Git repositories
- Remove installed themes
- List available and installed themes
- Symlink themes for development
- Theme validation and compatibility checking
"""Command usage:
# Install theme from directory
pelican-themes --install path/to/theme/
# Install theme from Git repository
pelican-themes --install https://github.com/user/theme.git
# Install and symlink for development
pelican-themes --install --symlink path/to/theme/
# List installed themes
pelican-themes --list
# Remove theme
pelican-themes --remove theme-name
# Get theme information
pelican-themes --info theme-nameTheme Operations:
Plugin discovery and management utility for listing available plugins and their information.
def list_plugins() -> None:
"""
Main entry point for pelican-plugins command.
Features:
- List all available plugins in plugin paths
- Show plugin metadata and descriptions
- Display plugin dependencies and requirements
- Plugin status and compatibility information
"""Command usage:
# List all available plugins
pelican-plugins
# Show detailed plugin information
pelican-plugins --info
# List plugins in specific path
pelican-plugins --path custom/plugins/Configure import behavior in settings or via command-line options:
# Import-specific settings
IMPORT_WORDPRESS_POSTS_ONLY = False # Import pages as well as posts
IMPORT_CLEAN_HTML = True # Clean imported HTML
IMPORT_MARKDOWN_EXTENSION = '.md' # Extension for converted Markdown
IMPORT_PRESERVE_METADATA = True # Preserve custom metadata fieldsConfigure theme installation and management:
# Theme-specific settings
THEME_STATIC_DIR = 'theme' # Theme static files directory
THEME_STATIC_PATHS = ['static'] # Theme static source directories
THEME_TEMPLATES_OVERRIDES = [] # Template override directories#!/bin/bash
# Automated Pelican site setup script
# Create project directory
mkdir my-blog
cd my-blog
# Run quickstart with predefined answers
echo -e "My Blog\nJohn Doe\nen\nAmerica/New_York\nhttps://myblog.com\ny\ny\nn\ny" | pelican-quickstart
# Install a theme
pelican-themes --install https://github.com/getpelican/pelican-themes.git
# Create first post
mkdir -p content
cat > content/first-post.md << EOF
Title: My First Post
Date: $(date +%Y-%m-%d)
Category: General
This is my first post using Pelican!
EOF
# Generate site
make html#!/bin/bash
# WordPress to Pelican migration script
# 1. Export WordPress content (done manually from WordPress admin)
# 2. Import content
pelican-import --wordpress wordpress-export.xml -o content/ --dir-cat
# 3. Convert HTML to Markdown (optional)
find content/ -name "*.html" -exec pandoc {} -f html -t markdown -o {}.md \;
find content/ -name "*.html" -delete
find content/ -name "*.md" -exec rename 's/\.html\.md$/.md/' {} \;
# 4. Download and organize images
python << EOF
import os
import re
import requests
from pathlib import Path
# Process all content files
for md_file in Path('content').glob('**/*.md'):
content = md_file.read_text()
# Find image URLs
img_urls = re.findall(r'!\[.*?\]\((https?://[^)]+)\)', content)
for url in img_urls:
# Download image
img_name = os.path.basename(url.split('?')[0])
img_path = Path('content/images') / img_name
img_path.parent.mkdir(exist_ok=True)
response = requests.get(url)
img_path.write_bytes(response.content)
# Update content with local path
content = content.replace(url, f'/images/{img_name}')
md_file.write_text(content)
EOF
# 5. Generate site
pelican content#!/bin/bash
# Theme development and testing workflow
# Create theme directory
mkdir -p themes/my-theme/templates
mkdir -p themes/my-theme/static/css
# Create basic theme files
cat > themes/my-theme/templates/base.html << EOF
<!DOCTYPE html>
<html>
<head>
<title>{{ SITENAME }}</title>
<link rel="stylesheet" href="{{ SITEURL }}/{{ THEME_STATIC_URL }}/css/style.css">
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
EOF
# Install theme for development (symlinked)
pelican-themes --install --symlink themes/my-theme/
# Test theme with sample content
pelican content -t my-theme -o output-test/
# Serve for testing
cd output-test
python -m http.server 8000#!/usr/bin/env python3
"""Plugin management helper script."""
import subprocess
import sys
from pathlib import Path
def list_available_plugins():
"""List all available plugins."""
result = subprocess.run(['pelican-plugins'], capture_output=True, text=True)
return result.stdout.split('\n')
def install_recommended_plugins():
"""Install commonly used plugins."""
recommended = [
'https://github.com/getpelican/pelican-plugins.git',
]
plugins_dir = Path('plugins')
plugins_dir.mkdir(exist_ok=True)
for plugin_repo in recommended:
plugin_name = plugin_repo.split('/')[-1].replace('.git', '')
plugin_path = plugins_dir / plugin_name
if not plugin_path.exists():
subprocess.run(['git', 'clone', plugin_repo, str(plugin_path)])
print(f"Installed plugin: {plugin_name}")
else:
print(f"Plugin already exists: {plugin_name}")
def update_plugins():
"""Update all git-based plugins."""
plugins_dir = Path('plugins')
for plugin_path in plugins_dir.iterdir():
if plugin_path.is_dir() and (plugin_path / '.git').exists():
print(f"Updating {plugin_path.name}...")
subprocess.run(['git', 'pull'], cwd=plugin_path)
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: plugin-manager.py [list|install|update]")
sys.exit(1)
command = sys.argv[1]
if command == 'list':
plugins = list_available_plugins()
for plugin in plugins:
if plugin.strip():
print(plugin)
elif command == 'install':
install_recommended_plugins()
elif command == 'update':
update_plugins()
else:
print(f"Unknown command: {command}")
sys.exit(1)#!/usr/bin/env python3
"""Automated content import with processing."""
import subprocess
import sys
import re
from pathlib import Path
from datetime import datetime
def import_content(source_type, source_path, output_dir='content'):
"""Import content using pelican-import."""
cmd = ['pelican-import', f'--{source_type}', source_path, '-o', output_dir]
if source_type == 'wordpress':
cmd.extend(['--dir-cat', '--strip-raw'])
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
print(f"Successfully imported {source_type} content")
return True
else:
print(f"Import failed: {result.stderr}")
return False
def post_process_content(content_dir='content'):
"""Post-process imported content."""
content_path = Path(content_dir)
for md_file in content_path.glob('**/*.md'):
content = md_file.read_text()
modified = False
# Fix common import issues
# 1. Clean up WordPress shortcodes
content = re.sub(r'\[caption[^\]]*\](.*?)\[/caption\]', r'\1', content, flags=re.DOTALL)
content = re.sub(r'\[gallery[^\]]*\]', '', content)
# 2. Fix image references
content = re.sub(r'!\[\]\(([^)]+)\)', r'', content)
# 3. Clean up extra whitespace
content = re.sub(r'\n\s*\n\s*\n', '\n\n', content)
# 4. Ensure proper metadata formatting
lines = content.split('\n')
if lines and not lines[0].startswith(('Title:', 'Date:')):
# Add basic metadata if missing
title = md_file.stem.replace('-', ' ').title()
date = datetime.now().strftime('%Y-%m-%d')
metadata = f"Title: {title}\nDate: {date}\n\n"
content = metadata + content
modified = True
if modified:
md_file.write_text(content)
print(f"Post-processed: {md_file}")
if __name__ == '__main__':
if len(sys.argv) < 3:
print("Usage: import-content.py <source_type> <source_path>")
print("Example: import-content.py wordpress export.xml")
sys.exit(1)
source_type = sys.argv[1]
source_path = sys.argv[2]
# Import content
success = import_content(source_type, source_path)
if success:
# Post-process content
post_process_content()
print("Content import and processing complete!")
else:
print("Content import failed!")
sys.exit(1)Install with Tessl CLI
npx tessl i tessl/pypi-pelican