Files
rspade_system/node_modules/@jqhtml/webpack-loader/README.md
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

5.1 KiB
Executable File

@jqhtml/webpack-loader

Webpack loader for JQHTML templates. Import .jqhtml files directly in your JavaScript!

Installation

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:

module.exports = {
  module: {
    rules: [
      {
        test: /\.jqhtml$/,
        use: '@jqhtml/webpack-loader'
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.jqhtml']
  }
};

Or use the configuration helper:

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:

<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

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

<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:

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:

<div $sid="content">
  <!-- Becomes id="content:abc123" where abc123 is the component's _cid -->
</div>

Access in component:

this.$sid('content') // Returns jQuery element

Advanced Configuration

Loader Options

{
  test: /\.jqhtml$/,
  use: {
    loader: '@jqhtml/webpack-loader',
    options: {
      sourceMap: true  // Enable source maps (default: true)
    }
  }
}

With TypeScript

Add type declarations for .jqhtml imports:

// 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:

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:

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:

resolve: {
  extensions: ['.js', '.jqhtml'],
  modules: ['node_modules', 'src']
}

jQuery Not Found

Ensure jQuery is available:

plugins: [
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery'
  })
]

Source Maps

For better debugging, ensure source maps are enabled:

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