0
# Command-Line Tools
1
2
Specialized CLI utilities for site setup, content import, theme management, and plugin operations. These tools provide convenient interfaces for common Pelican workflow tasks.
3
4
## Capabilities
5
6
### pelican-quickstart
7
8
Interactive site setup tool that creates initial project structure, configuration files, and basic content templates.
9
10
```python { .api }
11
def main() -> None:
12
"""
13
Main entry point for pelican-quickstart command.
14
15
Provides interactive prompts for:
16
- Site title and author information
17
- URL structure and paths
18
- Timezone and language settings
19
- Theme selection
20
- Plugin preferences
21
- Makefile and automation setup
22
"""
23
```
24
25
**Command usage:**
26
```bash
27
pelican-quickstart
28
```
29
30
**Features:**
31
- Interactive setup wizard with sensible defaults
32
- Creates project directory structure
33
- Generates `pelicanconf.py` configuration file
34
- Creates `publishconf.py` for production settings
35
- Optional Makefile and Fabric scripts for automation
36
- Sample content creation
37
38
### pelican-import
39
40
Content import utility supporting multiple blog platforms and formats for migrating existing content to Pelican.
41
42
```python { .api }
43
def main() -> None:
44
"""
45
Main entry point for pelican-import command.
46
47
Supports importing from:
48
- WordPress XML exports
49
- Blogger XML exports
50
- Tumblr API
51
- Medium posts
52
- RSS/Atom feeds
53
- Dotclear exports
54
- Posterous backups
55
"""
56
```
57
58
**Command usage:**
59
```bash
60
# WordPress import
61
pelican-import --wordpress wordpress-export.xml -o content/
62
63
# Blogger import
64
pelican-import --blogger blogger-export.xml -o content/
65
66
# RSS feed import
67
pelican-import --feed https://example.com/feed.xml -o content/
68
69
# Tumblr import (requires API key)
70
pelican-import --tumblr myblog.tumblr.com -o content/
71
```
72
73
**Import Features:**
74
- Automatic metadata extraction and conversion
75
- Image and media file downloading
76
- Tag and category mapping
77
- Content format conversion (HTML to Markdown optional)
78
- Duplicate detection and handling
79
- Custom field preservation
80
81
### pelican-themes
82
83
Theme management utility for installing, removing, and listing Pelican themes.
84
85
```python { .api }
86
def main() -> None:
87
"""
88
Main entry point for pelican-themes command.
89
90
Operations:
91
- Install themes from local directories or Git repositories
92
- Remove installed themes
93
- List available and installed themes
94
- Symlink themes for development
95
- Theme validation and compatibility checking
96
"""
97
```
98
99
**Command usage:**
100
```bash
101
# Install theme from directory
102
pelican-themes --install path/to/theme/
103
104
# Install theme from Git repository
105
pelican-themes --install https://github.com/user/theme.git
106
107
# Install and symlink for development
108
pelican-themes --install --symlink path/to/theme/
109
110
# List installed themes
111
pelican-themes --list
112
113
# Remove theme
114
pelican-themes --remove theme-name
115
116
# Get theme information
117
pelican-themes --info theme-name
118
```
119
120
**Theme Operations:**
121
- Theme validation and dependency checking
122
- Automatic theme asset handling
123
- Theme metadata extraction
124
- Conflict resolution
125
- Development symlink support
126
127
### pelican-plugins
128
129
Plugin discovery and management utility for listing available plugins and their information.
130
131
```python { .api }
132
def list_plugins() -> None:
133
"""
134
Main entry point for pelican-plugins command.
135
136
Features:
137
- List all available plugins in plugin paths
138
- Show plugin metadata and descriptions
139
- Display plugin dependencies and requirements
140
- Plugin status and compatibility information
141
"""
142
```
143
144
**Command usage:**
145
```bash
146
# List all available plugins
147
pelican-plugins
148
149
# Show detailed plugin information
150
pelican-plugins --info
151
152
# List plugins in specific path
153
pelican-plugins --path custom/plugins/
154
```
155
156
## CLI Tool Configuration
157
158
### Import Tool Settings
159
160
Configure import behavior in settings or via command-line options:
161
162
```python
163
# Import-specific settings
164
IMPORT_WORDPRESS_POSTS_ONLY = False # Import pages as well as posts
165
IMPORT_CLEAN_HTML = True # Clean imported HTML
166
IMPORT_MARKDOWN_EXTENSION = '.md' # Extension for converted Markdown
167
IMPORT_PRESERVE_METADATA = True # Preserve custom metadata fields
168
```
169
170
### Theme Tool Settings
171
172
Configure theme installation and management:
173
174
```python
175
# Theme-specific settings
176
THEME_STATIC_DIR = 'theme' # Theme static files directory
177
THEME_STATIC_PATHS = ['static'] # Theme static source directories
178
THEME_TEMPLATES_OVERRIDES = [] # Template override directories
179
```
180
181
## Usage Examples
182
183
### Automated Site Setup
184
185
```bash
186
#!/bin/bash
187
# Automated Pelican site setup script
188
189
# Create project directory
190
mkdir my-blog
191
cd my-blog
192
193
# Run quickstart with predefined answers
194
echo -e "My Blog\nJohn Doe\nen\nAmerica/New_York\nhttps://myblog.com\ny\ny\nn\ny" | pelican-quickstart
195
196
# Install a theme
197
pelican-themes --install https://github.com/getpelican/pelican-themes.git
198
199
# Create first post
200
mkdir -p content
201
cat > content/first-post.md << EOF
202
Title: My First Post
203
Date: $(date +%Y-%m-%d)
204
Category: General
205
206
This is my first post using Pelican!
207
EOF
208
209
# Generate site
210
make html
211
```
212
213
### WordPress Migration Workflow
214
215
```bash
216
#!/bin/bash
217
# WordPress to Pelican migration script
218
219
# 1. Export WordPress content (done manually from WordPress admin)
220
# 2. Import content
221
pelican-import --wordpress wordpress-export.xml -o content/ --dir-cat
222
223
# 3. Convert HTML to Markdown (optional)
224
find content/ -name "*.html" -exec pandoc {} -f html -t markdown -o {}.md \;
225
find content/ -name "*.html" -delete
226
find content/ -name "*.md" -exec rename 's/\.html\.md$/.md/' {} \;
227
228
# 4. Download and organize images
229
python << EOF
230
import os
231
import re
232
import requests
233
from pathlib import Path
234
235
# Process all content files
236
for md_file in Path('content').glob('**/*.md'):
237
content = md_file.read_text()
238
239
# Find image URLs
240
img_urls = re.findall(r'!\[.*?\]\((https?://[^)]+)\)', content)
241
242
for url in img_urls:
243
# Download image
244
img_name = os.path.basename(url.split('?')[0])
245
img_path = Path('content/images') / img_name
246
img_path.parent.mkdir(exist_ok=True)
247
248
response = requests.get(url)
249
img_path.write_bytes(response.content)
250
251
# Update content with local path
252
content = content.replace(url, f'/images/{img_name}')
253
254
md_file.write_text(content)
255
EOF
256
257
# 5. Generate site
258
pelican content
259
```
260
261
### Theme Development Workflow
262
263
```bash
264
#!/bin/bash
265
# Theme development and testing workflow
266
267
# Create theme directory
268
mkdir -p themes/my-theme/templates
269
mkdir -p themes/my-theme/static/css
270
271
# Create basic theme files
272
cat > themes/my-theme/templates/base.html << EOF
273
<!DOCTYPE html>
274
<html>
275
<head>
276
<title>{{ SITENAME }}</title>
277
<link rel="stylesheet" href="{{ SITEURL }}/{{ THEME_STATIC_URL }}/css/style.css">
278
</head>
279
<body>
280
{% block content %}{% endblock %}
281
</body>
282
</html>
283
EOF
284
285
# Install theme for development (symlinked)
286
pelican-themes --install --symlink themes/my-theme/
287
288
# Test theme with sample content
289
pelican content -t my-theme -o output-test/
290
291
# Serve for testing
292
cd output-test
293
python -m http.server 8000
294
```
295
296
### Plugin Management Script
297
298
```python
299
#!/usr/bin/env python3
300
"""Plugin management helper script."""
301
302
import subprocess
303
import sys
304
from pathlib import Path
305
306
def list_available_plugins():
307
"""List all available plugins."""
308
result = subprocess.run(['pelican-plugins'], capture_output=True, text=True)
309
return result.stdout.split('\n')
310
311
def install_recommended_plugins():
312
"""Install commonly used plugins."""
313
recommended = [
314
'https://github.com/getpelican/pelican-plugins.git',
315
]
316
317
plugins_dir = Path('plugins')
318
plugins_dir.mkdir(exist_ok=True)
319
320
for plugin_repo in recommended:
321
plugin_name = plugin_repo.split('/')[-1].replace('.git', '')
322
plugin_path = plugins_dir / plugin_name
323
324
if not plugin_path.exists():
325
subprocess.run(['git', 'clone', plugin_repo, str(plugin_path)])
326
print(f"Installed plugin: {plugin_name}")
327
else:
328
print(f"Plugin already exists: {plugin_name}")
329
330
def update_plugins():
331
"""Update all git-based plugins."""
332
plugins_dir = Path('plugins')
333
334
for plugin_path in plugins_dir.iterdir():
335
if plugin_path.is_dir() and (plugin_path / '.git').exists():
336
print(f"Updating {plugin_path.name}...")
337
subprocess.run(['git', 'pull'], cwd=plugin_path)
338
339
if __name__ == '__main__':
340
if len(sys.argv) < 2:
341
print("Usage: plugin-manager.py [list|install|update]")
342
sys.exit(1)
343
344
command = sys.argv[1]
345
346
if command == 'list':
347
plugins = list_available_plugins()
348
for plugin in plugins:
349
if plugin.strip():
350
print(plugin)
351
elif command == 'install':
352
install_recommended_plugins()
353
elif command == 'update':
354
update_plugins()
355
else:
356
print(f"Unknown command: {command}")
357
sys.exit(1)
358
```
359
360
### Content Import Automation
361
362
```python
363
#!/usr/bin/env python3
364
"""Automated content import with processing."""
365
366
import subprocess
367
import sys
368
import re
369
from pathlib import Path
370
from datetime import datetime
371
372
def import_content(source_type, source_path, output_dir='content'):
373
"""Import content using pelican-import."""
374
cmd = ['pelican-import', f'--{source_type}', source_path, '-o', output_dir]
375
376
if source_type == 'wordpress':
377
cmd.extend(['--dir-cat', '--strip-raw'])
378
379
result = subprocess.run(cmd, capture_output=True, text=True)
380
381
if result.returncode == 0:
382
print(f"Successfully imported {source_type} content")
383
return True
384
else:
385
print(f"Import failed: {result.stderr}")
386
return False
387
388
def post_process_content(content_dir='content'):
389
"""Post-process imported content."""
390
content_path = Path(content_dir)
391
392
for md_file in content_path.glob('**/*.md'):
393
content = md_file.read_text()
394
modified = False
395
396
# Fix common import issues
397
# 1. Clean up WordPress shortcodes
398
content = re.sub(r'\[caption[^\]]*\](.*?)\[/caption\]', r'\1', content, flags=re.DOTALL)
399
content = re.sub(r'\[gallery[^\]]*\]', '', content)
400
401
# 2. Fix image references
402
content = re.sub(r'!\[\]\(([^)]+)\)', r'', content)
403
404
# 3. Clean up extra whitespace
405
content = re.sub(r'\n\s*\n\s*\n', '\n\n', content)
406
407
# 4. Ensure proper metadata formatting
408
lines = content.split('\n')
409
if lines and not lines[0].startswith(('Title:', 'Date:')):
410
# Add basic metadata if missing
411
title = md_file.stem.replace('-', ' ').title()
412
date = datetime.now().strftime('%Y-%m-%d')
413
metadata = f"Title: {title}\nDate: {date}\n\n"
414
content = metadata + content
415
modified = True
416
417
if modified:
418
md_file.write_text(content)
419
print(f"Post-processed: {md_file}")
420
421
if __name__ == '__main__':
422
if len(sys.argv) < 3:
423
print("Usage: import-content.py <source_type> <source_path>")
424
print("Example: import-content.py wordpress export.xml")
425
sys.exit(1)
426
427
source_type = sys.argv[1]
428
source_path = sys.argv[2]
429
430
# Import content
431
success = import_content(source_type, source_path)
432
433
if success:
434
# Post-process content
435
post_process_content()
436
print("Content import and processing complete!")
437
else:
438
print("Content import failed!")
439
sys.exit(1)
440
```