Vite plugin for processing .morph files with @peter.naydenov/morph
npm install @peter.naydenov/vite-plugin-morph
!npm version
!npm license
!bundle size
!Morph compatibility
A Vite plugin for processing .morph files with HTML-like syntax, CSS modules, and JavaScript helpers. Built on top of @peter.naydenov/morph v3.3.0.
- π¨ HTML-like Syntax - Write components with familiar HTML/CSS/JS structure
- ποΈ CSS Layers Architecture - Complete CSS processing with @layer cascade, tree-shaking, and bundling
- π¦ CSS Modules - Automatic CSS scoping with unique class names
- β‘ PostCSS Processing - Autoprefixer, minification, and source maps
- π³ CSS Tree-Shaking - 30-70% bundle size reduction by removing unused CSS
- π¦ Advanced Bundling - CSS chunking, cache invalidation, and single optimized bundles
- π₯ CSS Hot Module Replacement - Instant style updates during development
- π Enhanced Error Reporting - File location tracking and detailed CSS error messages
- π§ CSS Debugging Tools - Rich inspection utilities and processing logs
- π οΈ TypeScript Support - Full type definitions included
- β‘ Vite Integration - Seamless Vite 4.x plugin API integration
- π Morph Syntax - Full support for @peter.naydenov/morph template syntax and helpers
- βοΈ Zero Config - Works out of the box with sensible defaults
- π― Production Optimized - Built-in optimizations for production builds
- π Library Mode - Build distributable component libraries with runtime CSS control
``bash`
npm install @peter.naydenov/vite-plugin-morph --save-dev
`javascript
// vite.config.js
import { defineConfig } from 'vite';
import morphPlugin from '@peter.naydenov/vite-plugin-morph';
export default defineConfig({
plugins: [morphPlugin()],
});
`
For the best development experience with .morph files, install the Morph Template Syntax Highlighter extension:
- Extension Name: PeterNaydenov.morph-template-syntax-highlighting
- Marketplace Link: https://marketplace.visualstudio.com/items?itemName=PeterNaydenov.morph-template-syntax-highlighting
Features:
- π¨ Full syntax highlighting for .morph files
- π¦ HTML-like template support
- π― JavaScript helper function highlighting
- π CSS style section support
- π JSON handshake data highlighting
- π§ Auto-completion for morph syntax
- π Error checking and validation
- π Dark/light theme support
This extension provides a professional editing experience with syntax highlighting, IntelliSense, and real-time error detection for your .morph files.
`html
`
`javascript
import Button, { styles } from './components/Button.morph';
// Render with custom data
const customButton = Button({
text: 'Save Changes',
variant: 'primary',
action: 'handleClick',
});
document.body.innerHTML = customButton;
// Access typed handshake data
console.log(handshake.text); // string
console.log(handshake.variant); // string
// Use typed CSS module classes
const className = styles.btn; // string
`
The plugin includes a comprehensive CSS processing system that transforms your component styles into a modern, scalable architecture.
Component styles are automatically scoped with unique class names to prevent conflicts:
`html
`
Generates scoped CSS:
`css`
.Button_btn_abc123 {
background: blue;
color: white;
}
Organize styles with predictable precedence using CSS layers:
`html`
Automatic vendor prefixing, minification, and source maps:
`javascript`
// vite.config.js
export default defineConfig({
plugins: [
morphPlugin({
css: {
postcss: {
autoprefixer: true,
minify: true,
sourceMaps: true,
},
},
}),
],
});
Automatically removes unused component CSS (30-70% bundle reduction):
`javascript
// Only imported components' CSS is included
import Button from './components/Button.morph';
// Button CSS included
// import Card from './components/Card.morph';
// Card CSS automatically excluded
`
Configure CSS chunking for large applications:
`javascript`
// vite.config.js
export default defineConfig({
plugins: [
morphPlugin({
css: {
chunking: {
enabled: true,
strategy: 'size', // 'size', 'category', 'manual'
maxChunkSize: 50 * 1024, // 50KB
},
outputDir: 'dist/components',
},
}),
],
});
Instant style updates during development - no page refresh needed:
`html`
Detailed error messages with file locations:
``
β CSS processing failed: Invalid CSS syntax
π Location: src/components/Button.morph:15:5
π Offset: 245
Rich inspection and logging tools:
`javascript
// Enable CSS debugging
import { enableCssDebugging } from '@peter.naydenov/vite-plugin-morph';
enableCssDebugging({ verbose: true });
// Inspect CSS processing
const inspector = debugUtils.createInspector(css, 'Button');
console.log(inspector.getRuleCount()); // Number of CSS rules
console.log(inspector.getScopedClasses()); // Scoped class names
`
The plugin includes full TypeScript definitions. Import morph files directly in TypeScript:
`typescript
// TypeScript usage
import Button, { styles, handshake } from './components/Button.morph';
// Type-safe component rendering
const buttonHtml = Button({
text: 'Submit',
variant: 'primary',
action: 'handleSubmit',
});
// Access typed handshake data
console.log(handshake.text); // string
console.log(handshake.variant); // string
// Use typed CSS module classes
const className = styles.btn; // string
`
A .morph file contains four main sections:
` {{ description }}html`
{{ title }}
{{ items : [], renderItem }}
`javascript`
`css`
`javascript`
`javascript`
// vite.config.js
export default defineConfig({
plugins: [
morphPlugin({
css: {
// PostCSS processing
postcss: {
autoprefixer: true,
minify: true,
sourceMaps: true,
},
// CSS chunking for large apps
chunking: {
enabled: true,
strategy: 'size', // 'size', 'category', 'manual'
maxChunkSize: 50 * 1024, // 50KB chunks
},
// Output configuration
outputDir: 'dist/components',
// CSS debugging
debug: {
enabled: true,
verbose: false,
showSourceMaps: true,
},
},
}),
],
});
`javascript`
// vite.config.js
export default defineConfig({
plugins: [
morphPlugin({
globalCSS: {
directory: 'src/styles',
include: ['*/.css'],
exclude: ['*/.min.css'],
},
}),
],
});
`javascript`
// vite.config.js
export default defineConfig({
plugins: [
morphPlugin({
production: {
removeHandshake: true,
minifyCSS: true,
},
}),
],
});
`javascript`
// vite.config.js
export default defineConfig({
plugins: [
morphPlugin({
development: {
sourceMaps: true,
hmr: true,
cssHmr: true, // Enable CSS hot reloading
},
hashMode: 'development', // Stable hash for CSS class names
}),
],
});
Hash Modes:
- 'development' (default): Stable hash based on component/class names. Class names don't change when CSS content changes - no template re-render needed.'production'
- : Content-based hash. Hash changes when CSS content changes - optimal for cache busting.
`javascript`
// vite.config.js
export default defineConfig({
plugins: [
morphPlugin({
errorHandling: {
failOnError: true,
showLocation: true,
maxErrors: 10,
cssErrors: true, // Enhanced CSS error reporting
},
}),
],
});
For global styles and design systems, create CSS-only morph files:
`html`
Create component-specific styles with proper layer organization:
` {{ content }}html
{{ title }}
`
Only CSS from imported components is included in the bundle:
`javascript
// src/main.js
import Button from './components/Button.morph'; // CSS included
import Card from './components/Card.morph'; // CSS included
// import Modal from './components/Modal.morph'; // CSS excluded (tree-shaken)
// import Form from './components/Form.morph'; // CSS excluded (tree-shaken)
// Result: Only Button and Card CSS in final bundle
// Bundle size reduced by ~60% compared to including all components
`
Use powerful template helpers for dynamic content:
` {{user.email}}html`
{{user.name}}
{{#if user.isAdmin}}
{{/if}} {{#each user.roles}}
{{this}}
{{/each}}
Define reusable helper functions:
`javascript`
Build distributable component libraries that work like Svelte - framework-free at runtime with full CSS control. CSS processing is delegated to host applications for maximum flexibility.
- Raw CSS Assets: All CSS files from src/styles/ are copied as raw assets without processing
- Host Processing: CSS layers, scoping, and optimization are handled by the host application's plugin configuration
- Runtime Control: Library consumers get full control over CSS architecture (themes, overrides, etc.)
1. Create build script (scripts/build-library.js):
`javascript
import { buildLibrary } from '@peter.naydenov/vite-plugin-morph';
await buildLibrary({
entry: 'src/main.js',
library: {
name: '@myorg/my-components',
version: '1.0.0',
},
});
`
2. Define library exports (src/main.js):
`javascript`
export { default as Button } from './components/Button.morph';
export {
applyStyles,
themesControl,
} from '@peter.naydenov/vite-plugin-morph/client';
3. Build: npm run build:lib
`javascript
import { Button, applyStyles, themesControl } from '@myorg/my-components';
// Host app processes CSS with its plugin configuration
applyStyles(); // Apply all CSS layers
document.body.innerHTML = Button('render', { text: 'Click me' });
themesControl.set('dark'); // Switch theme
`
Host Configuration Example:
`javascript`
// Host vite.config.js
export default defineConfig({
plugins: [
morphPlugin({
css: {
layers: { enabled: true },
postcss: { autoprefixer: true, minify: true },
},
}),
],
});
π Full documentation: See LIBRARY_MODE.md
- Node.js 16+
- Vite 4.x
- @peter.naydenov/morph v3.1.5
`bashInstall dependencies
npm install
$3
Enable CSS debugging for development:
`javascript
// src/main.js or vite.config.js
import { enableCssDebugging } from '@peter.naydenov/vite-plugin-morph';// Enable verbose CSS logging
enableCssDebugging({
verbose: true,
showSourceMaps: true,
});
// Now you'll see detailed CSS processing logs:
// π§ CSS Processing: Button
// π Original CSS: 245 chars
// π¨ Scoped CSS: 267 chars
// βοΈ Processed CSS: 189 chars (minified)
// π·οΈ Scoped Classes: 2
// πΊοΈ Source map generated for Button
`$3
Edit styles and see changes instantly:
`html
`No page refresh needed - styles update in real-time during development.
$3
The project includes comprehensive test coverage with 169 tests passing:
- 78.23% statement coverage
- 67.89% branch coverage
- 81.42% function coverage
- 78.15% line coverage
Run
npm run test:coverage to generate detailed HTML reports in ./coverage/.$3
`
src/
βββ core/ # Core processing logic
β βββ parser.js # HTML parsing and content extraction
β βββ processor.js # Main morph file processing pipeline
β βββ template.js # Template compilation and helpers
β βββ script.js # JavaScript helper processing
β βββ css-scoper.js # CSS scoping and class name generation
β βββ css-processor.js # PostCSS processing with autoprefixer/cssnano
β βββ themer.js # Theme processing and generation
β βββ composer.js # Component composition system
β βββ config-loader.js # Configuration loading
β βββ errors.js # Error handling and CSS error reporting
βββ plugin/ # Vite plugin integration
β βββ index.js # Main plugin factory and HMR
β βββ hooks.js # Transform and HMR hooks
β βββ config.js # Plugin configuration
βββ services/ # Advanced services
β βββ css-collection.js # CSS bundling and chunking
β βββ css-tree-shaker.js # CSS tree-shaking logic
β βββ css-generation.js # CSS processing and generation
β βββ theme-runtime.js # Theme management API
β βββ theme-discovery.js # Theme file discovery
βββ utils/ # Shared utilities
β βββ logger.js # Logging system
β βββ cache.js # Performance caching
β βββ css-debug.js # CSS debugging and inspection utilities
β βββ file-watcher.js # File watching for HMR
β βββ shared.js # Common utilities
βββ types/ # TypeScript type definitions
βββ index.js # Complete type definitions
`API Reference
$3
####
processMorphFile(content, filePath, options)Process a morph file and return compiled result.
Parameters:
-
content (string): Raw morph file content
- filePath (string): File path for error reporting
- options (MorphPluginOptions): Plugin configuration optionsReturns:
Promise####
isProductionMode(options)Check if running in production mode.
Parameters:
-
options (MorphPluginOptions): Plugin configurationReturns:
boolean$3
See
src/types/index.js for complete type definitions.$3
Import runtime functions for CSS management:
`javascript
import {
applyStyles,
themesControl,
registerComponentCSS,
getAllComponentCSS,
generateCombinedCSS,
updateComponentCSS,
detectEnvironment,
getMorphConfig,
setMorphConfig,
} from '@peter.naydenov/vite-plugin-morph/client';
`####
applyStyles()Applies CSS based on current environment:
- Development: Injects per-component