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>
This commit is contained in:
root
2025-11-21 04:35:01 +00:00
parent 081fc0b88e
commit 78553d4edf
899 changed files with 8887 additions and 7868 deletions

View File

@@ -177,15 +177,15 @@ JQHTML uses the `$` prefix as a shorthand for data attributes with special handl
2. For debugging visibility, if the value is a string or number, it's also set as a DOM attribute
3. Objects and arrays are stored in `.data()` but not visible in DOM
#### Special Case: `$id="name"` → Scoped IDs
#### Special Case: `$sid="name"` → Scoped IDs
The `$id` attribute has special handling for component-scoped element selection:
The `$sid` attribute has special handling for component-scoped element selection:
```jqhtml
<Define:UserCard>
<div $id="container">
<input $id="username" type="text" />
<button $id="submit">Submit</button>
<div $sid="container">
<input $sid="username" type="text" />
<button $sid="submit">Submit</button>
</div>
</Define:UserCard>
```
@@ -207,8 +207,8 @@ function render(_cid) {
class UserCard extends Component {
init() {
// Find scoped elements
const $username = this.$id('username'); // Returns $('#username:123')
const $submit = this.$id('submit'); // Returns $('#submit:123')
const $username = this.$sid('username'); // Returns $('#username:123')
const $submit = this.$sid('submit'); // Returns $('#submit:123')
$submit.on('click', () => {
const value = $username.val();
@@ -224,15 +224,15 @@ Component IDs flow through lexical scope naturally:
```jqhtml
<Define:ParentComponent>
<div $id="parent-element"> <!-- Gets ParentComponent's _cid -->
<div $sid="parent-element"> <!-- Gets ParentComponent's _cid -->
<ChildComponent>
<div $id="slot-element" /> <!-- Also gets ParentComponent's _cid -->
<div $sid="slot-element" /> <!-- Also gets ParentComponent's _cid -->
</ChildComponent>
</div>
</Define:ParentComponent>
<Define:ChildComponent>
<div $id="child-element"> <!-- Gets ChildComponent's _cid -->
<div $sid="child-element"> <!-- Gets ChildComponent's _cid -->
<%= content() %> <!-- Slot content preserves parent's _cid -->
</div>
</Define:ChildComponent>
@@ -374,9 +374,9 @@ The `@` prefix binds event handlers:
<!-- Wrapper that adds behavior to innerHTML -->
<Define:Collapsible>
<div class="collapsible" $id="wrapper">
<div class="collapsible" $sid="wrapper">
<button $onclick="toggle">Toggle</button>
<div class="content" $id="content">
<div class="content" $sid="content">
<%= content() %> <!-- Wrapped innerHTML -->
</div>
</div>
@@ -481,7 +481,7 @@ Templates compile to three instruction types:
{tag: ["div", {"class": "user-card"}, false]}
{tag: ["img", {"src": "/avatar.jpg", "alt": "User"}, true]}
{tag: ["button", {"onclick": this.handleClick}, false]}
{tag: ["div", {"data-id": "header"}, false]} // $id becomes data-id
{tag: ["div", {"data-sid": "header"}, false]} // $id becomes data-id
```
### 2. Component Instruction

View File

@@ -390,7 +390,7 @@ These patterns inform v2 implementation decisions, particularly around maintaini
- **Expressions**: `<%= expression %>` for output
- **Bindings**: `:text`, `:value`, `:class`, `:style` for data binding
- **Events**: `@click`, `@change`, etc. for event handlers
- **Scoped IDs**: `$id` attribute for component-scoped IDs
- **Scoped IDs**: `$sid` attribute for component-scoped IDs
### Instruction Format

0
node_modules/@jqhtml/parser/dist/ast.d.ts generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/ast.d.ts.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/ast.js generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/ast.js.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/codegen.d.ts generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/codegen.d.ts.map generated vendored Executable file → Normal file
View File

22
node_modules/@jqhtml/parser/dist/codegen.js generated vendored Executable file → Normal file
View File

@@ -1042,14 +1042,14 @@ export class CodeGenerator {
const entries = Object.entries(attrs).flatMap(([key, value]) => {
// Convert 'tag' to '_tag' for component invocations
const attrKey = key === 'tag' ? '_tag' : key;
// Special handling for data-id attribute (from $id) - create scoped id
// NOTE: Parser converts $id="foo" → data-id="foo" so we can distinguish from regular id
// This generates: id="foo:PARENT_CID" data-id="foo"
// Special handling for data-sid attribute (from $sid) - create scoped id
// NOTE: Parser converts $sid="foo" → data-sid="foo" so we can distinguish from regular id
// This generates: id="foo:PARENT_CID" data-sid="foo"
// The :PARENT_CID scoping happens at runtime in instruction-processor.ts
if (key === 'data-id') {
if (key === 'data-sid') {
const id_entries = [];
if (value && typeof value === 'object' && value.interpolated) {
// Interpolated $id like $id="user<%= index %>"
// Interpolated $sid like $sid="user<%= index %>"
const parts = value.parts.map((part) => {
if (part.type === 'text') {
return this.escape_string(part.value);
@@ -1060,19 +1060,19 @@ export class CodeGenerator {
});
const base_id = parts.join(' + ');
id_entries.push(`"id": ${base_id} + ":" + this._cid`);
id_entries.push(`"data-id": ${base_id}`);
id_entries.push(`"data-sid": ${base_id}`);
}
else if (value && typeof value === 'object' && value.quoted) {
// Quoted $id like $id="static"
// Quoted $sid like $sid="static"
const base_id = this.escape_string(value.value);
id_entries.push(`"id": ${base_id} + ":" + this._cid`);
id_entries.push(`"data-id": ${base_id}`);
id_entries.push(`"data-sid": ${base_id}`);
}
else {
// Simple $id like $id="username" or expression like $id=someVar
// Simple $sid like $sid="username" or expression like $sid=someVar
const base_id = this.escape_string(String(value));
id_entries.push(`"id": ${base_id} + ":" + this._cid`);
id_entries.push(`"data-id": ${base_id}`);
id_entries.push(`"data-sid": ${base_id}`);
}
return id_entries;
}
@@ -1348,7 +1348,7 @@ export class CodeGenerator {
for (const [name, component] of this.components) {
code += `// Component: ${name}\n`;
code += `jqhtml_components.set('${name}', {\n`;
code += ` _jqhtml_version: '2.2.217',\n`; // Version will be replaced during build
code += ` _jqhtml_version: '2.2.218',\n`; // Version will be replaced during build
code += ` name: '${name}',\n`;
code += ` tag: '${component.tagName}',\n`;
code += ` defaultAttributes: ${this.serializeAttributeObject(component.defaultAttributes)},\n`;

2
node_modules/@jqhtml/parser/dist/codegen.js.map generated vendored Executable file → Normal file

File diff suppressed because one or more lines are too long

0
node_modules/@jqhtml/parser/dist/compiler.d.ts generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/compiler.d.ts.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/compiler.js generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/compiler.js.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/errors.d.ts generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/errors.d.ts.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/errors.js generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/errors.js.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/index.d.ts generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/index.d.ts.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/index.js generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/index.js.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/integration.d.ts generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/integration.d.ts.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/integration.js generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/integration.js.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/lexer.d.ts generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/lexer.d.ts.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/lexer.js generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/lexer.js.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/parser.d.ts generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/parser.d.ts.map generated vendored Executable file → Normal file
View File

14
node_modules/@jqhtml/parser/dist/parser.js generated vendored Executable file → Normal file
View File

@@ -109,9 +109,9 @@ export class Parser {
}
while (!this.check(TokenType.GT) && !this.is_at_end()) {
const attr_name = this.consume(TokenType.ATTR_NAME, 'Expected attribute name');
// Validate that $id is not used in Define tags
if (attr_name.value === '$id') {
throw syntaxError('$id is not allowed in <Define:> tags. Component definitions cannot have scoped IDs.', attr_name.line, attr_name.column, this.source, this.filename);
// Validate that $sid is not used in Define tags
if (attr_name.value === '$sid') {
throw syntaxError('$sid is not allowed in <Define:> tags. Component definitions cannot have scoped IDs.', attr_name.line, attr_name.column, this.source, this.filename);
}
this.consume(TokenType.EQUALS, 'Expected =');
const attr_value = this.parse_attribute_value();
@@ -535,10 +535,10 @@ export class Parser {
}
// Handle special attribute prefixes
if (name.startsWith('$')) {
// Special case: $id becomes data-id (needed for scoped ID system)
// Special case: $sid becomes data-sid (needed for scoped ID system)
// All other $ attributes stay as-is (handled by instruction-processor.ts)
if (name === '$id') {
name = 'data-id';
if (name === '$sid') {
name = 'data-sid';
}
// Keep $ prefix for other attributes - they get stored via .data() at runtime
// Keep the value object intact to preserve quoted/unquoted distinction
@@ -781,7 +781,7 @@ export class Parser {
' Or set attributes in on_ready() using jQuery:\n' +
' ✅ <tag $id="my_element">\n' +
' on_ready() {\n' +
' if (this.args.required) this.$id(\'my_element\').attr(\'required\', true);\n' +
' if (this.args.required) this.$sid(\'my_element\').attr(\'required\', true);\n' +
' }';
throw error;
}

2
node_modules/@jqhtml/parser/dist/parser.js.map generated vendored Executable file → Normal file

File diff suppressed because one or more lines are too long

0
node_modules/@jqhtml/parser/dist/runtime.d.ts generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/runtime.d.ts.map generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/runtime.js generated vendored Executable file → Normal file
View File

0
node_modules/@jqhtml/parser/dist/runtime.js.map generated vendored Executable file → Normal file
View File

2
node_modules/@jqhtml/parser/package.json generated vendored Executable file → Normal file
View File

@@ -1,6 +1,6 @@
{
"name": "@jqhtml/parser",
"version": "2.2.217",
"version": "2.2.218",
"description": "JQHTML template parser - converts templates to JavaScript",
"type": "module",
"main": "dist/index.js",