Files
root 78553d4edf Fix code quality violations for publish
Remove unused blade settings pages not linked from UI
Convert remaining frontend pages to SPA actions
Convert settings user_settings and general to SPA actions
Convert settings profile pages to SPA actions
Convert contacts and projects add/edit pages to SPA actions
Convert clients add/edit page to SPA action with loading pattern
Refactor component scoped IDs from $id to $sid
Fix jqhtml comment syntax and implement universal error component system
Update all application code to use new unified error system
Remove all backwards compatibility - unified error system complete
Phase 5: Remove old response classes
Phase 3-4: Ajax response handler sends new format, old helpers deprecated
Phase 2: Add client-side unified error foundation
Phase 1: Add server-side unified error foundation
Add unified Ajax error response system with constants

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 04:35:01 +00:00

289 lines
5.1 KiB
Markdown
Executable File

# @jqhtml/webpack-loader
Webpack loader for JQHTML templates. Import `.jqhtml` files directly in your JavaScript!
## Installation
```bash
npm install --save-dev @jqhtml/webpack-loader webpack
npm install @jqhtml/core jquery
```
## Quick Start
### 1. Configure Webpack
Add the loader to your `webpack.config.js`:
```javascript
module.exports = {
module: {
rules: [
{
test: /\.jqhtml$/,
use: '@jqhtml/webpack-loader'
}
]
},
resolve: {
extensions: ['.js', '.jqhtml']
}
};
```
Or use the configuration helper:
```javascript
const { addJQHTMLSupport } = require('@jqhtml/webpack-loader');
module.exports = addJQHTMLSupport({
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
}
});
```
### 2. Create JQHTML Templates
Create `UserCard.jqhtml`:
```jqhtml
<Define:UserCard>
<div class="user-card">
<h2 :text="name"></h2>
<p :text="email"></p>
<button @click="handleClick">Contact</button>
<% if (this.data.showBio): %>
<div class="bio" :html="bio"></div>
<% endif; %>
</div>
</Define:UserCard>
```
### 3. Import and Use
```javascript
import UserCard from './UserCard.jqhtml';
import $ from 'jquery';
// Create component instance
const user = $('#user-container').component(UserCard, {
name: 'John Doe',
email: 'john@example.com'
});
// Set data
user.data = {
name: 'John Doe',
email: 'john@example.com',
showBio: true,
bio: '<p>Software developer</p>'
};
// Define methods
user.handleClick = function() {
console.log('Contact clicked!');
this.emit('contact', { user: this.data });
};
// Re-render to apply data
user.render();
```
## Features
### Multiple Components per File
```jqhtml
<Define:Header>
<header>
<h1><%= this.data.title %></h1>
</header>
</Define:Header>
<Define:Footer>
<footer>
<p>&copy; <%= this.data.year %></p>
</footer>
</Define:Footer>
```
Import all components:
```javascript
import { Header, Footer } from './Layout.jqhtml';
// Default export is the first component
import DefaultHeader from './Layout.jqhtml';
```
### Data Bindings
Use `:prop` syntax for reactive bindings:
- `:text="expression"` - Text content
- `:value="expression"` - Input values
- `:class="{active: isActive}"` - Dynamic classes
- `:style="{color: textColor}"` - Dynamic styles
- `:html="htmlContent"` - HTML content (use carefully)
### Event Handlers
Use `@event` syntax for event handling:
- `@click="methodName"` - Call component method
- `@change="updateValue"` - Form events
- `@submit="handleSubmit"` - Form submission
### Scoped IDs
Use `$sid` for component-scoped element IDs:
```jqhtml
<div $sid="content">
<!-- Becomes id="content:abc123" where abc123 is the component's _cid -->
</div>
```
Access in component:
```javascript
this.$sid('content') // Returns jQuery element
```
## Advanced Configuration
### Loader Options
```javascript
{
test: /\.jqhtml$/,
use: {
loader: '@jqhtml/webpack-loader',
options: {
sourceMap: true // Enable source maps (default: true)
}
}
}
```
### With TypeScript
Add type declarations for `.jqhtml` imports:
```typescript
// jqhtml.d.ts
declare module '*.jqhtml' {
import { Component } from '@jqhtml/core';
const component: typeof Component;
export default component;
// For multi-component files
export const Header: typeof Component;
export const Footer: typeof Component;
}
```
### Production Build
The loader automatically handles production optimizations:
```javascript
module.exports = {
mode: 'production',
module: {
rules: [
{
test: /\.jqhtml$/,
use: '@jqhtml/webpack-loader'
}
]
},
optimization: {
minimize: true
}
};
```
## How It Works
1. **Parse** - The loader uses `@jqhtml/parser` to parse templates
2. **Generate** - Converts templates to ES module code
3. **Export** - Each component becomes an ES6 class export
4. **Register** - Components are automatically registered globally
The generated code looks like:
```javascript
import { Component, render_template, register_component } from '@jqhtml/core';
export class UserCard extends Component {
static component_name = 'UserCard';
async on_render() {
const template_fn = function render() { /* ... */ };
await render_template(this, template_fn);
}
}
register_component('UserCard', UserCard);
export default UserCard;
```
## Troubleshooting
### Module Resolution
If webpack can't find `.jqhtml` files:
```javascript
resolve: {
extensions: ['.js', '.jqhtml'],
modules: ['node_modules', 'src']
}
```
### jQuery Not Found
Ensure jQuery is available:
```javascript
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
```
### Source Maps
For better debugging, ensure source maps are enabled:
```javascript
devtool: 'source-map',
module: {
rules: [{
test: /\.jqhtml$/,
use: {
loader: '@jqhtml/webpack-loader',
options: { sourceMap: true }
}
}]
}
```
## Examples
See the `/examples` directory for complete examples:
- Basic usage with vanilla JS
- TypeScript integration
- Multi-component layouts
- Complex data binding scenarios
## License
MIT