This document describes the modern JavaScript packages and features added to Jekyll.js to enhance functionality while maintaining backward compatibility with Jekyll (Ruby).
Jekyll.js leverages modern JavaScript packages to provide enhanced functionality:
- Syntax Highlighting with Shiki - Modern, fast, VSCode-powered syntax highlighting
- Image Optimization with Sharp - High-performance image processing and optimization
- Configuration Validation with Zod - Runtime type validation with TypeScript-first schemas
- HTML Minification - Reduce HTML file sizes for faster page loads
- Resource Hints - Preload/prefetch for optimized resource loading
All features are opt-in and do not affect existing Jekyll sites unless explicitly enabled in configuration.
Shiki is a modern syntax highlighter powered by the same engine as VS Code (TextMate grammars).
- Accurate, beautiful syntax highlighting
- 100+ languages supported out of the box
- Multiple themes available
- Zero runtime dependencies (pre-generated HTML)
- Perfect color accuracy
import { highlightCode, initHighlighter } from 'jekyll-ts/plugins/syntax-highlighting';
// Initialize once (optional - will auto-initialize on first use)
await initHighlighter({
theme: 'github-light',
});
// Highlight code
const html = await highlightCode(
'const x = 1;',
'javascript'
);Enable in _config.yml:
modern:
syntaxHighlighting:
enabled: true
theme: github-light
showLineNumbers: truegithub-light(default)github-darkmonokainordone-dark-prosolarized-lightsolarized-darkdraculamaterial-themevitesse-lightvitesse-dark
Over 100 languages including:
- JavaScript, TypeScript
- Python, Ruby, Go, Rust
- Java, C, C++, C#
- HTML, CSS, SCSS
- JSON, YAML, Markdown
- Bash, Shell, SQL
- And many more...
Sharp is a high-performance Node.js image processing library.
- Resize, crop, and transform images
- Convert between formats (JPEG, PNG, WebP, AVIF)
- Optimize file sizes
- Generate responsive images
- Extract metadata
import { optimizeImage } from 'jekyll-ts/plugins/image-optimization';
// Optimize an image
const result = await optimizeImage('input.jpg', 'output.jpg', {
quality: 80,
width: 1200,
generateWebP: true,
generateAVIF: true,
responsiveSizes: [400, 800, 1200],
});
console.log(`Reduced size by ${result.reduction}%`);Enable in _config.yml:
modern:
imageOptimization:
enabled: true
quality: 80
generateWebP: true
generateAVIF: true
responsiveSizes:
- 400
- 800
- 1200- JPEG (input and output)
- PNG (input and output)
- WebP (input and output)
- AVIF (input and output)
- GIF (input and output)
- TIFF (input and output)
- Smaller files: Reduce image sizes by 30-70%
- Modern formats: Automatic WebP/AVIF generation
- Responsive images: Generate multiple sizes automatically
- Fast processing: Uses native libraries for speed
Zod provides TypeScript-first schema validation for runtime type checking.
- Runtime type validation
- Type inference from schemas
- Detailed error messages
- Composable schemas
import { validateJekyllConfig, mergeAndValidateConfig } from 'jekyll-ts/config/validation';
// Validate a configuration
const result = validateJekyllConfig(config);
if (result.success) {
// result.data is typed and validated
console.log(result.data.title);
} else {
// result.errors contains detailed validation errors
console.error(result.errorMessage);
}- Type safety: Catch configuration errors at runtime
- Better errors: Clear, actionable error messages
- IntelliSense: Full TypeScript autocomplete support
- Validation: Ensure config values are valid (e.g., port numbers in range)
HTML minification reduces file sizes by removing unnecessary whitespace, comments, and optimizing markup.
- Remove HTML comments
- Collapse whitespace
- Minify inline CSS and JavaScript
- Collapse boolean attributes
- Remove empty attributes
- Preserve whitespace in pre/textarea elements
import { minifyHtml } from 'jekyll-ts/plugins/html-minifier';
const result = await minifyHtml(html, {
enabled: true,
removeComments: true,
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true,
});
console.log(`Reduced by ${result.reduction.toFixed(1)}%`);Enable in _config.yml:
modern:
htmlMinification:
enabled: true
removeComments: true
collapseWhitespace: true
minifyCSS: true
minifyJS: true
collapseBooleanAttributes: true
removeEmptyAttributes: true- Smaller files: Typically 10-30% size reduction
- Faster loads: Less data to transfer
- Cache efficiency: Smaller files improve caching
- Zero configuration: Sensible defaults
Resource hints tell browsers to fetch critical resources earlier, improving perceived page load performance.
- Preload: Load critical resources (CSS, fonts, hero images)
- Prefetch: Load likely next-page resources
- Preconnect: Establish early connections to important origins
- DNS Prefetch: Resolve DNS for external domains early
import { injectResourceHints } from 'jekyll-ts/plugins/resource-hints';
const html = injectResourceHints(originalHtml, {
enabled: true,
preloadStyles: true,
preloadFonts: true,
preconnectOrigins: ['https://fonts.googleapis.com'],
});Enable in _config.yml:
modern:
resourceHints:
enabled: true
preloadStyles: true
preloadFonts: true
preloadHeroImages: false
preconnectOrigins:
- https://fonts.googleapis.com
- https://fonts.gstatic.com
prefetchUrls:
- /about/
- /contact/
dnsPrefetchDomains:
- https://analytics.example.com- Faster page loads: Critical resources load earlier
- Better Core Web Vitals: Improved LCP and FID scores
- Automatic detection: Extracts stylesheets and fonts from HTML
- Common CDNs: Auto-detects popular CDN origins
All modern features:
- ✅ Are opt-in via configuration
- ✅ Do not affect existing Jekyll sites
- ✅ Maintain default behavior matching Jekyll (Ruby)
- ✅ Work alongside existing features
- ✅ Are fully tested and documented
Existing Jekyll sites continue to work without modification.
Modern packages are chosen for both functionality and performance:
- Shiki: Pre-generates HTML, zero runtime overhead
- Sharp: Native libraries, 4-5x faster than JavaScript alternatives
- Zod: Minimal runtime overhead, tree-shakeable
- HTML Minifier: Async processing, preserves content integrity
- Resource Hints: Zero runtime cost (static HTML injection)
The following modern packages are included:
{
"shiki": "^3.19.0", // Syntax highlighting
"sharp": "^0.34.5", // Image optimization
"zod": "^3.25.76", // Schema validation
"html-minifier-terser": "^7.2.0" // HTML minification
}All packages are:
- Well-maintained with active development
- Used by thousands of projects
- Battle-tested in production
- TypeScript-first with excellent type definitions
import { highlightCode } from 'jekyll-ts/plugins/syntax-highlighting';
async function renderCodeBlock(code: string, language: string) {
return await highlightCode(code, language, {
theme: 'github-dark',
});
}import { optimizeImage } from 'jekyll-ts/plugins/image-optimization';
import { glob } from 'glob';
async function optimizeAllImages() {
const images = await glob('assets/images/*.{jpg,png}');
for (const imagePath of images) {
await optimizeImage(imagePath, imagePath, {
quality: 85,
generateWebP: true,
});
}
}import { validateJekyllConfig } from 'jekyll-ts/config/validation';
const config = {
title: 'My Site',
port: 4000,
modern: {
syntaxHighlighting: {
enabled: true,
},
},
};
const result = validateJekyllConfig(config);
if (!result.success) {
console.error('Invalid config:', result.errorMessage);
process.exit(1);
}Jekyll.js includes several modern Liquid filters that enhance content processing while maintaining backwards compatibility:
Calculate estimated reading time for content:
{{ content | reading_time }}Returns the number of minutes to read the content (based on 200 words per minute by default):
Reading time: {{ page.content | reading_time }} minCustom words-per-minute:
{{ content | reading_time: 250 }}Generate a table of contents from HTML content:
{% assign toc = content | toc %}
<nav class="table-of-contents">
<ul>
{% for item in toc %}
<li class="toc-level-{{ item.level }}">
<a href="#{{ item.id }}">{{ item.text }}</a>
</li>
{% endfor %}
</ul>
</nav>Each TOC entry has:
level: Heading level (2-4)id: The heading's ID attribute (generated from text if not present)text: The heading text
Add anchor links to headings for easy linking:
{{ content | heading_anchors }}Transforms:
<h2>Getting Started</h2>Into:
<h2 id="getting-started">Getting Started <a href="#getting-started" class="anchor" aria-hidden="true">#</a></h2>Automatically add target="_blank" and rel="noopener noreferrer" to external links for security and UX:
{{ content | external_links }}Internal links (same domain) are left unchanged. External links get security attributes added.
Specify your site domain explicitly:
{{ content | external_links: "mysite.com" }}Truncate text to a specified number of words:
{{ content | truncate_words: 50 }}Custom ellipsis:
{{ content | truncate_words: 50, "..." }}Generate excerpts automatically:
{{ content | auto_excerpt }}This returns the first paragraph. For word-based excerpts:
{{ content | auto_excerpt: 100 }}Potential future additions:
- PDF generation with modern libraries
- Advanced markdown features (math, diagrams)
- Asset bundling and minification
- Modern image formats (JXL)
- Service worker generation
- Progressive web app features
- Shiki: https://shiki.matsu.io/
- Sharp: https://sharp.pixelplumbing.com/
- Zod: https://zod.dev/
To add new modern features:
- Choose well-maintained, popular packages
- Ensure TypeScript support
- Make features opt-in via configuration
- Maintain backward compatibility
- Add comprehensive tests
- Document usage and benefits
For questions or issues related to modern features:
- Open an issue on GitHub
- Include your configuration
- Provide reproduction steps
- Check documentation first
All modern features are part of Jekyll.js and follow the same MIT license.