Fix bin/publish: use correct .env path for rspade_system Fix bin/publish script: prevent grep exit code 1 from terminating script 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
289 lines
5.1 KiB
Markdown
Executable File
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>© <%= 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 `$id` for component-scoped element IDs:
|
|
|
|
```jqhtml
|
|
<div $id="content">
|
|
<!-- Becomes id="content:abc123" where abc123 is the component's _cid -->
|
|
</div>
|
|
```
|
|
|
|
Access in component:
|
|
|
|
```javascript
|
|
this.$id('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 |